android自定义View(2):实现百分比自适应布局

android界面适配难是历史原因,我们只能想办法解决。github上面已有一些布局自适应的解决方案,今天我分享的是自定义控件:RelativieLayout自适应百分比宽高。直接上菜。

一,实现的效果图

android自定义View(2):实现百分比自适应布局_第1张图片
眼见为实,截图所示,宽高都是50%,实现了自适应

二,实现的原理

其实很简单,就是自定义两个属性:宽和高的百分比,让自定义的view继承 RelativeLayout。取出这两个属性的值,测量父布局的宽高,乘百分比就是实际的宽高,然后确定在父控件中的位置。

三,自定义样式属性

在values文件夹中新建attrs.xml,内容如下:
layout_widthPercent和layout_heightPercent都是浮点型,0-1之间的值,代表百分百。


<resources>
    <declare-styleable name="percentRelativeLayout">
        <attr name="layout_widthPercent" format="float">attr>
        <attr name="layout_heightPercent" format="float">attr>
    declare-styleable>
resources>

四,自定义percentRelativeLayout

简单粗暴,根据xml布局中的子view的LayoutParams获取实际宽高。

public class PercentRelativeLayout extends RelativeLayout{
    public PercentRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // TODO Auto-generated constructor stub
    }
    public PercentRelativeLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }
    public PercentRelativeLayout(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }   
    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        // TODO Auto-generated method stub
        return new LayoutParams(getContext(), attrs);
    }
    //测量自己
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //获取自身的宽高
        int widthHint = View.MeasureSpec.getSize(widthMeasureSpec);
        int heightHint = View.MeasureSpec.getSize(heightMeasureSpec);
        for(int i = 0;i<this.getChildCount();i++){
            View child = this.getChildAt(i);
            //获取孩子view的布局属性
            ViewGroup.LayoutParams params = child.getLayoutParams();
            float widthPercent = 0;
            float heightPercent = 0;
            //含有自定义的属性,则获取百分百
            if(params instanceof PercentRelativeLayout.LayoutParams){
                widthPercent = ((PercentRelativeLayout.LayoutParams) params).getWidthPercent();
                heightPercent = ((PercentRelativeLayout.LayoutParams) params).getHeightPercent();
            }
            if(widthPercent == 0|| heightPercent == 0){
                continue;//百分百为0,跳出此次循环
            }
            //真实的宽高
            params.width = (int) (widthPercent*widthHint);
            params.height = (int) (heightPercent*heightHint);
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // TODO Auto-generated method stub
        super.onLayout(changed, l, t, r, b);
    }
    public static class LayoutParams extends RelativeLayout.LayoutParams{
        private float widthPercent;
        private float heightPercent;
        public float getWidthPercent() {
            return widthPercent;
        }
        public void setWidthPercent(float widthPercent) {
            this.widthPercent = widthPercent;
        }
        public float getHeightPercent() {
            return heightPercent;
        }
        public void setHeightPercent(float heightPercent) {
            this.heightPercent = heightPercent;
        }
        //构造函数里面获取自定义样式属性的值
        public LayoutParams(Context c, AttributeSet attrs) {
            super(c, attrs);
            TypedArray array = c.obtainStyledAttributes(attrs, R.styleable.percentRelativeLayout);
            widthPercent = array.getFloat(R.styleable.percentRelativeLayout_layout_widthPercent, widthPercent);
            heightPercent = array.getFloat(R.styleable.percentRelativeLayout_layout_heightPercent,heightPercent);
            array.recycle();
        }
        public LayoutParams(int w, int h) {
            super(w, h);
            // TODO Auto-generated constructor stub
        }
        public LayoutParams(android.view.ViewGroup.LayoutParams source) {
            super(source);
            // TODO Auto-generated constructor stub
        }
        public LayoutParams(MarginLayoutParams source) {
            super(source);
            // TODO Auto-generated constructor stub
        }
    }
}

五,布局中引用自定义View和属性

上菜了。不用 系统控件,用咱们自己的。

<com.example.view.PercentRelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res/com.example.percent_relativelayout_dn"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    "wrap_content"
        android:layout_height="wrap_content"
        android:text="测试百分比布局" 
        android:layout_centerInParent="true"
        app:layout_widthPercent = "0.5"
        app:layout_heightPercent = "0.5"
        android:background="#00ff00"
        android:id="@+id/textview"
        />
com.example.view.PercentRelativeLayout>

六,实现与总结

直接在activity中运行测试,是不是很完美了。宽高半分比布局OK了。

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

五大布局都可以实现,今天只是分享了RelativieLayout的中控件的百分百自适应。之前在github上面看了一个很全面的百分百布局方案,其实原理就这样。
欢迎交流,杜乾,Dusan,Q 291902259。

你可能感兴趣的:(Android,Advanced)