android view层次与位置大小
16lz
2021-01-25
1、改变层次
首先要明白,android的层次由摆放view的先后顺序决定,也就是addView中的index,0表示最下面,越大越上面,不会超过容器的包含的View个数,(因为是数组下标)。
1、所以需要第一种方法,是最原始的方法。将一个view remove掉然后再加入进来,因为越后面加入的view,在越下面。
如下代码展示了如何交换两个ImageView的层次。
int screen_w = getResources().getDisplayMetrics().widthPixels; int screen_h = getResources().getDisplayMetrics().heightPixels; mContent.removeAllViews(); RelativeLayout.LayoutParams layoutParams1 = (RelativeLayout.LayoutParams) mExample1.getLayoutParams(); RelativeLayout.LayoutParams layoutParams2 = (RelativeLayout.LayoutParams) mExample2.getLayoutParams(); mExample1 = new ImageView(MainActivity.this); mExample2 = new ImageView(MainActivity.this); mExample1.setImageResource(R.drawable.example_h); mExample2.setImageResource(R.drawable.example_v); layout(layoutParams1, layoutParams2); if (mExample2OnTop) { layoutParams1.width = screen_w / 4; layoutParams1.height = screen_h / 4; layoutParams2.width = screen_w; layoutParams2.height = screen_h; mExample1.setLayoutParams(layoutParams1); mExample2.setLayoutParams(layoutParams2); mContent.addView(mExample2); mContent.addView(mExample1); mExample2OnTop = false; } else { layoutParams1.width = screen_w; layoutParams1.height = screen_h; layoutParams2.width = screen_w / 4; layoutParams2.height = screen_h / 4; mExample1.setLayoutParams(layoutParams1); mExample2.setLayoutParams(layoutParams2); mContent.addView(mExample1); mContent.addView(mExample2); mExample2OnTop = true; } mExample2.setOnClickListener(ImageSwitchListener); mExample1.setOnClickListener(ImageSwitchListener);
mContent为父容器,先用removeAllViews将所有view去除,然后使用addView将View再添加,注意在if和else里面 添加两个View的顺序。layoutParam为位置view大小的方法,在实验中,楼主遇到一个问题,就是重新添加后两个View不能点击,换成Button发现不是状态的问题,完全没有点击效果,只有按Home键退出后,View才会响应OnClick事件,但是重新添加后又不能点击,重新New一个就OK了,怀疑是remove后是不是有些私有状态不对了。只有OnResume之后,恢复了过来,楼主没有深入研究,所以就新建了一下,重新设置参数。也算规避掉了,望知情人士提供线索。这种方法实际应用意义不大,又要重新new,又要remove和add。开销蛮大的。
楼主后来想了下,可能后AttachWindow的原因比较大,onResume之后重新AttachWindow所以按键效果就出来了。
于是介绍下一种方法 bringToFront()
int screen_w = getResources().getDisplayMetrics().widthPixels; int screen_h = getResources().getDisplayMetrics().heightPixels; RelativeLayout.LayoutParams layoutParams1 = (RelativeLayout.LayoutParams) mExample1.getLayoutParams(); RelativeLayout.LayoutParams layoutParams2 = (RelativeLayout.LayoutParams) mExample2.getLayoutParams(); layout(layoutParams1, layoutParams2); mContent.requestLayout(); if (mExample2OnTop) { layoutParams1.width = screen_w / 4; layoutParams1.height = screen_h / 4; layoutParams2.width = screen_w; layoutParams2.height = screen_h; mExample1.setLayoutParams(layoutParams1); mExample2.setLayoutParams(layoutParams2); mExample1.bringToFront(); mExample2OnTop = false; } else { layoutParams1.width = screen_w; layoutParams1.height = screen_h; layoutParams2.width = screen_w / 4; layoutParams2.height = screen_h / 4; mExample1.setLayoutParams(layoutParams1); mExample2.setLayoutParams(layoutParams2); mExample2.bringToFront(); mExample2OnTop = true; }
bringToFront起到了相同的作用,因为bringToFront将view的index设置为最大,内部只是调整了view结构树的层次,而不是remove和add。减小了开销。是目前比较常用的方法 也许有人会用到,bringToFront之后再重新调整到原来位置,这里提供一份代码。
private void moveToBack(View currentView) { ViewGroup viewGroup = ((ViewGroup) currentView.getParent()); int index = viewGroup.indexOfChild(currentView); for(int i = 0; i
3、在android5.0 api引入一个setZ(float)的函数,也可以调整view的层次。听说原理是相当于修改translationZ的属性(就是在3.0还是4.0引入的RotateXY,ScaleXY,TranslationXY之类的属性。)。全部代码不贴了,只看关键代码
if (mExample2OnTop) { // mExample1.bringToFront(); mExample1.setZ(100.f); mExample2.setZ(0.f); mExample2OnTop = false; } else {// mExample2.bringToFront(); mExample1.setZ(0.f); mExample2.setZ(100.f); mExample2OnTop = true; }
这个接口比较新。作用是体现出来了。但是副作用还不知道。 2、在代码中动态调整view的大小。 大部分情况下,View的大小在xml中已经定好了,不会在运行中动态调整,但是万一遇到一些需求需要在运行中调整view的大小呢 这个比层次简单,基本上就是修改 LayoutParams
不过需要注意的是,需要注意到父容器是什么类型的,FrameLayout,LinearLayout,RelativeLayout等,因为不同类型的LayoutParams是不同的
private void layout(RelativeLayout.LayoutParams layoutParams1, RelativeLayout.LayoutParams layoutParams2) { layoutParams1.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); layoutParams1.addRule(RelativeLayout.ALIGN_PARENT_LEFT); layoutParams2.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); layoutParams2.addRule(RelativeLayout.ALIGN_PARENT_LEFT); }请看,上面一些属性是只有RelativeLayout才有的。所以这就是为什么要区分父容器类型的原因。
下面是如何修改View大小的代码
RelativeLayout.LayoutParams layoutParams1 = (RelativeLayout.LayoutParams) mExample1.getLayoutParams(); RelativeLayout.LayoutParams layoutParams2 = (RelativeLayout.LayoutParams) mExample2.getLayoutParams(); layoutParams1.width = screen_w / 4; layoutParams1.height = screen_h / 4; layoutParams2.width = screen_w; layoutParams2.height = screen_h; mExample1.setLayoutParams(layoutParams1); mExample2.setLayoutParams(layoutParams2);
这样就好了,连invalidate或者requestLayout都不需要调用。因为内部自己会调用。 题外话,如果需要addView的话,那么使用getLayoutParams是没用的,因为这个你自己新建的一个View,没有与父容器有任何关联。所以LayoutParams也需要你自己创建。
mExample1 = new Button(this); mExample2 = new Button(this); RelativeLayout.LayoutParams layoutParams1 = new RelativeLayout.LayoutParams(screen_w, screen_h); RelativeLayout.LayoutParams layoutParams2 = new RelativeLayout.LayoutParams(screen_w / 4, screen_h / 4); layout(layoutParams1, layoutParams2); mExample1.setLayoutParams(layoutParams1); mExample2.setLayoutParams(layoutParams2); mContent.addView(mExample1); mContent.addView(mExample2);
更多相关文章
- 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
- Android(安卓)简单图片浏览器(疯狂Android讲义第三版)
- Android中关于Notification及NotificationManger的详解
- Android常用复杂控件使用(四)--Fragment(续)
- Android(安卓)Studio 使用Git创建本地分支和远程分支以及合并
- Android音乐播放器【安卓进化二十】
- android EventBus学习记录
- Android移动安全(一)Android混淆机制
- SharedPreferences初学~个人备忘录以及对进入APP的次数进行计数