android 自定义组合控件

自定义控件是一些android程序员感觉很难攻破的难点,起码对我来说是这样的,但是我们可以在网上找一些好的博客关于自定义控件好好拿过来学习研究下,多练,多写点也能找到感觉,把一些原理弄懂,今天就讲下自定义组合控件,这个特别适合在标题栏或者设置界面,看下面图:

就非常适合使用组合控件了,现在写一个玩玩:

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:hy="http://schemas.android.com/apk/res/com.example.customcircle"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
 >
     <com.example.customcircle.SettingView
         android:id="@+id/sv1"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         hy:title = "标题1"
         hy:content = "内容1"
         ></com.example.customcircle.SettingView>
     <com.example.customcircle.SettingView
         android:id="@+id/sv2"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
           hy:title = "标题2"
         hy:content = "内容2"
         ></com.example.customcircle.SettingView>
     <com.example.customcircle.SettingView
         android:id="@+id/sv3"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         hy:title = "标题3"
         hy:content = "内容3"
         ></com.example.customcircle.SettingView>
</LinearLayout>
SettingView.java
public class SettingView extends RelativeLayout {
	private TextView title;
	private TextView content;

	public SettingView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initView(context);
	}

	public SettingView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initView(context);
		/**
		 * 获取一个样式的属性集
		 * 把布局文件xml中的获取到的样式集合attrs跟自己自定义的样式集合建立一个映射关系
		 */
		TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SettingView);
		String title = a.getString(0);
		String content = a.getString(1);
		//设置到界面上
		setTitle(title);
		setContent(content);
		a.recycle();
	}

	public SettingView(Context context) {
		super(context);
		initView(context);
	}

	private View initView(Context context){
		View view = View.inflate(context, R.layout.setting_view, this);
		title = (TextView) view.findViewById(R.id.title);
		content = (TextView) view.findViewById(R.id.content);
		return view;
	}

	public void setTitle(String tilte){
		title.setText(tilte);
	}
	public void setContent(String strContent){
		content.setText(strContent);
	}
	public void setTextSize(int size){
		content.setTextSize(size);
		title.setTextSize(size);
	}
}

setting_view.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="vertical"

android:background="#22000000"

>

<RelativeLayout

android:layout_width="fill_parent"

android:layout_height="wrap_content"

>

<TextView

android:id="@+id/title"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:textSize="20sp"

android:layout_marginTop="5dp"

android:layout_marginLeft="5dp"

/>

<TextView

android:id="@+id/content"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:textSize="16sp"

android:layout_marginLeft="5dp"

android:layout_below="@id/title"

/>

<CheckBox

android:id="@+id/cb"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentRight="true"

android:layout_centerVertical="true"

/>

</RelativeLayout>

<View

android:layout_width="fill_parent"

android:layout_height="1px"

android:background="#000000"

android:layout_below="@id/cb"

/>

</LinearLayout>

我们发现在activity_main.xml中有二个属性

hy:title = "标题1"

hy:content = "内容1"

这个时候xml文件会报错

error: Error parsing XML: unbound prefix  说没有hy这样的前缀,因为我们写android:什么属性  都是因为有xmlns:android ="http://schemas.android.com/apk/res/android"

这样一个命名空间在,

那我们也自定义一个命名空间,仿照上面的写就是了

xmlns:hy ="http://schemas.android.com/apk/res/com.example.customcircle"//res后面的是你得包名

现在xml文件有报错了:

Multiple annotations found at this line:

- error: No resource identifier found for attribute ‘content‘ in package

‘com.example.customcircle‘

说在我们的包下没有找到conent的定义

 hy:title = "标题"

hy:content = "内容"

是我自定义的属性

如果要使用自定义的属性,就要把这些属性定义出来,而为什么系统的android:属性名---就可以呢?那是因为android sdk已经声明好了,在找到我们使用的sdk

D:\java\tools\adt-bundle-windows-x86_64-20130917\sdk\platforms\android-10\data\res\values在这个目录下有一个attrs.xml文件,我们就找一个平时大家都会用到的

<declare-styleable name="TextAppearance">

<!-- Text color. -->

<attr name="textColor" />

<!-- Size of the text. Recommended dimension type for text is "sp" for scaled-pixels (example: 15sp). -->

<attr name="textSize" />

<!-- Style (bold, italic, bolditalic) for the text. -->

<attr name="textStyle" />

<!-- Typeface (normal, sans, serif, monospace) for the text. -->

<attr name="typeface" />

<!-- Color of the text selection highlight. -->

<attr name="textColorHighlight" />

<!-- Color of the hint text. -->

<attr name="textColorHint" />

<!-- Color of the links. -->

<attr name="textColorLink" />

</declare-styleable>

这就是TextView中的属性,所以我们也要模仿他创建一个attrs文件在value目录下

<declare-styleable name="TextAppearance">

declare-styleable  声明的意思 name表示 声明的控件名称

我们的  <declare-styleable name="SettingView">

</declare-styleable >

当保存的时候就会在你R.java文件中生成了一个内部类

public static final class attr
{//属性集

}

然后声明属性

<attr name="title" format="string"></ attr>

<attr name="content" format="string" ></attr>

name表示属性的名称 format表示属性的类型

然后我们保存代码 就没错误提示了

然后再看R.java文件

public static final class attr
{

/** <p>Must
be a string value, using ‘\\;‘ to escape characters such as ‘\\n‘ or ‘\\uxxxx‘ for a unicode character.

<p>This may also be a reference
to a resource (in the form

"<code>@[ <i>package</i> :]<i>type </i>:<i> name</i></code>")
or

theme attribute (in the form

"<code>?[ <i>package</i> :][<i>type </i>:]<i> name</i></code>")

containing a value of this type.

*/

public static final int content=0x7f010001;

/** <p>Must
be a string value, using ‘\\;‘ to escape characters such as ‘\\n‘ or ‘\\uxxxx‘ for a unicode character.

<p>This may also be a reference
to a resource (in the form

"<code>@[ <i>package</i> :]<i>type </i>:<i> name</i></code>")
or

theme attribute (in the form

"<code>?[ <i>package</i> :][<i>type </i>:]<i> name</i></code>")

containing a value of this type.

*/

public static final int title=0x7f010000;

}

这个时候我们运行下我们的项目,发现这自定义的属性并没有起作用,那意思就是说我们要用代码的方式让它显示出来

AttributeSet类表示属性的集合 在我们定义的属性

比如:

android:id= "@+id/sv1"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

hy:title = "标题"

hy:content = "内容"

相当于把这些属性封装成了一个类,这真是我们java强大之处,面向对象编程思想

然在构造函数中做这个操作

public SettingView(Context
context, AttributeSet attrs) {

super(context,
attrs);

initView(context);

/**

* 获取一个样式的属性集

* 把布局文件 xml中的获取到的样式集合 attrs跟自己自定义的样式集合建立一个映射关系

*/

TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SettingView );

String title = a.getString(0);

String content = a.getString(1);

//设置到界面上

setTitle(title);

setContent(content);

a.recycle();

}

这样就算成功了

运行效果:

总结下自定义组合控件的步骤:

1. 写一个类 继承  ViewGroup LinearLayout  RelativeLayout

2. 如果在布局文件里面定义view对象 使用这个view对象的两个参数的构造方法.

3. 定义这个自定义控件里面要显示的内容

View.inflate(context, R.layout.ui_setting_view, this);

4. 添加自定义控件的属性.

定义自定义属性的命名空间

5. 声明自定义的属性

<declare-styleable name="SettingView">

<attr name="title" format="string" />

<attr name="desc_on" format="string" />

<attr name="desc_off" format="string" />

</declare-styleable>

观察R文件 生成 attr内部类 生成styleable  数组 所有的attrs

6. 在xml布局文件里面配置  自定义的属性.

7. 在自定义view对象的构造方法里面 获取AttributeSet

跟我们自定义的属性建立映射关系

8. 在自定义组合控件里面 设置 布局文件的数据, 扩展点击事件.

9. 在布局文件使用自定义的view对象.

时间: 2024-10-19 18:13:03

android 自定义组合控件的相关文章

Android 自定义组合控件小结

引言 接触Android UI开发的这段时间以来,对自定义组合控件有了一定的了解,为此小结一下,本文小结内容主要讨论的是如何使用Android SDK提供的布局和控件组成一个功能完整组合控件并将其封装为面向对象的类,而并非讨论如何继承自SDK提供的控件类(比如TextView),对其进行自定义扩展的问题. 进入正题前,我们先来看一组功能需求 假设在手机需求上,那么如上三个界面我们可以使用三个Activity,每个Activity一个布局文件,实现起来比较独立,但是假设在Android pad上要

Android自定义组合控件--底部多按钮切换

效果图: 现在市场上大多数软件都是类似于上面的结构,底部有几个按钮用于切换到不同的界面.基于OOP思想,我想把下面的一整块布局封装成一个类,也就是我们的自定义组合控件-底部多按钮切换布局,我把它叫做BottomLayout 看上面的布局,几个按钮横向排列,我们先看一下布局 最外面LinearLayout 方向 horizontal,然后5个weight相同的RelativeLayout,每个RelativeLayout里面有一个Button(用了显示选中状态)个ImageView(用来显示红点)

Android自定义组合控件--图片加文字,类似视频播放软件的列表

分四步来写: 1,组合控件的xml; 2,自定义组合控件的属性; 3,自定义继承组合布局的class类,实现带两参数的构造器; 4,在xml中展示组合控件. 具体实现过程: 一.组合控件的xml 我接触的有两种方式,一种是普通的Activity的xml:一种是父节点为merge的xml.我项目中用的是第一种,但个人感觉第二种好,因为第一种多了相对或者绝对布局层. 我写的 custom_pictext.xml <?xml version="1.0" encoding="u

Android自定义组合控件的实现

需求:在黑马做安全卫士的时候,功能9设置中心界面如下: 在点击item的时候,复选框会反转状态,同时"自动更新已经关闭"会变换内容和颜色. 可以发现这个界面类似ListView,但又不是ListView,因为它的item数量是固定的,且最后一 item和之前的都不一样.虽然这个看着像是标准的List结构,实则每个item不是完全一样,因为 每个item的提示文本(如"自动更新已经关闭")的内容并不完全一样. 假如用一般方式来布局的话,4个item就会有3*4 = 1

Android自定义组合控件---教你如何自定义下拉刷新和左滑删除

绪论 最近项目里面用到了下拉刷新和左滑删除,网上找了找并没有可以用的,有比较好的左滑删除,但是并没有和下拉刷新上拉加载结合到一起,要不就是一些比较水的结合,并不能在项目里面使用,小编一着急自己组合了一个,做完了和QQ的对比了一下,并没有太大区别,今天分享给大家,其实并不难,但是不知道为什么网上没有比较好的Demo,当你的项目真的很急的时候,又没有比较好的Demo,那么"那条友谊的小船儿真是说翻就翻啊",好了,下面先来具体看一下实现后的效果吧: 代码已经上传到Github上了,小伙伴们记

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

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

Android自定义组合控件

今天和大家分享下组合控件的使用.很多时候android自定义控件并不能满足需求,如何做呢?很多方法,可以自己绘制一个,可以通过继承基础控件来重写某些环节,当然也可以将控件组合成一个新控件,这也是最方便的一个方法.今天就来介绍下如何使用组合控件,将通过两个实例来介绍.第一个实现一个带图片和文字的按钮,如图所示: 整个过程可以分四步走.第一步,定义一个layout,实现按钮内部的布局.代码如下: <?xml version="1.0" encoding="utf-8&quo

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

在软件开发过程中,经常见到,就是APP 的标题栏样式几乎都是一样的,只是文字不同而已,两边图标不同.为了减少重复代码,提高效率, 方便大家使用,我们把标题栏通过组合的方式定义成一个控件. 例下图: 点击: 如不设置左边,右边图片: 下面说一下具体实现步骤: 步骤一: 导航栏包括:* 返回按钮* 标题* 右侧按钮(功能不确定) 首先是布局文件,如下: </pre><p></p><pre name="code" class="java&q

(转)android自定义组合控件

原文地址:http://mypyg.iteye.com/blog/968646 目标:实现textview和ImageButton组合,可以通过Xml设置自定义控件的属性. 1.控件布局:以Linearlayout为根布局,一个TextView,一个ImageButton. Xml代码   <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://