您好,欢迎来到源码搜藏网!分享精神,快乐你我!
[加入VIP] 设为首页 | 收藏本站 | 网站地图 | Sitemap | TAG标签
  • 首 页
  • 在线工具
  • jquery手册
  • 当前位置:首页 > 安卓源码 > 技术博客 >

    Android开发中一些非常适用必须要知道的布局优化技巧

    时间:2018-01-25 09:18 来源:互联网 作者:源码搜藏 浏览:收藏 挑错 推荐 打印

    Android开发中一些非常适用必须要知道的布局优化技巧 今天分享一些布局布局书写中的一些技巧,希望看过之后你也一样可以写出性价比高的布局。我个人的目标是用最少的浏览写出一样效果的布局。因为我相信搜索的数量减少伴随着的就是层级的减少。从而达到结构

    Android开发中一些非常适用必须要知道的布局优化技巧

    今天分享一些布局布局书写中的一些技巧,希望看过之后你也一样可以写出性价比高的布局。我个人的目标是用最少的浏览写出一样效果的布局。因为我相信搜索的数量减少伴随着的就是层级的减少。从而达到结构清晰,渲染速度快的效果。顺着这个逻辑,我将优化分为重用,合并,按需载入。

    重用

    <include />

    <include>标签可以在一个布局中引入另外一个布局,这个的好处显而易见。类似于我们经常用到的工具类,随用随调。便于统一修改使用。

    举例说明:首先写一个公共的布局title_bar.xml,应用中常用的标题栏。

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:background="@color/background"
        android:layout_height="48dp">
    
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:paddingLeft="15dp"
            android:paddingRight="15dp"
            android:src="@drawable/icon_back"/>
    
        <TextView
            tools:text="标题"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:textSize="18sp"
            android:textColor="@color/white" />
    
        <TextView
            tools:text="确定"
            android:layout_width="wrap_content"
            android:gravity="center"
            android:layout_height="match_parent"
            android:layout_alignParentRight="true"
            android:paddingLeft="15dp"
            android:paddingRight="15dp"
            android:textSize="16sp"
            android:textColor="@color/white" />
    
    </RelativeLayout>

    预览:

    Android开发中一些非常适用必须要知道的布局优化技巧

    下来activity_main.xml中调用它:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <include
            layout="@layout/title_bar"/>
    
    </RelativeLayout>

    运行后效果和预览一样一样的。当然我们也可以在<include>标签当中重新设置宽高等布局的属性。

    合并

    减少嵌套

    首先我们心中要有一个大原则:尽量保持布局层级的扁平化在这个大原则下我们要知道:

    • 在不影响层级深度的情况下,使用LinearLayout而不是RelativeLayout。因为RelativeLayout会让子查看调用2次onMeasure,LinearLayout在有重时,才会让子查看调用2次onMeasure.Measure的耗时越长那么绘制效率就低。

    • 如果非要是嵌套,那么尽量避免RelativeLayout的嵌套RelativeLayout的。这简直就是恶性循环,丧心病狂。

    实现方法就不细说了,大家都是明白人。

    <merge />

    因为我们布局外层就是FrameLayout,直接的接口,所以我们可以直接使用FrameLayout来实现这个功能。“合并”

    举例说明:比如上面用到的activity_main.xml文件,我们通过View Hierarchy工具看一下,如图:

    Android开发中一些非常适用必须要知道的布局优化技巧

    可以看到,最外层是FrameLayout里,下来我们修改一下。

    <?xml version="1.0" encoding="utf-8"?>
    <merge
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <include
            layout="@layout/title_bar"/>
    
    </merge>

    再次查看:

    Android开发中一些非常适用必须要知道的布局优化技巧

    很明显少了一层的RelativeLayout,当然运行效果是一样的。当然如果我们不需要title_bar.xml中的绿色背景,那么可以这样修改。

    <?xml version="1.0" encoding="utf-8"?>
    <merge
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="48dp"
            android:paddingLeft="15dp"
            android:paddingRight="15dp"
            android:src="@drawable/icon_back_1"/>
    
        <TextView
            android:layout_gravity="center_horizontal"
            android:text="标题"
            android:gravity="center"
            android:layout_width="wrap_content"
            android:layout_height="48dp"
            android:layout_centerInParent="true"
            android:textSize="18sp"
            android:textColor="@color/black" />
    
        <TextView
            android:text="确定"
            android:layout_gravity="right"
            android:layout_width="wrap_content"
            android:gravity="center"
            android:layout_height="48dp"
            android:layout_alignParentRight="true"
            android:paddingLeft="15dp"
            android:paddingRight="15dp"
            android:textSize="16sp"
            android:textColor="@color/black" />
    
    </merge>

    运行效果:

    Android开发中一些非常适用必须要知道的布局优化技巧

    运行查看层级,如下图:

    Android开发中一些非常适用必须要知道的布局优化技巧

    结果很明显。

    用TextView的同时显示图片和文字

    这个我就不细说了,举一个我们项目中的一个例子,代码一看便知。

    首先要完成的效果是如下图:

    Android开发中一些非常适用必须要知道的布局优化技巧

    这种效果很常见,一般实现方法是这样。(貌似没人这样写吧,哈哈)

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <LinearLayout
            android:orientation="horizontal"
            android:background="@color/white"
            android:layout_width="match_parent"
            android:layout_height="50dp">
    
            <ImageView
                android:layout_marginLeft="10dp"
                android:layout_width="wrap_content"
                android:src="@drawable/icon_1"
                android:layout_height="match_parent" />
    
            <TextView
                android:paddingLeft="10dp"
                android:paddingRight="10dp"
                android:textSize="16sp"
                android:text="我的卡券"
                android:gravity="center_vertical"
                android:layout_width="0dp"
                android:layout_weight="1"
                android:layout_height="match_parent" />
    
            <ImageView
                android:layout_marginRight="10dp"
                android:src="@drawable/icon_4"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"/>
        </LinearLayout>
    
    </LinearLayout>

    效果图:

    Android开发中一些非常适用必须要知道的布局优化技巧

    那么我们优化一下:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <TextView
            android:drawableLeft="@drawable/icon_1"
            android:drawableRight="@drawable/icon_4"
            android:drawablePadding="10dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:textSize="16sp"
            android:text="我的卡券"
            android:background="@color/white"
            android:gravity="center_vertical"
            android:layout_width="match_parent"
            android:layout_height="50dp" />
    
    </LinearLayout>

    你没有看错,少了两个ImageView的和去除嵌套的LinearLayout。效果不用说一样一样的。当然EditView中等也一样的,还有属性drawableBottom和drawableTop供你使用。利用同时代码setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom)可以让我们动态去设置图片。

    使用的TextView的行间距

    先上我们需要实现的效果图:

    Android开发中一些非常适用必须要知道的布局优化技巧

    效果很简单,实现代码:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_height="100dp"
        android:background="@color/white"
        android:layout_width="match_parent"
        xmlns:tools="http://schemas.android.com/tools">
    
        <ImageView
            android:padding="25dp"
            android:src="@drawable/kd_1"
            android:layout_width="100dp"
            android:layout_height="100dp"/>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:orientation="vertical"
            android:layout_height="100dp">
    
            <TextView
                tools:text="揽件方式:上门取件"
                android:gravity="center_vertical"
                android:layout_width="match_parent"
                android:layout_height="25dp"/>
    
            <TextView
                tools:text="快递公司:顺丰快递"
                android:gravity="center_vertical"
                android:layout_width="match_parent"
                android:layout_height="25dp"/>
    
            <TextView
                tools:text="预约时间:9月6日 立即取件"
                android:gravity="center_vertical"
                android:layout_width="match_parent"
                android:layout_height="25dp"/>
    
            <TextView
                tools:text="快递费用:等待称重确定价格"
                android:gravity="center_vertical"
                android:layout_width="match_parent"
                android:layout_height="25dp"/>
    
        </LinearLayout>
    
    </LinearLayout>

    这里我偷懒了多嵌套了一层的LinearLayout,但...这不重要,我先直接修改。

    优化后代码:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_height="100dp"
        android:background="@color/white"
        android:layout_width="match_parent">
    
        <ImageView
            android:padding="25dp"
            android:src="@drawable/kd_1"
            android:layout_width="100dp"
            android:layout_height="match_parent"/>
    
        <TextView
            android:textSize="14dp"
            android:lineSpacingExtra="8dp"
            android:gravity="center_vertical"
            android:text="揽件方式:上门取件\n快递公司:顺丰快递\n预约时间:9月6日 立即取件\n快递费用:等待称重确定价格"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
    </LinearLayout>

    老规矩,效果一样一样的。看到可以仅仅我们利用android:lineSpacingExtra="8dp"这一行代码就省去了3个TextView的,如果行数更多呢?是不是方便多了。

    其中:lineSpacingExtra属性代表的是行间距,他默认是0,是一个绝对高度值同时还有。lineSpacingMultiplier属性,它代表行间距倍数,默认为1.0F,是一个相对高度值我们来使用一下

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_height="100dp"
        android:background="@color/white"
        android:layout_width="match_parent">
    
        <ImageView
            android:padding="25dp"
            android:src="@drawable/kd_1"
            android:layout_width="100dp"
            android:layout_height="100dp"/>
    
        <TextView
            android:textSize="14dp"
            android:lineSpacingMultiplier="1.3"
            android:gravity="center_vertical"
            android:text="揽件方式:上门取件\n快递公司:顺丰快递\n预约时间:9月6日 立即取件\n快递费用:等待称重确定价格"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
    </LinearLayout>

    当然了这两条属性可以同时使用,查看源码可以知道,他们的高度计算规则为mTextPaint.getFontMetricsInt(null)*行间距倍数+行间距。

    使用Spannable或Html.fromHtml

    这里也是举例说明,比如下图效果:

    Android开发中一些非常适用必须要知道的布局优化技巧

    如果实现上图红框中的效果,笨办法就是写三个TextView的,“¥”,“价格”,“门市价”分别实现,其实用一个TextView中就可以实现,类似如下代码:

     String text = String.format("¥%1$s  门市价:¥%2$s", 18.6, 22);
     int z = text.lastIndexOf("门");
     SpannableStringBuilder style = new SpannableStringBuilder(text);
     style.setSpan(new AbsoluteSizeSpan(DisplayUtil.dip2px(mContext,14)), 0, 1, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); //字号
     style.setSpan(new ForegroundColorSpan(Color.parseColor("#afafaf")), z, text.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE); //颜色
     style.setSpan(new AbsoluteSizeSpan(DisplayUtil.dip2px(mContext,14)), z, text.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE); //字号
    
     tv.setText(style);

    同样Html.fromHtml也可以实现。这样不就减少了两个TextView的了。

    按需载入

    ViewStub

    在开发中经常会遇到这样的情况,会在程序运行时动态根据条件来决定显示哪个视图或某个布局。那么通常做法就是把用到的搜索都写在布局中,然后在代码中动态的更改它的可见性。但是它的这样仍然会创建视图,会影响性能。

    这时就可以用到ViewStub了,ViewStub是一个轻量级的浏览,不占布局位置,占用资源非常小。

    例子:比如我们请求网络加载列表,如果网络异常或者加载失败我们可以显示一个提示查看,上面可以点击重新加载当然一直没有错误时,我们就不显示。

    <?xml version="1.0" encoding="utf-8"?>
    <merge xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
        ……
        <ViewStub
            android:layout_gravity="center"
            android:id="@+id/hint_view"
            android:layout_width="match_parent"
            android:inflatedId="@+id/hint_view"
            android:layout_height="wrap_content"
            android:layout="@layout/hint_view"/>
    </merge>

    hint_view.xml就是这个提示查看,可以根据情况自己写。

    用法:

    private View hintView;
    
    if (网络异常。。。) {
        if (hintView == null) {
            ViewStub viewStub = (ViewStub)this.findViewById(R.id.hint_view);
            hintView = viewStub.inflate();
            TextView textView = (TextView) hintView.findViewById(R.id.tv);
            textView.setText("网络异常!");
        }
        hintView.setVisibility(View.VISIBLE);
    }else{
        if (hintView != null) {
            hintView.setVisibility(View.GONE);
        }
    }

    用法很简单,记得一旦ViewStub可见或是被充气了,ViewStub就不存在了,取而代之的是被充气的布局。所以它也被称做惰性控件。

    其他小技巧

    用LinearLayout中自带的分割线

    还记得上文用TextView的同时显示图片和文字中的例子吗?我们可以看到每个条目之间都是有一根分隔线的,那么怎么实现呢?别人我不知道,反正我原来是用一个视图设置高度实现的。相信一定有人和我一样。

    那么老办法我就不演示了,直接上代码:

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:divider="@drawable/divider"
        android:showDividers="middle">
    
        <TextView
            android:drawableLeft="@drawable/icon_1"
            android:drawableRight="@drawable/icon_4"
            android:drawablePadding="10dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:textSize="16sp"
            android:text="我的卡券"
            android:background="@color/white"
            android:gravity="center_vertical"
            android:layout_width="match_parent"
            android:layout_height="50dp" />
    
        <TextView
            android:drawableLeft="@drawable/icon_2"
            android:drawableRight="@drawable/icon_4"
            android:drawablePadding="10dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:textSize="16sp"
            android:text="地址管理"
            android:background="@color/white"
            android:gravity="center_vertical"
            android:layout_width="match_parent"
            android:layout_height="50dp" />
    
        <TextView
            android:drawableLeft="@drawable/icon_3"
            android:drawableRight="@drawable/icon_4"
            android:drawablePadding="10dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:textSize="16sp"
            android:text="检查更新"
            android:background="@color/white"
            android:gravity="center_vertical"
            android:layout_width="match_parent"
            android:layout_height="50dp" />
    
    </LinearLayout>

    效果图:

    Android开发中一些非常适用必须要知道的布局优化技巧

    实现的核心部分其实是LinearLayout中的这两行。

    android:divider="@drawable/divider"
    android:showDividers="middle"

    其中divider.xml是分隔线样式。

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
           android:shape="rectangle">
    
        <size android:width="1dp"
              android:height="1dp"/>
    
        <solid android:color="#e1e1e1"/>
    
    </shape>

    showDividers是分隔线的显示位置,开始,中间,结束分别代表显示在开始位置,中间,末尾。

    还有dividerPadding属性这里没有用到,意思很明确给分频器添加填充。感兴趣可以试试。

    空间控件

    还是接着上面的例子,如果要给条目中间添加间距,怎么实现呢?当然也很简单,比如添加一个高10dp的查看,使用或者android:layout_marginTop="10dp"等方法。但是增加查看违背了我们的初衷,并且影响性能。使用过多的利润率其实会影响代码的可读性。

    这时你就可以使用的空间,他是一个轻量级的我们可以看下源码:

    /**
     * Space is a lightweight View subclass that may be used to create gaps between components
     * in general purpose layouts.
     */
    public final class Space extends View {
        /**
         * {@inheritDoc}
         */
        public Space(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
            if (getVisibility() == VISIBLE) {
                setVisibility(INVISIBLE);
            }
        }
    
        /**
         * {@inheritDoc}
         */
        public Space(Context context, AttributeSet attrs, int defStyleAttr) {
            this(context, attrs, defStyleAttr, 0);
        }
    
        /**
         * {@inheritDoc}
         */
        public Space(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        /**
         * {@inheritDoc}
         */
        public Space(Context context) {
            //noinspection NullableProblems
            this(context, null);
        }
    
        /**
         * Draw nothing.
         *
         * @param canvas an unused parameter.
         */
        @Override
        public void draw(Canvas canvas) {
        }
    
        /**
         * Compare to: {@link View#getDefaultSize(int, int)}
         * If mode is AT_MOST, return the child size instead of the parent size
         * (unless it is too big).
         */
        private static int getDefaultSize2(int size, int measureSpec) {
            int result = size;
            int specMode = MeasureSpec.getMode(measureSpec);
            int specSize = MeasureSpec.getSize(measureSpec);
    
            switch (specMode) {
                case MeasureSpec.UNSPECIFIED:
                    result = size;
                    break;
                case MeasureSpec.AT_MOST:
                    result = Math.min(size, specSize);
                    break;
                case MeasureSpec.EXACTLY:
                    result = specSize;
                    break;
            }
            return result;
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            setMeasuredDimension(
                    getDefaultSize2(getSuggestedMinimumWidth(), widthMeasureSpec),
                    getDefaultSize2(getSuggestedMinimumHeight(), heightMeasureSpec));
        }
    }

    可以看到在绘制方法没有绘制任何东西,那么性能也就几乎没有影响。

    实现代码与效果:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:divider="@drawable/divider"
        android:showDividers="middle|beginning|end">
    
        <TextView
            android:drawableLeft="@drawable/icon_1"
            android:drawableRight="@drawable/icon_4"
            android:drawablePadding="10dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:textSize="16sp"
            android:text="我的卡券"
            android:background="@color/white"
            android:gravity="center_vertical"
            android:layout_width="match_parent"
            android:layout_height="50dp" />
    
        <TextView
            android:drawableLeft="@drawable/icon_2"
            android:drawableRight="@drawable/icon_4"
            android:drawablePadding="10dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:textSize="16sp"
            android:text="地址管理"
            android:background="@color/white"
            android:gravity="center_vertical"
            android:layout_width="match_parent"
            android:layout_height="50dp" />
    
        <Space
            android:layout_width="match_parent"
            android:layout_height="15dp"/>
    
        <TextView
            android:drawableLeft="@drawable/icon_3"
            android:drawableRight="@drawable/icon_4"
            android:drawablePadding="10dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:textSize="16sp"
            android:text="检查更新"
            android:background="@color/white"
            android:gravity="center_vertical"
            android:layout_width="match_parent"
            android:layout_height="50dp" />
    
    </LinearLayout>

    Android开发中一些非常适用必须要知道的布局优化技巧

    出处:CSDN唯鹿

    Android开发中一些非常适用必须要知道的布局优化技巧转载http://www.codesocang.com/appboke/38385.html
    标签:网站源码