Вопрос

I'm not sure if my question is understandable. I have an Image and a ViewGroup in my layout. The ViewGroup is comparable with a GridView, where I have items, that I can drag and drop. Now I'm interested in dragging the items of my ViewGroup over the image, but every time I try, the items seems to have a lower z-index, because the disappear behind the image.

I already tried combinations with bringToFront on the ViewGroup and its items, but nothing worked. Now my question is, whether it is even possible to bring the viewgroups items in front of the viewgroups sibling. Does anyone have experience with that?

My xml looks like this, where GridView is my Viewgroup...the image resource and visiblity of the image is set in code:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/relative_gridview_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:tag="@string/tag_fragment_GridView"
android:background="#FFF"
android:orientation="vertical" >

<ImageView
    android:id="@+id/img"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:visibility="gone" />


<de.test.GridView
    android:id="@+id/grid_view1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@id/img"
    android:background="#FFF"
    android:gravity="center"
    android:numColumns="auto_fit"
    android:stretchMode="none"
    android:tag="grid_view_tag" >
</de.test.GridView>

EDIT: I use a BaseAdapter to display the layout, because I have a dynamically amount of pages, that can be flipped using this library https://github.com/openaphid/android-flip.

The layout I create like the following:

public View loadView(final View view, final int position) {

    final GridView dgv = (GridView) view
            .findViewById(R.id.grid_view1);


    dgv.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(android.widget.AdapterView<?> arg0, View v,
                int position, long arg3) {

            // Simple click listener for the items...



        }
    });

    dgv.getViewTreeObserver().addOnGlobalLayoutListener(
            new OnGlobalLayoutListener() {

                @Override
                public void onGlobalLayout() {
                    if (Build.VERSION.SDK_INT < 16) {
                        dgv.getViewTreeObserver()
                                .removeGlobalOnLayoutListener(this);
                    } else {
                        dgv.getViewTreeObserver()
                                .removeOnGlobalLayoutListener(this);
                    }

                    int displayHeight = view.getHeight();
                    int displayWidth = view.getWidth();


                        dgv.initChilds(displayWidth, displayHeight,
                                2,
                                2);
                    } else {
                        mImage = (ImageView) view
                                .findViewById(R.id.img);
                        mImage.getLayoutParams().height = displayHeight / 2;

                        mImage.setImageResource(R.drawable.bild);


                        dgv.initChilds(displayWidth,
                                displayHeight / 2, 2,
                                2);
                    }

                    updateGridView();
                }

            });

    mList.add(view);

    return view;
}

the initChilds()-Methods determines the size of each item of the viewgroup. I would like to set the viewgroup item to the front, when it is choosen by longclick. The longclicklistener looks like that:

@Override
public boolean onLongClick(View view) {

    draggedItem = getDraggedView(); draggedItem.bringToFront();
    callback.bringGridToFront();            

    return true;
}

I try to bring the item to the front like this, but it do not work...the callback variable is an instance of the baseadapter class, which calls the bringGridToFront()-Method, which currently executes the following code:

public void bringGridToFront() {
    View view = mList.get(mCurrentPage);
    RelativeLayout rl = (RelativeLayout) view.findViewById(R.id.relative_gridview_layout);
    GridView dgv = (GridView) view.findViewById(R.id.grid_view1);       
    rl.bringChildToFront(dgv);
}
Это было полезно?

Решение 2

thanks for all the help. Finally the bringToFront()-Method seems to do not work for me. Now I'm able to solve my problem by using the getChildDrawingOrder()-Method overrided from ViewGroups.

With this method you can change the drawing order of the children and so draw the item you want to lay above all the others at last. An example:

@Override
public int getChildDrawingOrder(int childCount, int i) {
    if(mDragged != -1) {

        if(i == mDragged) {
            return childCount-1;
        }
        else if(i == (childCount - 1)) {
            return mDragged;
        }       
        else {
            return i;
        }
    }

    return i;
}

mDragged is the variable that should lay in the front. So i changed the drawing position of this variable with the last one...hope this help for anyone who had the same problem :D

Другие советы

Android manages the z-index based on the view's position inside the layout tree table. The view with the biggest index draws itself on top of the others. In your layout your custom grid is on top of the others because it is the last view in the layout and thus it gets the biggest index.

In your code I can see that you are calling

draggedItem = getDraggedView();

in the onLongClick(View view) event. getDraggedView() maybe returns a view which is the view you are dragging and it is not displayed on top (this is just a guess since you are not posting getDraggedView() code). If this is the case you need to know the parent of the dragged view if for example the parent is the main window then your entire layout will be on top of it. So my best guess is to add the dragged view in your layout and because it will be the last view it will go on top.

Furthermore I've noticed that you are calling

mImage.getLayoutParams().height = displayHeight / 2;

in your image view in order to change its height. I don't think that this is the correct way to do it because if take a look in View's source code here in line 10130 in which setLayoutParams code is you 'll see that some other things are happening besides the set of the layoutparams. However I don't know if this is related with your problem or not.

I know my answer is more of a guessing than a complete one but it is the best I can do based on the question's data.

Hope this helps...

I tried the accepted answer, but kept getting crashes whenever there were child views that weren't shown. The issue was that the parameters childCount and i refer to the visible children, not the entire list of children. This solution builds on that answer and incorporates this adjustment to the indexes.

@Override
public int getChildDrawingOrder(int childCount, int i) {
   int firstVisiblePosition = getFirstVisiblePosition();
   if (mDragged < firstVisiblePosition || mDragged > getLastVisiblePosition())
      return super.getChildDrawingOrder(childCount, i);
   int adjustedDragged = mDragged - firstVisiblePosition;
   if (i == adjustedDragged)
       return childCount - 1;
   if (i == (childCount - 1))
      return adjustedDragged;
   return i;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top