android-横状栏-自定义组合控件小试

前言

第一次写博客有些紧张,本人是一名大三学生,水平有限,如有错误请指证交流,也欢迎各式的话题讨论。

这是一篇关于自定义控件之组合控件的文章,主要实现了类似主流app上常见的横状栏(菜单列表)的简单组合封装。

贴一个目前项目中正在使用的效果:

Screenshot_20200417_232135_com.example.ctccp_副本.jpg

最终实现了:左图标、左文字、右文字、右图标、右箭头的内容定制,以及下划线、下划区域的定制。

需求:

因为目前的项目,本人负责个人中心的开发,所以难免要用到大量这样的横状栏去表示功能入口。但如果针对每一个横状栏都要重复地去写布局,就会使代码重复性、耦合度太高,也不便于修改。
于是想到自定义控件的方式来实现如上效果。

思路:

重温自定义控件的三种方式:
1.继承View:通过重写ondraw方法等,以绘图的方式自定义View。
2.继承ViewGroup:继承ViewGroup、LinearLayout、FrameLayout等。
3.组合控件:对已有控件进行组合封装,设置属性接口。
本文主要是基于组合控件。

实践:

1.布局编写
基本思路就是编写一个横状栏的布局文件,我们再在后面通过属性接口使用户可以通过属性的设置来选择哪些控件展示、展示的控件展示什么内容。

  <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/item_horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"
    android:orientation="vertical">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:padding="@dimen/padding_8"
       >

        <ImageView
            android:id="@+id/left_icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/padding_8"/>

        <TextView
            android:id="@+id/left_text"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:layout_marginLeft="@dimen/padding_8"
            android:textColor="@color/black"
            android:textSize="@dimen/text_size_normal_14" />

        <TextView
            android:id="@+id/right_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/margin_10"
            android:textColor="@color/hint_grey"
            android:textSize="@dimen/text_size_normal_14"
            />

        <ImageView
            android:id="@+id/right_icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/margin_8"
           />
        <ImageView
            android:id="@+id/right_arrow"
            android:layout_width="25dp"
            android:layout_height="30dp"
            android:layout_marginLeft="0dp"
            android:src="@drawable/ic_personal_info_arrow"
            />
    </LinearLayout>
    <View
        android:id="@+id/divide_line_view"
        android:layout_width="match_parent"
        android:layout_height="@dimen/view_size_1dp"
        android:background="@color/background_grey"
        android:visibility="gone" />
    <View
        android:id="@+id/divide_area_view"
        android:layout_width="match_parent"
        android:layout_height="@dimen/height_8"
        android:background="@color/background_grey"
        android:visibility="gone" />
</LinearLayout>

2.资源文件的编写
这里有关dimen尺寸定义以及图标资源文件就不列出了。
2.1色彩定义in colors.xml:

      <color name="white">#FFFFFF</color>
      <color name="black">#000000</color>
      <color name="hint_grey">#b7b7b7</color>
      <color name="background_grey">#F6F6F6</color>

2.2属性定义in attrs.xml:

一般属性的类型有下面这九种:

foromat 解释
color 颜色值
boolean 布尔值
dimesion 尺寸值
float 浮点值
integer 整型值
string 字符串
fraction 百分数
enum 枚举值
reference 引用资源文件

在<declare-styleable name="ItemHorizontal"> 中给自己定义的横状栏起一个名字,这个名字用来在自定义控件中获取相关属性。
<attr name="left_text" format="string"/> 自定义所需要的属性名称,以及这个属性的类型。

<declare-styleable name="ItemHorizontal">
        <attr name="left_text" format="string" />
        <attr name="left_icon" format="reference" />
        <attr name="right_text" format="string" />
        <attr name="right_icon" format="reference" />
        <attr name="is_show_right_icon" format="boolean" />
        <attr name="is_show_left_icon" format="boolean" />
        <attr name="is_show_right_arrow" format="boolean" />
        <attr name="divide_line_style" format="integer" />
</declare-styleable>

注:styleable标签可以不写。去除styleable标签后在第3步的typedArray获取属性时传入对应常量即可。

3.继承ViewGroup子类
实际上这就是我们前面提到的三种自定义控件方式中的第二种。

package com.example.personalcenter.ui.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.personalcenter.R;


public class ItemHorizontal extends FrameLayout {
    private Context mContext;
    private View mView;
    private TextView leftTv;
    private TextView rightTv;
    private ImageView leftImageView;
    private ImageView rightImageView;
    private ImageView rightArrow;

    public static final int NO_LINE = 0;
    public static final int DIVIDE_LINE = 1;
    public static final int DIVIDE_AREA = 2;

    private String leftText;
    private String rightText;
    boolean isShowLeftIcon;
    boolean isShowRightIcon;
    boolean isShowRightArrow;
    private int divideLineStyle = NO_LINE;

    public String getLeftText() {
        return leftText;
    }

    public void setLeftImageView(boolean isLeftIconShow, int iconImgId) {
        if (isLeftIconShow) {
            if (iconImgId != 9102) {
                leftImageView.setImageResource(iconImgId);
            }
        } else {
            leftImageView.setVisibility(GONE);
        }
    }

    public void  setRightImageView(boolean isRightIconShow, int iconImgId) {
        if (isRightIconShow) {
            if (iconImgId != 9102) {
                rightImageView.setImageResource(iconImgId);
            }
        } else {
            rightImageView.setVisibility(GONE);
        }
    }

    public void  setRightArrowView(boolean isRightArrowShow) {
        if (!isRightArrowShow) {
            rightArrow.setVisibility(INVISIBLE);
        }
    }

    public void setLeftText(String leftText) {
        if (leftText != null) {
            this.leftText = leftText;
            leftTv.setText(leftText);
        }
    }

    public String getRightText() {
        return rightText;
    }

    public void setRightText(String rightText) {
        if (rightText != null) {
            this.rightText = rightText;
            rightTv.setText(rightText);
        }
    }



    public void setDivideLineStyle(int divideLineLineStyle) {
        View lineView = findViewById(R.id.divide_line_view);
        View areaView = findViewById(R.id.divide_area_view);
        if(divideLineLineStyle==DIVIDE_LINE){
            lineView.setVisibility(VISIBLE);
        }
        else if (divideLineLineStyle == DIVIDE_AREA ) {
            areaView.setVisibility(VISIBLE);
        }
    }

    public ItemHorizontal(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        init(context, attributeSet);

    }

    public void init(Context context, AttributeSet attributeSet) {
        mContext = context;
        LayoutInflater.from(context).inflate(R.layout.item_horizontal, this);

        leftTv = (TextView) findViewById(R.id.left_text);
        rightTv = (TextView) findViewById(R.id.right_text);
        leftImageView = (ImageView) findViewById(R.id.left_icon);
        rightImageView = (ImageView) findViewById(R.id.right_icon);
        rightArrow=(ImageView)findViewById(R.id.right_arrow);

        TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.ItemHorizontal);

        isShowLeftIcon = typedArray.getBoolean(R.styleable.ItemHorizontal_is_show_left_icon, false);
        isShowRightIcon = typedArray.getBoolean(R.styleable.ItemHorizontal_is_show_right_icon, false);
        isShowRightArrow= typedArray.getBoolean(R.styleable.ItemHorizontal_is_show_right_arrow, true);
        divideLineStyle = typedArray.getInt(R.styleable.ItemHorizontal_divide_line_style, NO_LINE);

        setLeftImageView(isShowLeftIcon, typedArray.getResourceId(R.styleable.ItemHorizontal_left_icon, 9102));
        setRightImageView(isShowRightIcon,typedArray.getResourceId(R.styleable.ItemHorizontal_right_icon, 9102));
        setRightArrowView(isShowRightArrow);
        setLeftText(typedArray.getString(R.styleable.ItemHorizontal_left_text));
        setRightText(typedArray.getString(R.styleable.ItemHorizontal_right_text));
        setDivideLineStyle(divideLineStyle);

        typedArray.recycle();//注意回收
    }
}

最终使用

 <com.example.personalcenter.ui.widget.ItemHorizontal
                android:id="@+id/ih_settings_account"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:right_text="@string/settings_account_safe"
                app:is_show_right_icon="true"
                app:right_icon="@drawable/ic_settings_safe"
                app:left_text="@string/settings_account"
                app:divide_line_style="1"/>

这样就可以达到最开始那张图的效果啦,具体的样式变化通过属性设置就可以达到定制的效果。
至此,一个基本的自定义组合控件流程就宣告完成。

拓展:

但在这个流程中,相信还可能会出现不少疑问:
1.AttributeSet与TypedArray间的联系?
2.typedeArray是什么?为什么要使用TypedArray

如果理解了这些,那相信以后再遇到自定义组合控件的开发任务就会驾轻就熟啦。
这些内容在鸿洋大神的这篇博客中已经讲的很清楚,这里就不再赘述了。想要学习的朋友点击下方链接即可。
[鸿洋大神的博客]https://blog.csdn.net/lmj623565791/article/details/45022631/

后记

唔,一直有写博客的想法,但是始终因为各种各样的原因而一再推迟。终于,在这个安静的夜晚,我决定使用简书来记录我的日常感悟与开发心得。

不知怎得,突然就想起《邪不压正》里这两人的对话:“正经人谁写日记啊?”,“你写日记吗?”

image
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352