Android自定义组合控件

155 篇文章 0 订阅
28 篇文章 0 订阅
目标:实现textview和ImageButton组合,可以通过Xml设置自定义控件的属性。
  1.控件布局:以Linearlayout为根布局,一个TextView,一个ImageButton。
  
< ?xml version="1.0" encoding="utf-8"?>
   < LinearLayout xmlns:Android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent" android:layout_height="fill_parent"
   android:gravity="center_vertical">
   < TextView android:layout_height="wrap_content" android:id="@+id/text1"
   android:layout_width="wrap_content">< /TextView>
   < ImageButton android:layout_width="wrap_content"
   android:layout_height="wrap_content" android:id="@+id/btn1">< /ImageButton>
   < /LinearLayout>
  

  2.自定义控件代码,从LinearLayout继承:
  
 public class ImageBtnWithText extends LinearLayout {
  }
   public ImageBtnWithText(Context context) {
   this(context, null);
   }
  
   public ImageBtnWithText(Context context, AttributeSet attrs) {
   super(context, attrs);
   LayoutInflater.from(context).inflate(R.layout.imagebtn_with_text, this, true);
     }
   }
 

  在构造函数中将Xml中定义的布局解析出来。
  3.在主界面布局xml中使用自定义控件:
  
< com.demo.widget2.ImageBtnWithText
   android:id="@+id/widget"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent" />
  

  即使用完整的自定义控件类路径:com.demo.widget2.ImageBtnWithText定义一个元素。
  运行可以看到控件已经能够被加载到界面上。
  4.给按钮设置图片和文本
  如果图片是固定不变的,那么直接在控件布局中设置ImageButton的src属性即可。
  4.1通过Java代码设置,在控件代码中提供函数接口:
  
public void setButtonImageResource(int resId) {
   mBtn.setImageResource(resId);
   }
  
   public void setTextViewText(String text) {
   mTv.setText(text);
   }
  

  然后再在主界面的onCreate()通过函数调用设置即可。
  4.2通过Xml设置属性
  4.2.1首先定义Xml可以设置的属性集合,在values下创建attrs.xml,文件名可随意,一般都叫attrs.xml
  
< ?xml version="1.0" encoding="utf-8"?>
  < resources>
   < declare-styleable name="ImageBtnWithText">
   < attr name="android:text"/>
   < attr name="android:src"/>
   < /declare-styleable>
   < /resources>
  

  属性集合名字:ImageBtnWithText,自己可根据实际来定义;
  集合中包含的属性列表,每行一个属性。
  4.2.2修改自定义控件实现代码,以获取xml中定义的属性
  
 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ImageBtnWithText);
   CharSequence text = a.getText(R.styleable.ImageBtnWithText_android_text);
   if(text != null) mTv.setText(text);
   Drawable drawable = a.getDrawable(R.styleable.ImageBtnWithText_android_src);
   if(drawable != null) mBtn.setImageDrawable(drawable);
   a.recycle()
  

  首先通过context.obtainStyledAttributes获得所有属性数组;
  然后通过TypedArray类的getXXXX()系列接口获得相应的值。
  4.2.3在主界面布局中设置自定义控件的属
  android:text="ABC" android:src="@drawable/icon
  4.3自定义名称属性:
  在4.2中使用的属性名是Android系统命名空间的,都以android开头,比如android:text等。
实际开发中会自定义一些属性名,这些属性名仍然定义在4.2.1提到的attrs.xml中:
  4.3.1定义属性名
  
< attr name="appendText" format="string"/>

  和直接使用系统的attr不同的是要增加一个format属性,说明此属性是什么格式的。format可选项可参见注1
  4.3.2使用自定义属性
  
< ?xml version="1.0" encoding="utf-8"?>
   < LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:myspace="http://schemas.android.com/apk/res/com.demo.customwidget"
   android:orientation="vertical" android:layout_width="fill_parent"
   android:layout_height="fill_parent">
   < com.demo.widget2.ImageBtnWithText
   android:text="ABC" android:src="@drawable/icon" android:id="@+id/widget"
   android:layout_width="fill_parent" android:layout_gravity="center"
   android:layout_height="fill_parent" myspace:appendText="123456">
   < /com.demo.widget2.ImageBtnWithText>
   < /LinearLayout>
  

  直接在主布局文件中使用此属性appendText="abc"是不会设置生效的,而是要在主布局xml中定义一个xml命名空间:
xmlns:myspace="http://schemas.android.com/apk/res/com.demo.customwidget"
  命名空间的名字可以自己随便定义,此处为myspace,即xmlns:myspace;
  后面的地址则有限制,其开始必须为:"http://schemas.android.com/apk/res/",后面则是包名com.demo.customwidget,
  此处的包名与AndroidManifest.xml中< manifest>节点的属性package="com.demo.customwidget"一致,不是自定义控件Java代码所在的包,当然简单的程序自定义控件Java代码也一般在此包内。
   注1:format可选项
  "reference" //引用
  "color" //颜色
  "boolean" //布尔值
  "dimension" //尺寸值
  "float" //浮点值
  "integer" //整型值
  "string" //字符串
  "fraction" //百分数,比如200%
  枚举值,格式如下:
  < attr name="orientation">
  < enum name="horizontal" value="0" />
  < enum name="vertical" value="1" />
  < /attr>
  xml中使用时:
  android:orientation = "vertical"
  标志位,位或运算,格式如下:
  < attr name="windowSoftInputMode">
  < flag name = "stateUnspecified" value = "0" />
  < flag name = "stateUnchanged" value = "1" />
  < flag name = "stateHidden" value = "2" />
  < flag name = "stateAlwaysHidden" value = "3" />
  < flag name = "stateVisible" value = "4" />
  < flag name = "stateAlwaysVisible" value = "5" />
  < flag name = "adjustUnspecified" value = "0x00" />
  < flag name = "adjustResize" value = "0x10" />
  < flag name = "adjustPan" value = "0x20" />
  < flag name = "adjustNothing" value = "0x30" />
  < /attr>
  xml中使用时:
  android:windowSoftInputMode = "stateUnspecified | stateUnchanged | stateHidden">
  另外属性定义时可以指定多种类型值,比如:
  < attr name = "background" format = "reference|color" />
  xml中使用时:
  android:background = "@drawable/图片ID|#00FF00"


最后来个完整实例:

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ProgressBar;

public class Meter extends LinearLayout {
	private int max=100;
	private int incrAmount=1;
	private int decrAmount=-1;
	private ProgressBar bar=null;
	public Meter(final Context ctxt, AttributeSet attrs) {
		super(ctxt, attrs);
		
		this.setOrientation(HORIZONTAL);
		
		TypedArray a=ctxt.obtainStyledAttributes(attrs,R.styleable.Meter);
		
		//获取里面属性用 "名字_ 属性" 连接起来
		max=a.getInt(R.styleable.Meter_max, 100);
		incrAmount=a.getInt(R.styleable.Meter_incr, 1);
		decrAmount=-1*a.getInt(R.styleable.Meter_decr, 1);
		
		a.recycle();
	}
	//当View中所有的子控件 均被映射成xml后触发
	@Override
	protected void onFinishInflate() {
		super.onFinishInflate();
		
//		((Activity)getContext()).getLayoutInflater().inflate(R.layout.meter, this);
		
		LayoutInflater.from(getContext()).inflate(R.layout.meter, this);
		
		bar=(ProgressBar)findViewById(R.id.bar);
		bar.setMax(max);
		
		ImageButton btn=(ImageButton)findViewById(R.id.incr);
		btn.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				bar.incrementProgressBy(incrAmount);
			}
		});
		
		btn=(ImageButton)findViewById(R.id.decr);
		btn.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				bar.incrementProgressBy(decrAmount);
			}
		});
//		this.addView(view);//不需要add,默认已经add了
	}
}

attrs.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
	<declare-styleable name="Meter">
		<attr name="max" format="integer" />
		<attr name="incr" format="integer" />
		<attr name="decr" format="integer" />
	</declare-styleable>
</resources>

meter.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="horizontal"
	android:layout_width="fill_parent"
	android:layout_height="wrap_content"
>
	<ImageButton android:id="@+id/decr"
		android:layout_height="wrap_content"
		android:layout_width="wrap_content"
		android:scaleType="fitCenter"
		android:src="@drawable/arrow_down"
	/>
	<ProgressBar android:id="@+id/bar"
		style="?android:attr/progressBarStyleHorizontal"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:layout_weight="1"
		android:layout_gravity="center_vertical"
	/>
	<ImageButton android:id="@+id/incr"
		android:layout_height="wrap_content"
		android:layout_width="wrap_content"
		android:scaleType="fitCenter"
		android:src="@drawable/arrow_up"
	/>
</LinearLayout>

使用:

@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}

main.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/com.ql.app"
	android:orientation="horizontal"
	android:layout_width="fill_parent"
	android:layout_height="wrap_content"
	>
	<com.ql.app.Meter
		android:id="@+id/meter"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		app:max="100"
		app:incr="5"
		app:decr="5"
	/>
</LinearLayout>



  • 大小: 3.6 KB
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值