自定义组合控件思路:
1 将已经编写好的布局文件,抽取到一个类中去管理,下次还需要用到此布局的时候直接使用组合控件对应得对象
2 将组合的控件布局抽取到单独的xml中
3 通过单独的类加载布局文件
实现过程
1
<?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:id="@+id/activity_setting"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.administrator.mobilesafe.SettingActivity"
android:orientation="vertical">
<!-- 自定义组合控件-->
<!-- 相随布局内部由四个控件组成的一个布局 -->
<!-- 后面还需用到 只是有一些小改变
故可以吧控件抽取到单独的一个类中去管理 以后在布局文件中添加此类可以达到效果-->
<RelativeLayout
android:padding="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="自动更新设置"
android:textColor="#000"
android:textSize="18sp"/>
<TextView
android:layout_below="@+id/tv_title"
android:id="@+id/tv_des"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="自动更新已关闭"
android:textColor="#000"
android:textSize="18sp"/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/cb_box"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#000"
android:layout_below="@+id/tv_des"
/>
</RelativeLayout>
</LinearLayout>
2 吧RelativeLayout抽取到单独的layout中
3
自定义类
package com.example.administrator.mobilesafe.View;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.RelativeLayout;
/**
* Created by Administrator on 2017/9/7.
*/
// 布局也属于View控件
public class SettingItemView extends RelativeLayout {
// 直接用此类new 对象时调用此方法
public SettingItemView(Context context) {
super(context);
}
// 在xml布局使用此类对象时调用此方法
public SettingItemView(Context context, AttributeSet attrs) {
super(context, attrs);
}
// 含有主题的调用时用到此方法
public SettingItemView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
自定义view属性:
<!-- 复用SettignItemView 时 要可以更换title des文字内容
就像textView的text属性一样 用到自定义属性-->
<!-- 查看源码定义属性做法
SDK所在目录\platforms\android-24(我的版本)\data\res\values\attr.xml
1 例如 textView 源码示例局部
<resource>
<declare-styleable name="TextView">//声明是哪个控件(完整的类名)
<attr name="bufferType">
<enum name="normal" value="0" />
<enum name="spannable" value="1" />
<enum name="editable" value="2" />
</attr>
<attr name="text" format="string" localization="suggested" />// text属性
<attr name="hint" format="string" />
<declare-styleable>
<resource>
2 给SettingItemView 自定义属性 在工程的res、value下创建attrs.xml
<resources>
<declare-styleable name="com.example.administrator.mobilesafe.View.SettingItemView(View所在类的完整包名)">
<attr name="destitle" format="string" />
<attr name="desoff" format="string" />
<attr name="deson" format="string" />
</declare-styleable>
<resources>
-->
3 自定义属性的使用
用安卓的属性是应为在头部生命了安卓的命名空间
(xmlns:android="http://schemas.android.com/apk/res/android"("http://schemas.android.com/apk/res/android"是命名空间))
不用安卓的属性时候要定义命名空间
mobiesafe替换了原有android com.example.administrator.mobilesafe必须这样写替换android代表自定义属性
xmlns:mobilesafe(写啥都可以)="http://schemas.android.com/apk/res/com.example.administrator.mobilesafe(res下完整类名必须这样写)"
在view中通过命名空间调用属性 如 mobiesafe:destitle="哈哈哈"-->
<com.example.administrator.mobilesafe.View.SettingItemView
xmlns:mobiesafe="http://schemas.android.com/apk/res/com.example.administrator.mobilesafe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
mobilesafe:destitle="啊哈哈哈">
</com.example.administrator.mobilesafe.View.SettingItemView>
4 SettingItemview局部
initAttr(attrs);
tv_title.setText(destitle);
}
// 构造方法中维护好的属性集合 返回属性集合中维护好的属性值
private void initAttr(AttributeSet attrs) {
// 通过属性索引获得属性名属性值
/*
for (int i=0;i<attrs.getAttributeCount();i++){
Log.i(TAG, "attrs.getAttributeaName():"+attrs.getAttributeName(i));
Log.i(TAG, "attrs.getAttributeaValue():"+attrs.getAttributeValue(i));
}*/
//通过名空间+属性名获得属性值
destitle = attrs.getAttributeValue(NAME_SPACE,"destitle");
desoff = attrs.getAttributeValue(NAME_SPACE,"desoff");
deson = attrs.getAttributeValue(NAME_SPACE,"deson");
// error 命名空间出错(写错)返回值为null
}
// 由勾选状态判断settingItemView是否选中
public boolean isCheck(){
return cb_box.isChecked();
}
// 设置是否选中 点击条目一次调用一次此方法
public void setCheck(boolean isCheck){
cb_box.setChecked(isCheck);
if(isCheck){
// 变成了动态设定
tv_des.setText(deson);
}else{
tv_des.setText(desoff);
}
}
这样在xml用自定义控件属性时可以用
小提示:
// match_parent 在源码中定义的属性值静态值为-1 wrap_content为-2
// 通过属性索引获得属性名属性值
/*
for (int i=0;i<attrs.getAttributeCount();i++){
Log.i(TAG, "attrs.getAttributeaName():"+attrs.getAttributeName(i));
Log.i(TAG, "attrs.getAttributeaValue():"+attrs.getAttributeValue(i));
}*/
//通过名空间+属性名获得属性值
destitle = attrs.getAttributeValue(NAME_SPACE,"destitle");
desoff = attrs.getAttributeValue(NAME_SPACE,"desoff");
deson = attrs.getAttributeValue(NAME_SPACE,"deson");
// error 命名空间出错(写错)返回值为null
小补充: 参考http://blog.csdn.net/qq_33991989/article/details/78548509?locationNum=3&fps=1
Android中的xmlns:解析
原创 2017年11月16日 10:59:40 38
在Android中,目前我们碰到的xmlns一共有三种:
[java] view plain copy
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android
命名空间android用于 Android 系统定义的一些属性。
这个主要作用是在运行的时候那些控件的属性都是通过它来识别的,如果上面你写错了,不会有任何问题,但是在运行的时候就会有问题,提示你没有指定宽度等什么。这个是不用联网的。
tools
根据官方定义,tools命名空间用于在 XML 文档记录一些,当应用打包的时候,会把这部分信息给过滤掉,不会增加应用的 size,说直白点,这些属性是为IDE提供相关信息。
app(自定义名称)
命名空间app用于我们应用自定义的一些属性。
Android自定义控件的属性,在xml中使用自己自定义的attr的时候,其中有一步就是要自定义一个xml的命名空间后然后再给自定义属性赋值
现在发现不知道什么时候开始Android把这个改了,现在发现可以统一用:
xmlns:app="http://schemas.android.com/apk/res-auto"
而不是原来的:
xmlns:app="http://schemas.android.com/apk/App的Package名"
还有人提到在作为lib被使用的时候,也应该用res-auto
如果你http://schemas.android.com/apk/后面写的是res/包名,那就是相关包名下的自定义属性,而res-auto就是所有的自定义包名。
使用时可以为:
android:..
tools:text tools:visibility tools.src tools.background
app:...
网友评论