• 布局优化技巧笔记


    在实际开发中怎样尽可能的降低层级、降低控件数量,并达到相同的视觉效果?本文记录开发过程中的实践。

    1. 降低 ImageView 的数目

    1.1 使用 TextView.drawableXXX

    如大众点评APP的首页:



    注意红色框内的部分

    红色框住的部分。由一张图片和它以下的文字组成,至少有两种实现方式:

    1. ImageView + TextView,图在上文字在下;
    2. TextView,设置 TextView.drawableTop=”xxx”。

    显然第2种方式能够省掉 ImageView。

    另一种情况,还是拿我经常使用的大众点评 APP 中的页面作为样例。见下图:



    注意最右边的箭头

    我们能够用例如以下的布局实现:

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:drawableRight="@drawable/arrow"
            android:gravity="center_vertical"
            android:text="查看所有网友点评"
            android:textSize="16sp" />

    除非 android:layout_width = “wrap_content”,否则即使把 android:gravity 属性改成 center,箭头仍然是居右的。这是非常恶心的地方,导致我们无法将文本和 drawable 一起居中(解决方法见 自己定义控件让TextView、Button的drawableLeft和drawableRight与文本一起居中显示),可是我们却能够利用这一点实现上述布局。

    1.2 使用 layer-list 画线

    经经常使用到横线。最直观的实现方法是放一张图片,事实上这张图片能够省掉。

    相同以大众点评APP的页面为例:



    注意“网友推荐”以下横线(右边的小手能够用1.1的方法实现哦)

    当然能够用 ImageView 实现。
    或者换种方法:将“网友推荐”所在的 layout 的 background 属性设置为:

    background="@drawale/bg_line"

    当中 bg_line.xml :

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item>
            <shape>
                <solid android:color="#DADADA" />
            </shape>
        </item>
        <item android:bottom="1px">
            <shape>
                <solid android:color="@color/white" />
            </shape>
        </item>
    </layer-list>

    2 个 item 画了 2 个层叠的矩形。下层矩形填充色是 #DADADA,上层矩形的填充色是白色。并且上层矩形的下边框比下层矩形的下边框高 1px,于是就有宽 1px、颜色为 #DADADA 的矩形区域显示出来。看起来就是一条横线。

    2. 使用 ViewStub

    3. 使用 merge

    4. 使用 ClickableSpan



    注意红色框中不同颜色的文本

    使用 ClickableSpan 富文本实如今同一个 TextView 中的文本的颜色、大小、背景色等属性的多样化和个性化。例如以下图红色框内是一个 TextView(也可能是多个 TextView),可是却有两种不同的颜色,这样的效果就能够用 Spannale 实现:

    Spannable richText = new Spannale("<font color=#E3E5F3>Alan海波</font>回复<font color=#E3E5F3>大赞</font>:你走开···");
    textView.setText(richText);

    假设不仅颜色不同,还要对某些文字加入响应事件(如跳转链接等),能够使用例如以下方式:

    String username = "Alan 海波";
    String content = "你走开……";
    SpannableString spannableString = new SpannableString(username);
    ClickableSpan span = new ClickableSpan() {
        @Override
        public void onClick(View widget) {
        // do sth.    
        }
    
        @Override
        public void updateDrawState(TextPaint ds) {
            ds.setColor(getResources().getColor(R.color.link_color));
            ds.setUnderlineText(false);
        }
    };
    spannableString.setSpan(span, 0, username.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
    
    Spanned replyText = Html.fromHtml("<font color=" + getColor(R.color.deep_gray) + ">回复</font>");
    Spanned colon = Html.fromHtml("<font color=" +getColor(R.color.link_color) + ">:</font>");
    Spanned body = Html.fromHtml("<font color=" + getColor(R.color.text_color) + ">" + content + "</font>");
    Spanned richText = (Spanned) android.text.TextUtils.concat(spannableString, replyText, spannableString, colon, body);
    textView.setText(richText);
    tv.setMovementMethod(LinkMovementMethod.getInstance());

    注意:

    • Html.fromHtml(string) 会将 string 中的 ‘ ’ 和 ‘ ’ 替换成空格,须要显式的将 ‘ ’(早期 Mac 系统)和 ‘ ’ (Unix 和 Max OS X)和 ‘ ’(Windows) 替换成 html 识别的 ‘< br>’,不替换的话,假设 string 中出现 “xx&xx ” 形式的子串,会发生 IOException:
    Html.fromHtml(string.replace("
    ", "< br>").replace("
    ", "< br>")).replace("
    ", "< br>"));
    <a href="...">
    <b>
    <big>
    <blockquote>
    <br>
    <cite>
    <dfn>
    <div align="...">
    <em>
    <font size="..." color="..." face="...">
    <h1>
    <h2>
    <h3>
    <h4>
    <h5>
    <h6>
    <i>
    <img src="...">
    <p>
    <small>
    <strike>
    <strong>
    <sub>
    <sup>
    <tt>
    <u>

    有支持所有的 HTML tag 标签的库,详细见 https://github.com/NightWhistler/HtmlSpanner

    5. 代码格式化

    使用 Cmd + Alt + L(Mac)。Ctrl+Alt+L (Windows)快捷键格式化 layout 代码,使得属性排列更加规范。

    6. 资源文件命名

    很多其它信息请參考 该站点

    控件类型 前缀 演示样例
    Action bar ab_ ab_stacked.9.png
    Button btn_ btn_send_pressed.9.png
    Dialog dialog_ dialog_top.9.png
    Divider divider_ divider_horizontal.9.png
    Icon ic_ ic_star.png
    Menu menu_ menu_submenu_bg.9.png
    Notification notification_ notification_bg.9.png
    Tabs tab_ tab_pressed.9.png


    图标资源的命名:

    资源类型 前缀 演示样例
    Icons ic_ ic_star.png
    Launcher icons ic_launcher ic_launcher_calendar.png
    Action bar icons ic_menu iic_menu_archive.png
    Status bar icons ic_stat_notify ic_stat_notify_msg.png
    Tab icons ic_tab ic_tab_recent.png
    Dialog icons ic_dialog ic_dialog_info.png
    PopupWindow icons ic_pop ic_dialog_like.png


    按压态的命名:

    状态 后缀 演示样例
    Normal _normal btn_order_normal.9.png
    Pressed _pressed btn_order_pressed.9.png
    Focused _focused btn_order_focused.9.png
    Disabled _disabled btn_order_disabled.9.png
    Selected _selected btn_order_selected.9.png


    简单的project建议使用上述前缀来差别文件的类型。
    复杂的project,建议以 module_ (如,个人中心模块的前缀为 account_。account_ic_launcher_calendar.png)作为前缀命名,公用的资源能够使用 base_ 或 common_ 作为前缀,这样命名有例如以下优点:

    • 格式整齐。易读性强;
    • 清理废弃资源文件时,比方使用 lint 来检查废弃资源时,方便划分责任范围;
    • 防止出现引用非本module资源文件的发生;

    7. 自己定义 View

    假设使用现有的控件特别是 layout 不能非常多好的满足需求。我们能够自己定义 View 完毕。

    比方微信头像墙的这个效果:


    我们能够用 LinearLayout 实现。每一行都是一个 LinearLayout。可是这样层级较多(当然,盲目的降低层级也是不推荐的,由于 view 的绘制过程是由 meassure、layout、draw 三个过程完毕的。层级会降低 draw 的时间,可是可能会添加 meassure 的时间。甚至得不偿失)。

    我们也能够自己定义一个 layout。在水平方向上放置子 view,空间不足时自己主动换行。

  • 相关阅读:
    出现“尝试读取或写入受保护的内存。这通常指示其他内存已损坏”的解决方法
    angular中的:class的使用
    Vue中的:class的使用
    audio 音乐自动播放,循环播放,隐藏等
    vue放大缩小视图窗口按钮
    js获取显示器、页面等高度 (转)
    在 vue 中添加错误与成功提示的代码段
    在 vue 中添加初始化代码段
    学习react基本语法初始化webpack.pub.config.js
    学习react基本语法初始化webpack.config.js
  • 原文地址:https://www.cnblogs.com/jzssuanfa/p/7053125.html
Copyright © 2020-2023  润新知