android 自己定义组合控件

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

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY29kZXJpbmNoaW5h/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >

就很适合使用组合控件了,如今写一个玩玩:

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-06 07:02:44

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

Android UI-自定义日历控件

Android UI-自定义日历控件 本篇博客笔者给大家分享一个日历控件,这里有个需求:要求显示当前月的日期,左右可以切换月份来查看日期. 我们想一想会如何去实现这样的一个控件,有开源的,但可能不太满足我们的特定的需求,这里笔者自定义了一个,读者可以根据自己的需求来修改代码.下面来说一下实现的思路: 首先我们要显示当前月份,自然我们要计算出当前的日期,并且把每一天对应到具体的星期,我们会有以下效果: 我们先想一下这样的效果用什么控件可以实现?很自然可以想到用网格视图GridView,但这里笔者使

Android自定义控件——自定义组合控件

转载请注明出处http://blog.csdn.net/allen315410/article/details/39581055  前面几篇博文介绍了Android如何自定义控件,其实就是讲一下如何"从无到有"的自定义一个全新的控件,继承View或者继承ViewGroup,复写其相关方法,这种自定义控件的方式相对来说难度较大,而且并不是所有需要新控件的情况下,都要这样进行.有很多情况下,我们只要运用好Android给我提供好的控件,经过布局巧妙的结合在一起,就是一个新的控件,我称之为&

android:自定义组合控件Weight(高仿猫眼底部菜单栏)

在我们实际开发当中,会碰见一些布局结构类似或者相同的界面,例如应用的设置界面.tab按钮界面等.这时候,对于初学者来说,xml里面一个个绘制出来或许是最初的想法:可能随着经验的积累,又学会一招,就是使用include标签,导入类似或者相同的布局,提高了性能又减少了代码:再以后呢,自定义控件又可以实现这一目的.本文就是简单的使用自定义的组合控件模仿猫眼底部菜单栏. 1.自定义组合控件属性:在res/values目录下创建attrs.xml文件 <declare-styleable name="

【android】自定义组合控件PullToRefreshRecyeclerView

场景:自从Android 5.0发布以来,越来越多的开发者开始接触RecyeclerView,但是RecyclerView如何实现下拉刷新,上拉加在更多.于是我就偷懒 写了一个,以供大家参考和学习,以待大家改进. 构思:想必大家对SwipeRefreshLayout这个控件有一定了解,没错本次自定义组合控件也就是SwipeRefreshLayout与RecyeclerView的组合. 那么我们一步一步来实现: 1.首先写一个组合布局如下:pulltorefreshrecyclerview.xml

Android中自定义组合控件

Android中自定义控件的情况非常多,一般自定义控件可以分为两种:继承控件及组合控件.前者是通过继承View或其子类,重写方法实现自定义的显示及事件处理方式:后者是通过组合已有的控件,来实现结构的简化和代码的重用. 本篇文章主要介绍自定义组合控件,继承控件后续有机会再述. 自定义组合控件一般来说都是以ViewGroup及其子类(LinearLayout.RelativeLayout.FrameLayout等)为主,内部嵌套其他控件,来组合成一个新的控件,实现一些特定的需要,可以是代码简化,结构

android项目自定义组合控件添加属性

首先要在values文件下新建立一个文件arrts.xml,这个文件就是用来说明键名称是做什么的,和值的类型 <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="SeetingView"> <attr name="up" format="string" /> &

android项目自定义组合控件

自定义控件首先要有一个布局文件 <?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="60dp" a

Android自定义控件之自定义组合控件(三)

前言: 前两篇介绍了自定义控件的基础原理Android自定义控件之基本原理(一).自定义属性Android自定义控件之自定义属性(二).今天重点介绍一下如何通过自定义组合控件来提高布局的复用,降低开发成本,以及维护成本. 使用自定义组合控件的好处? 我们在项目开发中经常会遇见很多相似或者相同的布局,比如APP的标题栏,我们从三种方式实现标题栏来对比自定义组件带来的好处,毕竟好的东西还是以提高开发效率,降低开发成本为导向的. 1.)第一种方式:直接在每个xml布局中写相同的标题栏布局代码 <?xm

[android] 手机卫士自定义组合控件

设置中心 新建SettingActivity 设置GridView条目的点击事件 调用GridView对象的setOnItemClickListenner()方法,参数:OnItemClickListenner对象 匿名内部类实现,重写onItemClick()方法,传递进来的参数: parent是GridView对象,view是当前View对象,position是当前索引 switch判断,当时设置中心的索引时,跳转到设置中心 设置中心界面 使用相对布局,右边的<CheckBox/> 位于父