4

I have an app filled with custom buttons for Android. I would like to allow user to rearrange these buttons like image buttons of Home or Application panel.

I researched on this and found out that I can use drag & drop functionality to interact with user's motion. But in my case parent layout can be different. OnMove or OnDrop event, I need to actually move that button in that corresponding layout.

So question is how I can find a layout that contains coordinate x & y and put the button in it.

@Override
public boolean onTouchEvent(MotionEvent event) {


    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        status = START_DRAGGING;
        break;
    case MotionEvent.ACTION_UP:
        status = STOP_DRAGGING;
        break;
    case MotionEvent.ACTION_MOVE:
        if(status == START_DRAGGING){
            //parentLayout.setPadding((int)event.getRawX(), 0,0,0);
            //**What to do here**
            parentLayout.invalidate();
        }                           
        break;

    }

    return true;
}
Tae-Sung Shin
  • 20,215
  • 33
  • 138
  • 240
  • I expect you can't use a layout xml file, so start with removing that, and locate the buttons in one function based on x,y coordinates or cells in a table. – James Black Nov 30 '11 at 17:10
  • I understand what you mean. Hmm...I have hundred or so buttons so it will be major change. – Tae-Sung Shin Nov 30 '11 at 17:26

3 Answers3

8

You can loop through all the controls in the parent container and compare each child's bounds with the current X, Y. You can get a views bounds by calling this:

View.getHitRect()

So something like this:

for(View v : parent.children())
{
    // only checking ViewGroups (layout) obviously you can change
    // this to suit your needs
    if(!(v instanceof ViewGroup))
        continue;

    if(v.getHitRect().contains(x, y))
        return v;
}

This is just Psuedo-code and will need to be adapted for whatever you use is (i.e. adding recursion for nested controls).

Hope that helps.

Joe
  • 2,649
  • 21
  • 33
2

I would suggest something to loop through the root XML and check the visible coordinates of any contained ViewGroups; something like this, though this is untested:

ViewGroup root = (ViewGroup)findViewById(R.id.id_of_your_root_viewgroup);
//get event coordinates as int x, int y

public ViewGroup findContainingGroup(ViewGroup v, int x, int y) {
    for (int i = 0; i < v.getChildCount(); i++) {
        View child = v.getChildAt(i);
        if(child instanceof ViewGroup) {
            Rect outRect = new Rect();
            child.getDrawingRect(outRect);
            if(outRect.contains(x, y)) return child;
        }
    }
}

ViewGroup parent = findContainingGroup(root, x, y);
Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
0

I would suggest using a TableLayout. As it's made of rows and columns, you can dynamically reorder them by inserting / deleting rows or columns and rebuilding your whole layout on the fly.

But that probably means you'd have to set you layout programmatically, I can see how you can do that from an XML layout.

(The following is pseudo-code)

if (dropping button) {
    calculate new layout based on which row/column button was moved, and where it was dropped;
    generate new layout (TableLayout --> addRow --> addView);
    apply it to buttons view (Buttons.setView(TableLayoutView));
}
Guillaume
  • 22,694
  • 14
  • 56
  • 70