Android笔记--自定义View之组合控件

Android-自定义View

分享是最好的记忆--
如需转发请注明出处

[强调]:共同学习 共同进步 不喜勿喷

内容简介


  1. 前言
  2. 实现
  3. 总结

1. 前言


这次更新有2个目的
1. 复用控件,而不是每次都写冗余代码
2. 好久没有更新了(๑• . •๑)

在Android开发当中自定义View是一项不可或缺的技能,也是我们大部分小白以及小小白的软肋。
  自定义View其实也不是很难,因为我们不需要攻克什么技术难关,只需要坐在巨人的肩膀上,抱紧巨人的脑袋就行(ฅ>ω<*ฅ)
  自定义View分两大类:
一 : 组合 : 也就是在现有的控件基础上通过组合各种不同功能的控件来组合出功能更强大全民的新控件。
二 : 完全自定义:通过继承View或者ViewGroup来自定义全新的View。  今天讨论的自定义View是第一种方式,即组合方式。如果想了解完全自定义或者更多自定义方面的知识,推荐看扔物线大神以及张鸿翔大神的文章。

2. 实现


1. 确定需求

  功能列表中的Item是我们经常用到的控件之一。它也许是这样的:
item1.png

或者是这样的:
item2.png

再或者是这样的:
item3.png

  为了满足这些情况,我们抽象出功能最丰富的Item;确定了需求之后开始编码。

2. 编码

1. 自定义属性
  首先确定我们需要动态设置的属性;包括 :1-左边图片2-3-左边图片的宽高4-大标题5-大标题文字大小6-大标题文字颜色7-副标题8-副标题文字大小9-副标题文字颜色10-右边图片11-12-右边图片宽高等12个属性,当然不止这些,这个可以根据自己的需求丰富,比如 Item 下面是否显示阴影线条,右边图片是否显示等;
  那么在../res/attrs.xml中定义自定义属性;

<declare-styleable name="UILibraryListItem">
        <attr name="leftImg" format="reference"/>
        <attr name="leftImg_width" format="dimension"/>
        <attr name="leftImg_height" format="dimension"/>
        <attr name="rightImg" format="reference"/>
        <attr name="rightImg_width" format="dimension"/>
        <attr name="rightImg_height" format="dimension"/>
        <attr name="title" format="string"/>
        <attr name="title_color" format="color"/>
        <attr name="title_size" format="dimension"/>
        <attr name="subTitle" format="string"/>
        <attr name="subTitle_color" format="color"/>
        <attr name="subTitle_size" format="dimension"/>
</declare-styleable>

这里有必要解释一下属性定义中的format

name format 描述
资源 reference 通过id来指定资源
颜色 color 设置颜色
尺寸 dimension 长宽,字体大小等尺寸
字符串 String 设置文本
布尔值 boolean 通过布尔值设置
浮点值 float 设置浮点值
百分数 fraction 设置百分数值
枚举值 enum 设置枚举值
位或运算 flag 位或运算
整型值 integer 设置整型

属性定义时可以指定多种类型值

2.抽象组建
  这里说的抽象组建是把该Item可能有的所有功能都写出来;
../res/layout/item.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="wrap_content">
    <ImageView
        style="@style/UILibraryListItemBase"
        android:id="@+id/leftImg"
        android:layout_alignParentLeft="true"
        android:padding="8dp"
        />
    <TextView
        style="@style/UILibraryListItemBase"
        android:id="@+id/title"
        android:layout_toRightOf="@+id/leftImg"
        />
    <TextView
        style="@style/UILibraryListItemBase"
        android:id="@+id/subTitle"
        android:layout_toLeftOf="@+id/rightImg"
        android:layout_toRightOf="@+id/title"
        android:gravity="right"
        />
    <ImageView
        style="@style/UILibraryListItemBase"
        android:id="@+id/rightImg"
        android:layout_alignParentRight="true"
        android:padding="8dp"
        />
    <View
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:layout_alignBottom="@+id/leftImg"
        />
</RelativeLayout>

3.实现功能
选择一个适当的ViewGroup来继承,实现Item;
我的样式中rootView是个RelativeLayout,因此我继承了RelativeLayout。具体实现如下:

package com.uilib.ui.listitem;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.example.uilibrary.R;
import com.uilib.ui.util.FindView;

/**
 * Created by Elyar.Anwar on 2017/8/10.
 */

public class UILibraryListItem extends RelativeLayout {

    /**
     * 选项控件的左边图片
     */
    private ImageView leftImageView;

    /**
     * 选项控件的右边图片
     */
    private ImageView rightImageView;

    /**
     * 选项控件的标题
     */
    private TextView titleView;

    /**
     * 选项控件的副标题
     */
    private TextView subTitleView;

    /**
     * 左边图片资源
     */
    private Drawable leftImage;

    /**
     * 左边图片资源宽度
     */
    private int leftImageWidth;

    /**
     * 左边图片资源高度
     */
    private int leftImageHeight;

    /**
     * 右边图片资源
     */
    private Drawable rightImage;

    /**
     * 右边图片资源宽度
     */
    private int rightImageWidth;

    /**
     * 右边图片资源高度
     */
    private int rightImageHeight;

    /**
     * 标题文本
     */
    private String title;

    /**
     * 标题文本颜色
     */
    private int titleTextColor;

    /**
     *标题文本字体大小
     */
    private float titleTextSize;

    /**
     *副标题文本
     */
    private String subTitle;

    /**
     *副标题文本颜色
     */
    private int subTitleTextColor;

    /**
     *副标题文本字体大小
     */
    private float subTitleTextSize;

    /**
     *上下文
     */
    private Context mContext;

    /**
     * 属性结合
     */
    private AttributeSet attrs;

    public UILibraryListItem(Context context) {
        this(context,null);
    }

    public UILibraryListItem(Context context, AttributeSet attrs) {
        this(context, attrs,0);
        this.mContext = context;
        this.attrs = attrs;
        init();
    }

    public UILibraryListItem(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mContext = context;
        this.attrs = attrs;
        init();
    }

    /**
     * 初始化视图
     */
    private void init() {
        View.inflate(mContext, R.layout.listitem, this);
        findView();//绑定视图
        loadParams();//加载属性值
        initView();//为视图赋值
    }

    /**
     *  为控件赋值
     */
    private void initView() {
        if(leftImage!=null){
            leftImageView.setImageDrawable(leftImage);
        }
        leftImageView.getLayoutParams().width = leftImageWidth;
        leftImageView.getLayoutParams().height = leftImageHeight;

        if(rightImage!=null){
            rightImageView.setImageDrawable(rightImage);
        }
        rightImageView.getLayoutParams().width = rightImageWidth;
        rightImageView.getLayoutParams().height = rightImageHeight;

        if (!TextUtils.isEmpty(title)){
            titleView.setText(title);
            titleView.setTextColor(titleTextColor);
            titleView.setTextSize(titleTextSize);
        }
        if (!TextUtils.isEmpty(subTitle)){
            subTitleView.setText(subTitle);
            subTitleView.setTextColor(subTitleTextColor);
            subTitleView.setTextSize(subTitleTextSize);
        }
    }


    /**
     * 初始化控件的属性
     */
    private void loadParams() {
        TypedArray typedArray = mContext.obtainStyledAttributes(attrs,R.styleable.UILibraryListItem);
        leftImage = typedArray.getDrawable(R.styleable.UILibraryListItem_leftImg);
        leftImageHeight = typedArray.getDimensionPixelSize(R.styleable.UILibraryListItem_leftImg_height,128);
        leftImageWidth = typedArray.getDimensionPixelSize(R.styleable.UILibraryListItem_leftImg_width,128);

        rightImage = typedArray.getDrawable(R.styleable.UILibraryListItem_rightImg);
        rightImageHeight = typedArray.getDimensionPixelSize(R.styleable.UILibraryListItem_rightImg_height,128);
        rightImageWidth = typedArray.getDimensionPixelSize(R.styleable.UILibraryListItem_rightImg_width,128);

        title = typedArray.getString(R.styleable.UILibraryListItem_title);
        titleTextColor = typedArray.getColor(R.styleable.UILibraryListItem_title_color,Color.BLACK);
        titleTextSize = typedArray.getDimensionPixelSize(R.styleable.UILibraryListItem_title_size,20);

        subTitle = typedArray.getString(R.styleable.UILibraryListItem_subTitle);
        subTitleTextColor = typedArray.getColor(R.styleable.UILibraryListItem_subTitle_color,Color.GRAY);
        subTitleTextSize = typedArray.getDimensionPixelSize(R.styleable.UILibraryListItem_subTitle_size,14);
        typedArray.recycle();
    }

    /**
     * 关联控件
     */
    private void findView() {
        leftImageView =  FindView.findView(this,R.id.leftImg);
        rightImageView = FindView.findView(this,R.id.rightImg);
        titleView = FindView.findView(this,R.id.title);
        subTitleView = FindView.findView(this,R.id.subTitle);
    }


}

4.引用并预览
  引用时为了看出明显效果我定义了2个Item;

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:uilib="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <com.uilib.ui.listitem.UILibraryListItem
        android:id="@+id/it"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        uilib:leftImg="@drawable/icon_a"
        uilib:rightImg="@drawable/icon_b"
        uilib:subTitle="SubTitle"
        uilib:title="Title" />

    <com.uilib.ui.listitem.UILibraryListItem
        android:id="@+id/it2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        uilib:leftImg="@drawable/test_icon_allow"
        uilib:subTitle="SubTitle"
        uilib:subTitle_color="@color/red"
        uilib:title="Title" />
</LinearLayout>

于是完成结果如下:
2017-08-11_004205.png

可以根据自己的实际情况灵活改变样式,且仅仅在第四步引用处做出更改即可;

总结


自定义View之组合;
通过组合来自定义View能满足我们大部分的需求,且相对容易。
总结其过程:
1.自定义属性
2.抽象出样式
3.编码实现类
4.引用和预览

我是ElyarAnwar,在技术的道路上摸爬滚打;
热爱生活,热爱技术;如果喜欢记得点赞;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 174,539评论 25 709
  • 一三五 二四六 时光拂过发梢 梧桐叶落生生 时光的墙板上 写满了 两千一百多昼夜呢喃 人来人往的路口 抬头 是你笑...
    往往以往阅读 183评论 2 0
  • 源码来自时序数据库InfluxDB的高可用套件InfluxDB-relay.
    lwhile阅读 238评论 0 0
  • 对越南的向往,是源于岘港那间占婆博物馆。 说了好几年,错过了好几次,终于成行。和从未想过一起出行的人出行(相关文章...
    黄小智子阅读 428评论 0 0
  • 经年故纸遗长恨,转眼成非 ,转眼成非,昨日深红已半飞。 丝弦和尽黄昏雨,一缕相催,一缕相催 ,渐有心思散作灰。
    baobei朵朵阅读 286评论 0 0