How to send view to back ? How to control the z-order programmatically?

a 夏天 提交于 2019-11-27 19:35:03

Afaik there's no built-in solution for this. I guess you're trying to modify the z-order in a FrameLayout, or something similar.

However, I think you can modify the order of the contained child elements in the layout. RemoveChild...() and addView() methods can take position values, so you could most likely swap child elements around, and that would modify the z-order. It seems a bit hacky solution however.

Or consider modifying the visibility property of the child views, you may get similar behaviour, and that'd be much cleaner I think.

Edit:

With the new Android version, the L Developer Preview it seems that at last we have the ability to easily change the Z ordering of Views. 'Elevation' and 'TranslationZ' properties to the rescue: https://developer.android.com/preview/material/views-shadows.html

I realize that this has been implied in other answers, but no one posted the code. I keep the following in a utility class where I have "helper" functions for dealing with views:

public static void sendViewToBack(final View child) {
    final ViewGroup parent = (ViewGroup)child.getParent();
    if (null != parent) {
        parent.removeView(child);
        parent.addView(child, 0);
    }
}
Pepijn

There is no sendToBack() method. But if you call bringToFront() on the lower positioned view you get almost the same effect.

noob

Call bringToFront() on the view you want to get in the front, and then call the invalidate() method on all the view including the view which you want in the front. Repeat same for all the listeners.

So when another view's listener will get called, the previous view will get invalidated and will be in background.

Here is the method I am using to send a View to the back (so opposite of bringToFront, kind of sendToBack):

    private void moveToBack(View myCurrentView) 
    {
        ViewGroup myViewGroup = ((ViewGroup) myCurrentView.getParent());
        int index = myViewGroup.indexOfChild(myCurrentView);
        for(int i = 0; i<index; i++)
        {
            myViewGroup.bringChildToFront(myViewGroup.getChildAt(i));
        }
    }

Hope this helps!

Please note that you can use view.setZ(float) starting from API level 21. Here you can find more info.

it work's fine like bringToBack()

public void moveToBack(ViewGroup viewGroup, View v) {
    int s = 1;
    for (int i = 1; i < viewGroup.getChildCount(); i++) {
        if (viewGroup.getChildAt(1) == v) {
            s = 2;
        } else {
            viewGroup.getChildAt(s).bringToFront();
        }
    }
}

You can also try to use functionality of ViewGroup.addViewInLayout() method which take an index, determining should the view be at the end or at the beginning of the list

In your XML File you must to write in order:

<FrameLayout
android:id="@+id/frameLayoutXML"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
<ImageView
 android:id="@+id/imageViewXML"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/floatB_XML"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</FrameLayout>

In this case, the imageView will be back of the FloatingActionButton.

If you want change something, and you will do it programmatically then:

public class SomeActivity extends AppCompatActivity {

    //declare variables
    ImageView imageView;
    FrameLayout frameLayout;
    FloatingActionButton floatingActionButtonNew;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //Here is to call what already exists at XML file
        frameLayout=findViewById(R.id.frameLayoutXML);   
        imageView = findViewById(R.id.imageViewXML);
        //Here is to declare a new Element to add to the view, but is not at XML File
        floatingActionButtonNew=New FloatingActionButton(this);
        frameLayout.removeAllViews();  //here you remove all views.
        frameLayout.addView(imageView);//And you add again the imageView first
        floatingActionButtonNew.setLayoutParams(new 
         RelativeLayout.LayoutParams(
          RelativeLayout.LayoutParams.WRAP_CONTENT,
          RelativeLayout.LayoutParams.WRAP_CONTENT
        )); //Then you can give some format to your floatingButtonNew

        //And finally  add to the frameLayout the new View in this case the floatingButtonNew
        frameLayout.addView(floatingActionButtonNew);
    }
}

In this order of view declarations, you will have again the image back from the floating button. So the view that is declared first will be back from the view that is declared secondly, and the key to achieve the order, is to removeAllViews of a FrameLayout or LinearLayout and add again this views when you are adding programmatically.

I would either set it's visibility to 0 or just bring the view under it in front of it.

If you're using appCompat library, there's another way to change Z order for devices lower than 21 API level:

ViewCompat.setTranslationZ(view, zValue);

You could try doing view.setVisibility(View.INVISIBLE) or view.setVisibility(View.GONE).

UPDATE:

This shows you how to accomplish what you want to do.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!