Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How would I go about creating a custom container view in Android?

Tags:

java

android

I would like to create a view with a listener that acts sort of like a container or grocery bag. Any image or text that is dragged into it, gets collected and saved into a local database. Or rather the image name or string gets saved. I've created custom views before that displayed a custom row of data but I'm not sure how to create a "grocery bag" type of view. I've searched Google for creating a custom container view with listener but couldn't find anything related to what I am looking for. I'm not asking anyone to do it for me, just give me some advice or push in the right direction.

Edit Just to clarify a little more. I already know how to drag and drop a view. The problem with that is that you can drop anywhere. What I want is a view that when something is dropped within its bounds, it gets the views' string or tag. Regardless of what kind of view that may be. Somehow this custom view has to know what kind of view was dropped within its bounds and remove that view on drop.

like image 375
Steve C. Avatar asked Apr 12 '16 05:04

Steve C.


2 Answers

   <view class="at.calista.quatscha.views.SwipebarLayout"
        android:id="@+id/sbl"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">

        <!-- Top View -->
        <Button android:text="Top" android:id="@+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>

        <!-- Bottom View -->
        <Button android:text="Bottom" android:id="@+id/Button02" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>

like image 159
Idrish Multani Avatar answered Oct 06 '22 01:10

Idrish Multani


You would need a method that determines whether two views overlap. For example, something like these methods could work for when the target view and the dragged item view are 2 distinct views in the same container view:

private Rect getScreenBounds(View view)
{
    int[] location = new int[2];
    view.getLocationOnScreen(location);

    return new Rect(location[0], location[1], location[0] + view.getWidth(), location[1] + view.getHeight());
}

private boolean doViewsIntersect(View dropTarget, View item)
{
    Rect dropRect = getScreenBounds(dropTarget);
    Rect itemRect = getScreenBounds(item);

    return Rect.intersects(dropRect, itemRect);
}

However, if the views being dragged are child views on a container, and that container has a special hit area where you want to perform the drop logic, then you can just use that hit area's Rect for the intersect test.

To save information on the View, you have a few options:

  • You can use view.setTag(key, object) and view.getTag(key) to store whatever information you'd like on each item.
  • If you are using a custom class for the items, you can just add a method to get the data from the view class.
  • If you are using multiple different classes for the items, you could make an interface, and implement that interface on each draggable view class.

On an item's release, you could then check whether the areas/views intersect, and if they do, get whatever information you need from the dragged item to process as necessary, either using getTag or the method added to the view.

For example, this could be triggered via an onTouchListener, when you receive a MotionEvent.ACTION_UP event. Here's an example of a listener that you can add on each item:

item.setOnTouchListener(new View.OnTouchListener()
{
    @Override
    public boolean onTouch(View v, MotionEvent event)
    {
        if (event.getActionMasked() == MotionEvent.ACTION_UP)
        {
            if (doViewsIntesect(dropTarget, v))
            {
                Object data = v.getTag(DATA_KEY);
                //process data
                ((ViewGroup) v.getParent()).removeView(v); // to remove the item afterwards
            }
        }
        return false;
    }
});
like image 23
Allen G Avatar answered Oct 06 '22 00:10

Allen G