Android自定义模板view的方法

本文介绍了如何在Android中自定义一个包含两个按钮和一个文本视图的Topbar控件,详细展示了从定义属性到实现点击事件的全过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       今天学习了Android自定义模板view的方法,之前还是不太懂这个自定义view到底是如何实现的,但是通过今天的学习,基本上搞懂了自定义view的设计理念。

       关于自定义view用处,实际上有很多,我们用过的slidingMenu就是最经典的自定义view,android本身只能提供最基本的layout和一些button,textview等基本控件,但是通过对这些view的组合与设计,我们便可以设计出符合我们自己要求的UI控件。就好像一个actionbar,我们只要写出一个模板来,然后就可以把它当成已有的控件来像button一样使用,这大大的提高了我们的开发效率与增强了程序的健壮性。

        现在我以设计一个topbar为例,topbar类似于一个actionbar,左边一个button,右边一个button,中间一个textview来设计一个view模板:


首先我们知道一个系统控件自带很多属性,例如:layout_width等,都是android自己定义好的,现在我们在value下定义一个属性文件attr.xml用于存放我们topbar的属性:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- 自定义属性文件,自定义控件属性名称以及资源格式 -->

    <declare-styleable name="Topbar">
        <attr name="title" format="string"></attr>
        <attr name="titleTextsize" format="dimension"></attr>
        <attr name="titleTextcolor" format="color"></attr>
        <attr name="leftTextColor" format="color"></attr>
        <attr name="leftText" format="string"></attr>
        <attr name="leftBackground" format="reference|color"></attr>
        <attr name="rightTextColor" format="color"></attr>
        <attr name="rightText" format="string"></attr>
        <attr name="rightBackground" format="color|reference"></attr>      
    </declare-styleable>

</resources>
设置好这些属性后,我们就可以创建一个topbar类,来映射这些属性,由于在文件中我已经写好了注释,所以就把完整的代码放出来了,其中主要是步骤:

  1. 先定义好要实现的组件,我们有两个button还有一个textview
  2. 定义好与attr.xml中对应的属性值
  3. 然后通过typedarray数组来获取attr.xml中对应的属性
  4. 然后实例化子控件
  5. 再将自定义属性值赋给子控件
  6. 通过LayouParams将设置好控件的宽高等其他系统默认属性,通过addveiw方法赋值给子控件
  7. 由于要实现button的点击事件,所以我们可以提供一个接口,让外部添加事件,实现的方法我已经在注释中写清除了

package com.example.zidingyi_view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;

/**
 * 自定义view的步骤: 1:定义好attr下的xml文件属性 
 * 2:定义好class
 * 3:引入控件,定义好layoutparams,再addview
 * 
 * @author nickming
 *实例总结:
 *添加名字空间 {
 *1.Android Studio中只需要写上res-auto即可
 *2.Eclipse中则需要加上完整的包名和控件名
 *3.xmlns:custom="http://schmas.android.com/apk/res-auto"}
 *
 *通过模板复用,接口回调,增加程序的效率,降低程序的耦合度
 *接口回调是重点
 *
 */

@SuppressLint("NewApi")
public class Topbar extends RelativeLayout {

	private Button leftButton, rightButton;
	private TextView tvTitle;

	// 对应的attr下的属性值
	private int leftTextColor;
	private Drawable leftBackground;
	private String leftTextString;

	private int rightTextColor;
	private Drawable rightBackground;
	private String rightTextString;

	private int titleTextColor;
	private float titleTextSize;
	private String titleString;
	
	LayoutParams leftLayoutParams;
	LayoutParams rightLayoutParams;
	LayoutParams titleLayoutParams;
	
	private boolean leftButtonVisiable=true;
	
	/**
	 * 接口回调
	 * 重点,接口的设计,一般先一个公共接口,然后在里面设置好提供的函数
	 * 然后再提供一个外部访问的函数接口,再通过实例化一个接口对象,来与方法
	 * 进行映射,这里面再对button经行事件的设计
	 * @author nickming
	 *
	 */
	public interface topbarClickListener{
		public void leftClick();
		public void rightClick();
	}
	public topbarClickListener mListener;
	
	public void setOnTopBarClickListener(topbarClickListener listener){
		mListener=listener;
	}

	public Topbar(Context context) {
		this(context, null);
		// TODO Auto-generated constructor stub
	}

	@SuppressLint("NewApi")
	public Topbar(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
		// 用typeArray来获取xml中的属性集合
		TypedArray tArray = context.obtainStyledAttributes(attrs,
				R.styleable.Topbar);

		leftTextColor = tArray.getColor(R.styleable.Topbar_leftTextColor, 0);
		leftTextString = tArray.getString(R.styleable.Topbar_leftText);
		leftBackground = tArray.getDrawable(R.styleable.Topbar_leftBackground);

		rightBackground = tArray
				.getDrawable(R.styleable.Topbar_rightBackground);
		rightTextColor = tArray.getColor(R.styleable.Topbar_rightTextColor, 0);
		rightTextString = tArray.getString(R.styleable.Topbar_rightText);

		titleString = tArray.getString(R.styleable.Topbar_title);
		titleTextColor = tArray.getColor(R.styleable.Topbar_titleTextcolor, 0);
		titleTextSize = tArray
				.getDimension(R.styleable.Topbar_titleTextsize, 0);
		
		tArray.recycle();//最后要回收这个数组
		
		leftButton=new Button(context);
		rightButton=new Button(context);
		tvTitle=new TextView(context);
		
		//将自定义的属性赋值
		leftButton.setTextColor(leftTextColor);
		leftButton.setBackground(leftBackground);
		leftButton.setText(leftTextString);
		
		rightButton.setTextColor(rightTextColor);
		rightButton.setBackground(rightBackground);
		rightButton.setText(rightTextString);
		
		tvTitle.setText(titleString);
		tvTitle.setTextColor(titleTextColor);
		tvTitle.setTextSize(titleTextSize);
		tvTitle.setGravity(Gravity.CENTER);
		
		setBackgroundColor(0xFFF59563);
		
		/**
		 *先定义宽高属性
		 *然后定义其他属性,用addrule
		 *最后再调用本函数的addview方法添加控件到viewgroup中
		 */
		leftLayoutParams=new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
		leftLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT,TRUE);
		addView(leftButton,leftLayoutParams);
		
		rightLayoutParams=new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
		rightLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,TRUE);
		addView(rightButton,rightLayoutParams);
		
		titleLayoutParams=new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.MATCH_PARENT);
		titleLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
		addView(tvTitle,titleLayoutParams);
				
		
		leftButton.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				mListener.leftClick();
			}
		});
		
		
		rightButton.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				mListener.rightClick();
			}
		});
	}
	
	
	public void setLeftIsVisiable(boolean flag)
	{
		if (flag) {
			leftButton.setVisibility(View.VISIBLE);
			leftButtonVisiable=true;
		}else {
			leftButton.setVisibility(View.GONE);
			leftButtonVisiable=false;
		}
	}

	
	public boolean isLeftButtonVisiable()
	{
		return leftButtonVisiable;
	}
}

最后,我们在main.xml中使用我们的控件,注意要记得命名空间一定要写好:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:nickming="http://schemas.android.com/apk/res/com.example.zidingyi_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.zidingyi_view.MainActivity" >

    <com.example.zidingyi_view.Topbar 
        android:id="@+id/topbar"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        nickming:leftBackground="#33333333"
        nickming:leftTextColor="#ffffff"
        nickming:leftText="你好"
        nickming:rightTextColor="#ffffff"
        nickming:rightText="我好"
        nickming:rightBackground="#87889999"
        nickming:title="自定义标题"
        nickming:titleTextsize="10sp"
        nickming:titleTextcolor="#ffffff">
        
    </com.example.zidingyi_view.Topbar>

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/topbar"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="102dp"
        android:text="更改topbar" />

</RelativeLayout>

最后放出mainActivity的方法:

package com.example.zidingyi_view;

import com.example.zidingyi_view.Topbar.topbarClickListener;

import android.R.bool;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity {
	private Topbar topbar;
	private Button button;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		topbar=(Topbar) findViewById(R.id.topbar);
		topbar.setOnTopBarClickListener(new topbarClickListener() {
			
			@Override
			public void rightClick() {
				// TODO Auto-generated method stub
				Toast.makeText(MainActivity.this, "rightButton", Toast.LENGTH_SHORT).show();
			}
			
			@Override
			public void leftClick() {
				// TODO Auto-generated method stub
				Toast.makeText(MainActivity.this, "leftButton", Toast.LENGTH_SHORT).show();
			}
		});
		
		
		button=(Button) findViewById(R.id.button1);
		button.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				if (topbar.isLeftButtonVisiable()) {
					topbar.setLeftIsVisiable(false);
				}else {
					topbar.setLeftIsVisiable(true);
				}
			}
		});
	}
	
	

	
}

基本上就大功告成,这只是一个简单的demo,最主要的就是定义好属性与接口回调方法。如有错误,请大家一起讨论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值