继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Android编辑信息界面,组合控件的封装

哈士奇WWW
关注TA
已关注
手记 370
粉丝 70
获赞 400

效果图

组合控件1.png

组合控件2.PNG

在很多APP当中,有些页面需要填写很多资料,比如个人中心,还有一些页面,点击每个Item都要跳转页面或者弹框选择。这样的组合控件,相信大家都见过,说到这里,可能有人不服了,不就是一个线性布局或者相对布局吗,我分分钟写出来。是的,我承认你可以搞定,因为我以前也是一个个布局嵌套写出来的,但是我想说,这么多相似的重复布局,你难道真的要一个个去写吗?复制粘贴一个个改,而且有些功能是重复的,比如输入框那个清除输入内容按钮,你也去写,你累吗?这样的代码看上去可读性高吗?所以,我今天就是来和大家一起解决这个问题的,我们完全可以把这种组合控件封装起来,然后专注于处理我们的业务逻辑就好。

实现步骤

1、分析布局(以组合控件1为例子来分析)
从上面图我们可以看出,每一个Item的布局从左往右依次是:标题,输入框,清除输入的按钮,向右的箭头。前2个Item,我们点击中间输入框的时候,直接跳出来软键盘,直接输入文字内容,当有内容的时候,显示清除按钮,没有内容的时候,隐藏清除按钮。后2个Item,是带箭头的,是不可以输入的,提示我们这一项是用来跳转或者点击弹出选择框等。

选择城市.jpg

上面这些个Item的布局很简单,大致结构是这样的

<LinearLayout>
    <LinearLayout>
        <TextView />
        <EditText />
        <!--清除输入内容-->
        <ImageView />
        <!--点击跳转或者弹出选择框-->
        <ImageView />
    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/item_group_divider" /></LinearLayout>

然后每一项都这么写一个相似的LinearLayout,然后如果没有右边的箭头,我们又把它去掉,如果我们的项目中也有这种类似的item,而且有很多,那么这个界面的layout的代码会显得很臃肿,维护起来也不清晰。

所以我根据我的项目把这种组合控件封装了一个,可能扩展性不是那么好,但是代码少,思路清晰,符合我的项目需求,你拿过去做适当调整也能用。

下面来介绍怎样封装成为一个通用的控件

2、Item的布局 item_group_layout.xml

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

    <LinearLayout
        android:id="@+id/item_group_layout"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:background="@color/white"
        android:gravity="center_vertical"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/title_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:textColor="@color/item_group_title"
            android:textSize="15sp"
            tools:text="姓名" />

        <EditText
            android:id="@+id/content_edt"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@null"
            android:gravity="center_vertical|end"
            android:hint="请输入姓名"
            android:singleLine="true"
            android:paddingStart="10dp"
            android:textColor="@color/item_group_edt"
            android:textSize="13sp" />
        
        <!--清除输入内容-->
        <ImageView
            android:id="@+id/clear_iv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="10dp"
            android:padding="8dp"
            android:scaleType="centerCrop"
            android:src="@mipmap/close" />
        
        <!--点击跳转或者弹出选择框-->
        <ImageView
            android:id="@+id/jt_right_iv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="7dp"
            android:padding="8dp"
            android:scaleType="centerCrop"
            android:src="@mipmap/jiantou_right" />
    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/item_group_divider" /></LinearLayout>

3.首先新建一个类,继承自FrameLayout,实现对应的构造方法
我们引入刚才Item的布局,把它添加到这个FrameLayout

public class ItemGroup extends FrameLayout implements View.OnClickListener {    private LinearLayout itemGroupLayout; //组合控件的布局
    private TextView titleTv; //标题
    private EditText contentEdt; //输入框
    private ImageView clearIv; //清楚输入内容
    private ImageView jtRightIv; //向右的箭头
    private ItemOnClickListener itemOnClickListener; //Item的点击事件
  
  public ItemGroup(@NonNull Context context) {        super(context);
        initView(context);
    }    public ItemGroup(@NonNull Context context, @Nullable AttributeSet attrs) {        super(context, attrs);
        initView(context);
    }    public ItemGroup(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {        super(context, attrs, defStyleAttr);
        initView(context);
    }    //初始化View
    private void initView(Context context) {
        View view = LayoutInflater.from(context).inflate(R.layout.item_group_layout, null);
        itemGroupLayout = (LinearLayout) view.findViewById(R.id.item_group_layout);
        titleTv = (TextView) view.findViewById(R.id.title_tv);
        contentEdt = (EditText) view.findViewById(R.id.content_edt);
        clearIv = (ImageView) view.findViewById(R.id.clear_iv);
        jtRightIv = (ImageView) view.findViewById(R.id.jt_right_iv);
        addView(view); //把自定义的这个组合控件的布局加入到当前FramLayout}
}

**4.属性的定义,在完成类的创建后,来自定义相关属性 
首先需要在values目录下面新建一个attrs.xml文件 , 自定义相关属性,**

其定义格式如下:

<declare-styleable name="自定义属性名称">
    <attr name="属性名称" format="属性类型"/></declare-styleable>
<?xml version="1.0" encoding="utf-8"?><resources>
    <declare-styleable name="ItemGroup">
        <!--标题的文字-->
        <attr name="title" format="string" />
        <!--标题的字体大小-->
        <attr name="title_size" format="dimension" />
        <!--标题的字体颜色-->
        <attr name="title_color" format="color" />
        <!--输入框的内容-->
        <attr name="edt_content" format="string" />
        <!--输入框的字体大小-->
        <attr name="edt_text_size" format="dimension" />
        <!--输入框的字体颜色-->
        <attr name="edt_text_color" format="color" />
        <!--输入框提示的内容-->
        <attr name="edt_hint_content" format="string" />
        <!--输入框的提示字体的字体颜色-->
        <attr name="edt_hint_text_color" format="color" />
        <!--输入框是否可以编辑内容-->
        <attr name="isEditable" format="boolean"/>
        <!--向的右箭头图标是否可见-->
        <attr name="jt_visible" format="boolean"/>
        <!--item布局的内边距-->
        <attr name="paddingLeft" format="dimension"/>
        <attr name="paddingRight" format="dimension"/>
        <attr name="paddingTop" format="dimension"/>
        <attr name="paddingBottom" format="dimension"/>
        
        <attr name="drawable_left" format="reference" />
        <attr name="drawable_right" format="reference" />
        <attr name="line_color" format="color" />
        <attr name="line_height" format="integer" />
    </declare-styleable></resources>

属性类型主要包括: 
reference 引用 
color 颜色 
boolean 布尔值 
dimension 尺寸值 
float 浮点值 
integer 整型值 
string 字符串 
enum 枚举值

5.属性的引入,在定义完属性后,接下来将定义的属性值引入到类中
先获取到各属性,然后将引入的属性值设置到布局控件上。

 /**
     * 初始化相关属性,引入相关属性
     *
     * @param context
     * @param attrs
     */
    private void initAttrs(Context context, AttributeSet attrs) {        //标题的默认字体颜色
        int defaultTitleColor = context.getResources().getColor(R.color.item_group_title);        //输入框的默认字体颜色
        int defaultEdtColor = context.getResources().getColor(R.color.item_group_edt);        //输入框的默认的提示内容的字体颜色
        int defaultHintColor = context.getResources().getColor(R.color.item_group_edt);

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ItemGroup);
        String title = typedArray.getString(R.styleable.ItemGroup_title);        float paddingLeft = typedArray.getDimension(R.styleable.ItemGroup_paddingLeft, 15);        float paddingRight = typedArray.getDimension(R.styleable.ItemGroup_paddingRight, 15);        float paddingTop = typedArray.getDimension(R.styleable.ItemGroup_paddingTop, 5);        float paddingBottom = typedArray.getDimension(R.styleable.ItemGroup_paddingTop, 5);        float titleSize = typedArray.getDimension(R.styleable.ItemGroup_title_size, 15);        int titleColor = typedArray.getColor(R.styleable.ItemGroup_title_color, defaultTitleColor);
        String content = typedArray.getString(R.styleable.ItemGroup_edt_content);        float contentSize = typedArray.getDimension(R.styleable.ItemGroup_edt_text_size, 13);        int contentColor = typedArray.getColor(R.styleable.ItemGroup_edt_text_color, defaultEdtColor);
        String hintContent = typedArray.getString(R.styleable.ItemGroup_edt_hint_content);        int hintColor = typedArray.getColor(R.styleable.ItemGroup_edt_hint_text_color, defaultHintColor);        //默认输入框可以编辑
        boolean isEditable = typedArray.getBoolean(R.styleable.ItemGroup_isEditable, true);        //向右的箭头图标是否可见,默认可见
        boolean showJtIcon = typedArray.getBoolean(R.styleable.ItemGroup_jt_visible, true);
        typedArray.recycle();        //设置数据
        //设置item的内边距
        itemGroupLayout.setPadding((int) paddingLeft, (int) paddingTop, (int) paddingRight, (int) paddingBottom);
        titleTv.setText(title);
        titleTv.setTextSize(titleSize);
        titleTv.setTextColor(titleColor);

        contentEdt.setText(content);
        contentEdt.setTextSize(contentSize);
        contentEdt.setTextColor(contentColor);
        contentEdt.setHint(hintContent);
        contentEdt.setHintTextColor(hintColor);
        contentEdt.setFocusableInTouchMode(isEditable); //设置输入框是否可以编辑
        contentEdt.setLongClickable(false); //输入框不允许长按
        jtRightIv.setVisibility(showJtIcon ? View.VISIBLE : View.GONE);  //设置向右的箭头图标是否可见}

这里主要通过obtainStyledAttributes方法获取到一个TypedArray对象,然后通过TypedArray对象就可以获取到相对应定义的属性值,相关自定义View的内容,自行查阅

6、在完成上面的步骤以后,就算大体上封装好了,就可以在布局文件里面使用了

调用的xml布局文件

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.zx.itemgroup.MainActivity">

    <com.zx.itemgroup.ItemGroup
        android:id="@+id/name_ig"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:edt_hint_content="请输入姓名"
        app:jt_visible="false"
        app:paddingLeft="15dp"
        app:title="姓名" />

    <com.zx.itemgroup.ItemGroup
        android:id="@+id/id_card_ig"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:edt_hint_content="请输入身份证号"
        app:jt_visible="false"
        app:paddingLeft="15dp"
        app:title="身份证" />

    <com.zx.itemgroup.ItemGroup
        android:id="@+id/select_birthday_ig"
        android:layout_width="match_parent"
        android:layout_height="46dp"
        app:edt_hint_content="请选择出生日期"
        app:isEditable="false"
        app:paddingLeft="15dp"
        app:title="出生日期" />

    <com.zx.itemgroup.ItemGroup
        android:id="@+id/select_city_ig"
        android:layout_width="match_parent"
        android:layout_height="46dp"
        app:edt_hint_content="请选择您所在的城市"
        app:isEditable="false"
        app:paddingLeft="15dp"
        app:title="所在城市" /></LinearLayout>

调用的activity

/**
 * 组合控件封装(提交信息及编辑信息界面及功能)
 */public class MainActivity extends AppCompatActivity {    private Context mContext;    private ItemGroup nameIG, idCardIG, birthdayIG, cityIG;    @Override
    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mContext = this;
        initView();
    }    private void initView() {
        nameIG = (ItemGroup) findViewById(R.id.name_ig);
        idCardIG = (ItemGroup) findViewById(R.id.id_card_ig);
        birthdayIG = (ItemGroup) findViewById(R.id.select_birthday_ig);
        cityIG = (ItemGroup) findViewById(R.id.select_city_ig);
        birthdayIG.setItemOnClickListener(new ItemGroup.ItemOnClickListener() {            @Override
            public void onClick(View v) {
                Toast.makeText(mContext, "点击了选择出生日期", Toast.LENGTH_SHORT).show();
            }
        });
        cityIG.setItemOnClickListener(new ItemGroup.ItemOnClickListener() {            @Override
            public void onClick(View v) {
                Toast.makeText(mContext, "点击了选择城市", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

原文链接:http://www.apkbus.com/blog-927424-72832.html

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP