views:

1209

answers:

2

I am working on something that needed custom drag-and-drop functionality, so I have been subclassing View, doing a bunch of math in response to touch events, and then rendering everything manually through code on the canvas in onDraw. Now, the more functionality I add, the more the code is growing out of control and I find myself writing a ton more code than I would expect to write in a high level environment like Android.

Is this how it's done, or am I missing something? If I'm not doing anything fancy in the UI, the framework handles the majority of my interactions. Built-in controls handle the touches and drags, and my code is pretty much limited to business logic and data. Is there a way to leverage the power of some of the UI controls and things like animations while also doing some of it manually in the onDraw canvas? Is there an accepted standard of when to use one or the other (if indeed the two approaches can be mixed)?

A: 

Drag and drop is rarely employed on mobile devices, even touch devices like Android and iPhone. I would advise against it. Rightly or wrongly, users will not be expecting drag and drop operations to work, so you will have discoverability issues.

Jim Blackler
What kind of drag and drop are you thinking about? In games it can be perfectly normal and intuitive. For example, some arcade games use a drag-and-drop to move your character/vehicle around, or my jigsaw puzzle game uses it to move pieces around. Touching and dragging was the first kind of interaction everyone tried with my app.
Steve H
Fair point, in games it may be OK. I was thinking of apps.
Jim Blackler
Maybe for the average Blackberry user checking their work email on the weekends drag-and-drop might not be the first instinct, but iPhone and Android users most certainly expect everything to have cool-factor baked in, and they find it weird if things like tap, drag, and long-hold aren't implemented.
Rich
Well long tap and long-hold are a doddle, as they are part of the standard Android GUI. Drag and drop isn't.
Jim Blackler
+2  A: 

Hi! I use drag and drop in my music player application! I give to user the ability to move an song from an playlist to an other playlist. It is really nice and simple for the user. I start the drag event for my view when user make an long tap on an song or when an option from an menu is selected! This is my class:

package com.liviu.app.smpp.gui;

import android.content.Context; import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.widget.RelativeLayout; import android.widget.TextView;

import com.liviu.app.smpp.R; import com.liviu.app.smpp.listeners.CollisionListener;

public class SongItemView extends RelativeLayout implements OnClickListener {

// data
private String TAG = "SongItemView";
private Context context;
private LayoutInflater lInflater;   
private String title;
private int id;
private int maxHeight = 410;
private int mCurX;
private int mCurY;

//listeners
private CollisionListener onCollisionListener = null;

// views
private View v;

public SongItemView(Context ctx, String title_, int id_) {
    super(ctx);

    context   = ctx;
    lInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    v         = lInflater.inflate(R.layout.song_item_view, null);
    title     = title_;
    id        = id_;

    ((TextView)v.findViewById(R.id.siv_title)).setText(title);      

    addView(v, new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}

@Override
public void onClick(View v) {
    Log.e(TAG, "clicked! " + ((TextView)v.findViewById(R.id.piv_title)).getText().toString());
}

public View getView(){
    return v;
}

public String getPlsName() {
    return title;
}

public int getID() {
    return id;
}

public void setTitle(String title_){
    ((TextView)v.findViewById(R.id.siv_title)).setText(title_);
    title = title_;
}

public void setID(int id_) {
    id = id_;   
}

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    mCurX = (int) event.getRawX();
    mCurY = (int) event.getRawY();

    int action = event.getAction();         

    if (action == MotionEvent.ACTION_MOVE) 
    {       
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);                     
        params.leftMargin = mCurX;
        params.topMargin  = mCurY;
        this.setLayoutParams(params);

        if(this.getTop() >= maxHeight)
        {
            Log.e(TAG, "Collision!!!!");
            if(onCollisionListener != null){
                    onCollisionListener.onCollision(this);                  
            }
        }                   
    }

    return true;
}

public void setOnCollisionListener(CollisionListener listener){
    onCollisionListener = listener;
}

public void setMaxHeight(int height){
    maxHeight = height;
}

public int getmCurX() {
    return mCurX;
}

public int getmCurY() {
    return mCurY;
}

public int getMaxHeight() {
    return maxHeight;
}

}

I hope this will help a bit.

Thanks!

Ungureanu Liviu