从LayoutParams说起到代码动态布局

本文说两点
1、介绍LayoutParams并且简单代码实现xml布局效果
2、代码动态控制RelativeLayout子控件的布局变化

一、LayoutParams

LayoutParams
如果直接从字面上来看,这应该是 布局参数 的意思。
我们常常利用LayoutParams来做代码动态布局,现在再来赘述一下它吧。

从LayoutParams说起到代码动态布局_第1张图片
Paste_Image.png

在安卓的布局世界里面就2个东西,要么是容器(ViewGroup),要么是控件(View)。
个性与规则并存,我们一个小小控件,要张扬个性,也要遵守规矩,基本宽高我们时候要的,左对齐还是居中对齐我们也不一样,这些不用如果在xml的布局文件自然是几行代码的事情,但是换成Java代码的话就需要LayoutParams来出力了。

一.1、LayoutParams的几个小特点

LayoutParams 是 子控件 用来告诉 父控件 自己要如何布局时用的。

  • LayoutParams 是ViewGroup的一个内部类,这是一个基类,主要描述了宽高.
    宽与高有三种指定方式
    • FILL_PARENT (renamed MATCH_PARENT in API Level 8 and higher) 填充父窗体
    • WRAP_CONTENT 包裹内容
    • an exact number 精准描述
  • 每一个继承自ViewGroup的容器比如RelativeLayout等自己对应的LayoutParams,而且这些LayoutParams又有自己独特的属性,比如RelativeLayout.LayoutParams可以设置RelativeLayout.RIGHT
 RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(vgLp);
 params.addRule(RelativeLayout.RIGHT_OF,R.id.mTvBlue);
  • 子控件在获取LayoutParams一定要和当前父控件的容器类型保持一致。
    比如TextView是在LinearLayout下面的,那么LayoutParams就必须是 LinearLayout.LayoutParams。比如上面例子代码中的
LinearLayout.LayoutParams textParams = new LinearLayout.LayoutParams(textView.getLayoutParams());
textParams.width = dip2px(LikeXmlActivity.this,200);
textParams.height = dip2px(LikeXmlActivity.this,30);
textView.setLayoutParams(textParams);

.
.
.

一.2、代码简单实现xml效果

文字说完了,来点代码吧
我们先看下面的代码

    
        
    

这个一段非常简单的安卓布局文件的代码,一个LinearLayout里面放了一个TextView。其最终展现的效果和对顶代码布局代码如下:

从LayoutParams说起到代码动态布局_第2张图片
Paste_Image.png

接下来在Activity中换成代码来实现布局

public class LikeXmlActivity extends AppCompatActivity {
    private LinearLayout mRootView;
    private LinearLayout mLinearLayout;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_like_xml);
        mRootView = (LinearLayout) findViewById(R.id.mRootView);

        // 第一步,把 LinearLayout 添加到布局里面
        // 给LinearLayoutnew一个LinearLayout.LayoutParams,并且通过  etLayoutParams  让layout更新
        // LayoutParams可以从父窗体获得也可以自己new出来,这里我们采用自己new的方式
        mLinearLayout = new LinearLayout(LikeXmlActivity.this);
        mLinearLayout.setBackgroundColor(Color.parseColor("#0000ff"));

        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT);
        mLinearLayout.setLayoutParams(layoutParams);
        mRootView.addView(mLinearLayout);

        // 第二步,把TextView 添加到 第一步的 LinearLayout 里面
        TextView textView = new TextView(LikeXmlActivity.this);
        textView.setText("代码在此2");
        textView.setBackgroundColor(Color.parseColor("#ff0000"));
        textView.setGravity(Gravity.CENTER);
        mLinearLayout.addView(textView);

        // 第三步,把TextView获取对应父窗体类型的LayoutParams 并且设置参数更新layout
        LinearLayout.LayoutParams textParams = new LinearLayout.LayoutParams(textView.getLayoutParams());
        textParams.width = dip2px(LikeXmlActivity.this,200);
        textParams.height = dip2px(LikeXmlActivity.this,30);
        //textParams.gravity = Gravity.CENTER;  // 无效,这样并不能让文字在控件里居中
        textView.setLayoutParams(textParams);
        
    }

    private int dip2px(Context context, float dipValue)
    {
        Resources r = context.getResources();
        return (int) TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP, dipValue, r.getDisplayMetrics());
    }
}

对比

从LayoutParams说起到代码动态布局_第3张图片
Paste_Image.png

一.3、LayoutParams的使用小结

step 1、获得对应父窗体类型的LayoutParams

LinearLayout.LayoutParams textParams = new LinearLayout.LayoutParams(textView.getLayoutParams());

step 2、对控件本身的宽高和特有的属性比如对齐方式等进行设置

textParams.width = dip2px(LikeXmlActivity.this,200);
textParams.height = dip2px(LikeXmlActivity.this,30);

step 3、利用setLayoutParams方法对控件的layout进行布局更新

textView.setLayoutParams(textParams);

.
.
.

二、DEMO —— 代码动态控制RelativeLayout子控件的位置

从LayoutParams说起到代码动态布局_第4张图片
lp.gif

效果图大致如上,代码也是比较简单的,直接附上就好:

Activity

public class MoveActivity extends AppCompatActivity {
    private ImageView mIv;
    private TextView mTvBlue;
    private TextView mTvGreen;
    private ViewGroup.LayoutParams mVgLp;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_move);
        mIv = (ImageView) findViewById(R.id.mIv);
        mTvBlue = (TextView) findViewById(R.id.mTvBlue);
        mTvGreen = (TextView) findViewById(R.id.mTvGreen);

        mVgLp = mIv.getLayoutParams();

        findViewById(R.id.mTvMoveRight).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ViewGroup.LayoutParams vg_lp = mIv.getLayoutParams();
                // RelativeLayout.LayoutParams 不可抽取为成员变量
                RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(vg_lp);
                params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, R.id.mIv);
                mIv.setLayoutParams(params); //使layout更新
            }
        });

        findViewById(R.id.mTvMoveLeft).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 左 (默认处于顶部,所以看起来是左上)
                RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(mVgLp);
                params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
                mIv.setLayoutParams(params);
            }
        });

        findViewById(R.id.mTvCenter).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 居中
                RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(mVgLp);
                params.addRule(RelativeLayout.CENTER_IN_PARENT);
                mIv.setLayoutParams(params);
            }
        });

        findViewById(R.id.mTvLeftVer).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 左部垂直居中
                RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(mVgLp);
                params.addRule(RelativeLayout.ALIGN_PARENT_LEFT|RelativeLayout.CENTER_VERTICAL);
                mIv.setLayoutParams(params);
            }
        });

        findViewById(R.id.mTvRightBot).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 右下
                RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(mVgLp);
                params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
                params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
                mIv.setLayoutParams(params);
            }
        });
        //  绿在蓝右边
        findViewById(R.id.mTvaGRightB).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ViewGroup.LayoutParams vgLp = mTvGreen.getLayoutParams();
                RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(vgLp);
                params.addRule(RelativeLayout.RIGHT_OF,R.id.mTvBlue);
                mTvGreen.setLayoutParams(params);
            }
        });

        // 绿在蓝下边
        findViewById(R.id.mTvGElowB).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ViewGroup.LayoutParams vgLp = mTvGreen.getLayoutParams();
                RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(vgLp);
                params.addRule(RelativeLayout.BELOW,R.id.mTvBlue);
                mTvGreen.setLayoutParams(params);
            }
        });
    }
}

.
.
.

布局文件



    
        
        
        
    
    
        
        
    
    
        
        
    
    
        
        
        
        
    

本篇完。

你可能感兴趣的:(从LayoutParams说起到代码动态布局)