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);






更多相关文章

  1. 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
  2. Android(安卓)简单图片浏览器(疯狂Android讲义第三版)
  3. Android中关于Notification及NotificationManger的详解
  4. Android常用复杂控件使用(四)--Fragment(续)
  5. Android(安卓)Studio 使用Git创建本地分支和远程分支以及合并
  6. Android音乐播放器【安卓进化二十】
  7. android EventBus学习记录
  8. Android移动安全(一)Android混淆机制
  9. SharedPreferences初学~个人备忘录以及对进入APP的次数进行计数

随机推荐

  1. windows 10 下mysql-8.0.17-winx64的安装
  2. mysql 错误号码1129 解决方法
  3. MYSQL存储过程即常用逻辑知识点总结
  4. MySQL慢SQL语句常见诱因以及解决方法
  5. MySQL中常见的八种SQL错误用法示例
  6. Mysql导入导出时遇到的问题解决
  7. 详解Windows10下载mysql的教程图解
  8. MySQL计算两个日期相差的天数、月数、年
  9. MySQL数值类型溢出的处理方法
  10. MySql 快速插入千万级大数据的方法示例