1.需求介绍

将已经编写好的布局文件,抽取到一个类中去做管理,下次还需要使用类似布局时,直接使用该组合控件的对象。

优点:可复用。

例如要重复利用以下布局:

<RelativeLayout
android:padding="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"> <TextView
android:id="@+id/tvSet_title"
android:textSize="18dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000"
android:text="自动更新设置" /> <TextView
android:id="@+id/tvSet_def"
android:textSize="18dp"
android:textColor="#000"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tvSet_title"
android:text="自动更新已关闭" /> <!--android:layout_alignParentRight="true" 设置控件在父控件的最右边-->
<!--android:layout_centerVertical="true" 垂直方向居中-->
<CheckBox
android:id="@+id/cbSet_1"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" /> <!--实现分割线的效果-->
<View
android:background="#000"
android:layout_marginTop="5dp"
android:layout_below="@id/tvSet_def"
android:layout_width="match_parent"
android:layout_height="1dp"/>
</RelativeLayout>

2.事件传递规则与相应规则

SettingActivity对应布局文件的根布局获取点击事件
此事件传递给SettingItemView控件

(1)点击在SettingItemView非CheckBox区域,事件就由SettingItemView去做响应
(2)点击在SettingItemView中CheckBox区域,事件就由SettingItemView传递给CheckBox,由CheckBox去做响应
CheckBox响应当前的点击事件,则SettingItemView就不能再去响应此事件,不能调用onClick方法,去改变状态

解决此问题的方案为:不让checkBox响应点击事件

3.自定义属性

在复用SettingItemView的时候,每一个条目对应的标示,描述内容都不一致。

解决方案:给自定义控件SettingItemView定义属性

(1)在res\values目录下新建attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="SetttingItemView">
<attr name="destitle" format="string"/>
<attr name="desoff" format="string"/>
<attr name="deson" format="string"/>
</declare-styleable>
</resources>

(2)自定义属性的使用

后3个属性就是自定义属性

safeguard替换掉原有android

com.example.administrator.test62360safeguard(工程的包名)必须这样编写,替换掉了android,代表当前应用自定义属性

<com.example.administrator.test62360safeguard.Utils.SetttingItemView
xmlns:safeguard="http://schemas.android.com/apk/res/com.example.administrator.test62360safeguard"
android:id="@+id/siv_update"
android:layout_width="match_parent"
android:layout_height="wrap_content"
safeguard:destitle="自动更新设置"
safeguard:desoff="自动更新已关闭"
safeguard:deson="自动更新已开启"
>

(3)获取属性值

在自定义控件类(SetttingItemView)中创建获取属性值的方法

/**
* @param attrs 自定义属性值
*/
private void initAttrs(AttributeSet attrs) {
destitle=attrs.getAttributeValue(NAMESPACE,"destitle");
desoff=attrs.getAttributeValue(NAMESPACE,"desoff");
deson=attrs.getAttributeValue(NAMESPACE,"deson");
}

4.实现步骤

(1)将组合控件的布局,抽取到一个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"> <RelativeLayout
android:padding="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"> <TextView
android:id="@+id/tvSet_title"
android:textSize="18dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000"
android:text="自动更新设置" /> <TextView
android:id="@+id/tvSet_def"
android:textSize="18dp"
android:textColor="#000"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tvSet_title"
android:text="自动更新已关闭" /> <!--android:layout_alignParentRight="true" 设置控件在父控件的最右边-->
<!--android:layout_centerVertical="true" 垂直方向居中-->
<!--android:clickable="false"-->
<!--android:focusable="false"-->
<!--android:focusableInTouchMode="false" 让当前的CheckBox不能被点击,即不能相应事件-->
<CheckBox
android:id="@+id/cbSet_1"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:layout_width="wrap_content"
android:layout_height="wrap_content" /> <!--实现分割线的效果-->
<View
android:background="#000"
android:layout_marginTop="5dp"
android:layout_below="@id/tvSet_def"
android:layout_width="match_parent"
android:layout_height="1dp"/>
</RelativeLayout>
</RelativeLayout>

(2)通过一个单独的类,去加载此段布局文件

获取自定义的属性值,并将属性值的内容赋值给自定义控件;

package com.example.administrator.test62360safeguard.Utils;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.CheckBox;
import android.widget.RelativeLayout;
import android.widget.TextView; import com.example.administrator.test62360safeguard.R; //通过一个单独的类,去加载此段布局文件,由于布局采用相对布局,所以此类需继承RelativeLayout
public class SetttingItemView extends RelativeLayout {
CheckBox cbSet_1;
TextView tvSet_def;
String destitle;
String desoff;
String deson;
private static final String NAMESPACE="http://schemas.android.com/apk/res/com.example.administrator.test62360safeguard";
//使得该方法调用第二个构造方法
public SetttingItemView(Context context) {
this(context,null);
} //使得该方法调用第三个构造方法
public SetttingItemView(Context context, AttributeSet attrs) {
this(context, attrs,0);
} public SetttingItemView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//将xml转化为一个view对象,直接添加到当前的SetttingItemView对应的view中
View.inflate(context, R.layout.setting_item_view,this);
TextView tvSet_title=findViewById(R.id.tvSet_title);
tvSet_def=findViewById(R.id.tvSet_def);
cbSet_1=findViewById(R.id.cbSet_1); //获取自定义以及原生属性
initAttrs(attrs);
//获取布局文件中定义的字符串,赋值给自定义组合控件的标题
tvSet_title.setText(destitle);
tvSet_def.setText(desoff);
} /**
* @param attrs 自定义属性值
*/
private void initAttrs(AttributeSet attrs) {
destitle=attrs.getAttributeValue(NAMESPACE,"destitle");
desoff=attrs.getAttributeValue(NAMESPACE,"desoff");
deson=attrs.getAttributeValue(NAMESPACE,"deson");
} //判断SetttingItemView组件是否被选中,true(选中),false(未选中)
public boolean isChecked(){
//SetttingItemView组件是否被选中与该自定义组件内部的checkbox的状态绑定
return cbSet_1.isChecked();
} //切换选中状态
public void setChecked(boolean isCheck){
if(isCheck){
cbSet_1.setChecked(isCheck);
tvSet_def.setText(deson);
}else {
cbSet_1.setChecked(isCheck);
tvSet_def.setText(desoff);
}
} }

(3)自定义组合控件在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=".SettingActivity"> <!--调用可复用的样式-->
<TextView
style="@style/TitleStyle"
android:text="设置中心"/>
<!--使用自定义的组合控件-->
<com.example.administrator.test62360safeguard.Utils.SetttingItemView
xmlns:safeguard="http://schemas.android.com/apk/res/com.example.administrator.test62360safeguard"
android:id="@+id/siv_update"
android:layout_width="match_parent"
android:layout_height="wrap_content"
safeguard:destitle="自动更新设置"
safeguard:desoff="自动更新已关闭"
safeguard:deson="自动更新已开启"
>
</com.example.administrator.test62360safeguard.Utils.SetttingItemView> <com.example.administrator.test62360safeguard.Utils.SetttingItemView
xmlns:safeguard="http://schemas.android.com/apk/res/com.example.administrator.test62360safeguard" android:layout_width="match_parent"
android:layout_height="wrap_content"
safeguard:destitle="电话归属地显示设置"
safeguard:desoff="归属地显示已关闭"
safeguard:deson="归属地显示已开启"
>
</com.example.administrator.test62360safeguard.Utils.SetttingItemView> </LinearLayout>

(4)UI界面应用

package com.example.administrator.test62360safeguard;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View; import com.example.administrator.test62360safeguard.ViewUtil.SetttingItemView; public class SettingActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_setting);
initUpdate();
} private void initUpdate() {
final SetttingItemView siv_update=findViewById(R.id.siv_update);
siv_update.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//获取之前的选中状态
boolean isCheck=siv_update.isChecked();
//将原有状态取反,设置为当前状态
siv_update.setChecked(!isCheck);
}
});
}
}

5.效果图

       

014 Android 自定义组合控件的更多相关文章

  1. Android自定义组合控件详细示例 (附完整源码)

    在我们平时的Android开发中,有时候原生的控件无法满足我们的需求,或者经常用到几个控件组合在一起来使用.这个时候,我们就可以根据自己的需求创建自定义的控件了,一般通过继承View或其子类来实现. ...

  2. Android自定义组合控件

    今天和大家分享下组合控件的使用.很多时候android自定义控件并不能满足需求,如何做呢?很多方法,可以自己绘制一个,可以通过继承基础控件来重写某些环节,当然也可以将控件组合成一个新控件,这也是最方便 ...

  3. Android自定义组合控件内子控件无法显示问题

    今天自定义了一个组合控件,与到了个奇葩问题: 我自定义了一个RelativeLayout,这个layout内有多个子控件.但奇怪的是这些子控件一直显示不出来.调试了一下午,竟然是因为在获取(infla ...

  4. (转)android自定义组合控件

    原文地址:http://mypyg.iteye.com/blog/968646 目标:实现textview和ImageButton组合,可以通过Xml设置自定义控件的属性. 1.控件布局:以Linea ...

  5. android 自定义组合控件 顶部导航栏

    在软件开发过程中,经常见到,就是APP 的标题栏样式几乎都是一样的,只是文字不同而已,两边图标不同.为了减少重复代码,提高效率, 方便大家使用,我们把标题栏通过组合的方式定义成一个控件. 例下图: 点 ...

  6. Android自定义组合控件:UIScrollLayout(支持界面滑动及左右菜单滑动)

    一.前言: 我之前很早的时候,写过一篇<左右滑出菜单>的文章: http://blog.csdn.net/qingye_love/article/details/8776650 用的是对V ...

  7. Android 自定义组合控件

    1, you need to add this kind of code to the constructors of your custom view which must extend ViewG ...

  8. Android自定义控件之自定义组合控件

    前言: 前两篇介绍了自定义控件的基础原理Android自定义控件之基本原理(一).自定义属性Android自定义控件之自定义属性(二).今天重点介绍一下如何通过自定义组合控件来提高布局的复用,降低开发 ...

  9. Android 手机卫士--自定义组合控件构件布局结构

    由于设置中心条目中的布局都很类似,所以可以考虑使用自定义组合控件来简化实现 本文地址:http://www.cnblogs.com/wuyudong/p/5909043.html,转载请注明源地址. ...

随机推荐

  1. 未公开函数 NtQuerySystemInfoMation 遍历进程信息,获得进程的用户名(如: system,Admin..)

    目录 遍历进程用户名 代码例子 遍历进程用户名 代码例子 #include <windows.h> #include <iostream> #include <COMDE ...

  2. 重写Dijkstra

    啊我沙雕了,竟然以为DJ的邻接矩阵不用初始化.. #include<bits/stdc++.h> #define R register int using namespace std; / ...

  3. 纯JavaScript开发飞机大战项目

    开发工具: HBuilder 编程语言:JavaScript 其他技术:Html + Css 项目截图:   视频:   源代码:   在线观看地址: (暂无) 百度网盘下载地址: 请加QQ群:915 ...

  4. Spring boot 事务Transactional

    开启事务只需要加上注解@Transactional即可 // 默认情况下数据库的事务作用范围是在JapRepository 的crud上 // save 一旦执行成功,就会进行提交 // 开启事务后遇 ...

  5. [转]MATLAB 2018b 中文版下载与安装教程

    MATLAB R2018b_win64.iso 压缩包一个 MATLAB R2018b Win64 Crack 压缩包一个 一.下载与安装   1 下载中文原程序安装包和破解文件,链接: https: ...

  6. JVM Java字节码方法表与属性

    方法表 1.methods_count  method_info,前三个字段和field_info一样 2.方法的属性结构 方法中的每个属性都是一个attribut_info结构 JVM定义了部分at ...

  7. Spring事务原理分析--手写Spring事务

    一.基本概念和原理 1.Spring事务 基于AOP环绕通知和异常通知的 2.Spring事务分为编程式事务.声明事务.编程事务包括注解方式和扫包方式(xml) Spring事务底层使用编程事务(自己 ...

  8. 从库延迟增大,MySQL日志出现InnoDB: page_cleaner: 1000ms intended loop took 17915ms.

    今天同事负责的数据库从库出现从库延迟增大,MySQL日志InnoDB: page_cleaner: 1000ms intended loop took 17915ms. 了解原因,keepalived ...

  9. SpringBoot整合Quartz和H2的例子

    话不多说,直接上代码: pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xml ...

  10. 000 装docker

    直接参考别人的文章,经过验证,没有问题,需要网络. URL: https://www.cnblogs.com/qgc1995/archive/2018/08/29/9553572.html 我是虚拟机 ...