014 Android 自定义组合控件
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 自定义组合控件的更多相关文章
- Android自定义组合控件详细示例 (附完整源码)
在我们平时的Android开发中,有时候原生的控件无法满足我们的需求,或者经常用到几个控件组合在一起来使用.这个时候,我们就可以根据自己的需求创建自定义的控件了,一般通过继承View或其子类来实现. ...
- Android自定义组合控件
今天和大家分享下组合控件的使用.很多时候android自定义控件并不能满足需求,如何做呢?很多方法,可以自己绘制一个,可以通过继承基础控件来重写某些环节,当然也可以将控件组合成一个新控件,这也是最方便 ...
- Android自定义组合控件内子控件无法显示问题
今天自定义了一个组合控件,与到了个奇葩问题: 我自定义了一个RelativeLayout,这个layout内有多个子控件.但奇怪的是这些子控件一直显示不出来.调试了一下午,竟然是因为在获取(infla ...
- (转)android自定义组合控件
原文地址:http://mypyg.iteye.com/blog/968646 目标:实现textview和ImageButton组合,可以通过Xml设置自定义控件的属性. 1.控件布局:以Linea ...
- android 自定义组合控件 顶部导航栏
在软件开发过程中,经常见到,就是APP 的标题栏样式几乎都是一样的,只是文字不同而已,两边图标不同.为了减少重复代码,提高效率, 方便大家使用,我们把标题栏通过组合的方式定义成一个控件. 例下图: 点 ...
- Android自定义组合控件:UIScrollLayout(支持界面滑动及左右菜单滑动)
一.前言: 我之前很早的时候,写过一篇<左右滑出菜单>的文章: http://blog.csdn.net/qingye_love/article/details/8776650 用的是对V ...
- Android 自定义组合控件
1, you need to add this kind of code to the constructors of your custom view which must extend ViewG ...
- Android自定义控件之自定义组合控件
前言: 前两篇介绍了自定义控件的基础原理Android自定义控件之基本原理(一).自定义属性Android自定义控件之自定义属性(二).今天重点介绍一下如何通过自定义组合控件来提高布局的复用,降低开发 ...
- Android 手机卫士--自定义组合控件构件布局结构
由于设置中心条目中的布局都很类似,所以可以考虑使用自定义组合控件来简化实现 本文地址:http://www.cnblogs.com/wuyudong/p/5909043.html,转载请注明源地址. ...
随机推荐
- BurpSuite经常拦截firefox报文如success.txt的解决办法
因为工作需要经常使用Burp对收发报文进行检测,平时习惯使用火狐浏览器,但是火狐浏览器经常进行一些登录状态的检测,导致Burp拦截中出现大量的火狐报文,如http://detectportal.fir ...
- Python字符串转十六进制进制互转
def str_to_hex(s): return ' '.join([hex(ord(c)).replace('0x', '') for c in s]) def hex_to_str(s): ) ...
- bootstrap select 多选的用法,取值和赋值(取消默认选择第一个的对勾)
h5自带的select标签可以实现按住ctrl键多选的功能,但是样式及其难看. bootstrap select是很好用的前端插件 首先引入bootstrap和bootstrap-select的c ...
- 响应面分析 | response surface analysis | R代码
先开题,慢慢补充. 参考: 什么是响应面(RSM)分析 Response-Surface Methods in R, Using rsm In-class Examples with R Code R ...
- 微信小程序wx.uploadFile的两个坑
-- setImage:function(e){ var _this = this //坑1 wx.chooseImage({ count: , sizeType: ['original', 'com ...
- 使用hwclock读取rtc中的时间时报错"hwclock: ioctl(RTC_RD_TIME) to /dev/rtc0 to read the time failed: No such device or address"如何处理?
1. No such device or address 这一句表明当前的板子上没有这样的外设,检查设备树和硬件连接情况 2. 笔者是这样解决的 由于设备树中为rtc所指定的总线与硬件上的连接rtc的 ...
- leetcode 361.Bomb Enemy(lintcode 553. Bomb Enemy)
dp 分别计算从左到右.从右到左.从上到下.从下到上4个方向可能的值,然后计算所有为‘0’的地方的4个方向的值的最大值 https://www.cnblogs.com/grandyang/p/5599 ...
- DataSource接口 Connection pooling(连接池
一.DataSource接口是一个更好的连接数据源的方法: JDBC1.0是原来是用DriverManager类来产生一个对数据源的连接.JDBC2.0用一种替代的方法,使用DataSource的实 ...
- typescript命名空间
/* 命名空间: 在代码量较大的情况下,为了避免各种变量命名相冲突,可将相似功能的函数.类.接口等放置到命名空间内 同Java的包..Net的命名空间一样,TypeScript的命名空间可以将代码包裹 ...
- 时序数据库技术体系 – 初识InfluxDB(原理)
原贴地址:http://hbasefly.com/2017/12/08/influxdb-1/?qytefg=c4ft23 在上篇文章<时序数据库体系技术 – 时序数据存储模型设计>中笔者 ...