【安卓自定义控件系列】安卓自定义控件之组合控件


在安卓开发中,谷歌已经为咱们提供了许多原生控件,基本上可以知足咱们平常的开发需求,可是某些项目中原生控件可能达不到产品所要求的各式各样的酷炫效果或功能效果,这个时候咱们只能本身自定义控件来知足项目需求,咱们知道自定义控件包括三种方式:java

1继承控件,即继承谷歌提供的原生控件,在此基础上提供一些原生控件不具有的功能,如github上各类酷炫效果的开源组件基本上都是采用的这种方式.android

2组合控件:即组合多个原生控件来达到某些单个原生控件本来不具有的功能,这个在平常开发中应该是使用的比较多的,如基本上每一个App都存在一个标题栏,而这些标题栏是能够被复用的,此时咱们能够将其抽象出来组合为一个控件,这样在须要标题栏的地方直接使用该控件。(固然也能够采用include布局的方式,可是这样仅仅只是界面复用而已,功能不能复用)git

3自绘控件:即直接继承自View类,而后本身重写onDraw方法,某些状况下可能须要重写onMeasure方法。github


这三种方式,第一种方式咱们使用的不多,由于github上大量优秀的开源组件就是采用的这种方式,以下拉刷新上拉加载的listView,侧滑删除的listView等,所以咱们只须要直接拿来用就能够了,不要去重复造轮子,固然若是是学习自定义控件的知识的话,咱们也能够直接去阅读这些开源项目的源代码,第二种方式咱们使用的比较多的地方就是一个App的标题栏,一般都是采用的这种方式来完成的,第三种方式在通常的项目中不多使用到,除非项目须要完成一些复杂的效果。本博客将以第二中方式即组合控件为例来说解安卓自定义控件的使用,将以模仿腾讯QQ的标题栏为例来教你们如何自定义组合控件。首先咱们来看一下腾讯QQ的标题栏。而后按照这个样子咱们本身模仿自定义一个标题栏控件。固然QQ的标题栏仍是比较复杂的,由于标题栏中的文字会随着用户点击底部不一样的button而显示不一样的内容,固然这个功能个也很好实现,关键是若是要截图的话得截几张图,这里我就选择最具表明性的一个界面,其他的看官能够本身用QQ试一下。app


能够看到在左侧是一个ImageView,中间是两个button,点击不一样button显示不一样内容,固然这是在消息界面,所以中间是两个button,而在联系人与动态界面中间只显示文字而已,所以此时中间是TextView,右侧基本上也是一样的道理。因此第一步咱们须要在layout布局文件中组合控件来到达这样的一个界面效果。函数

common_title_bar的layout文件以下:布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/relativeLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" 
        android:background="#fff"
       >

    <hq.king.view.CircleImageView
        android:paddingLeft="4dp"
        android:id="@+id/title_bar_leftImg"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="7dp"
        android:background="@drawable/title_bar_image_shape"
        app:civ_border_width="1dp"
        app:civ_border_color="@color/blue"
        />
 
    <TextView
        android:id="@+id/center_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_marginLeft="14dp" />

    <Button
        android:id="@+id/title_bar_rightBtn"
        android:layout_width="35dp"
        android:layout_height="30dp"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_marginTop="7dp"
        android:layout_marginRight="3dp"
        android:background="#fff"/>


    <LinearLayout
        android:id="@+id/title_bar_linearLayout"
        android:layout_width="150dp"
        android:layout_height="30dp"
        android:layout_centerInParent="true"
        android:layout_marginLeft="60dp"
        android:layout_toRightOf="@+id/imageView1" >



        <Button
            android:id="@+id/title_bar_linear_leftBtn"
            android:layout_width="70dp"
            android:layout_height="30dp"
            android:background="@drawable/title_bar_linear_leftbtn_shape"
             />

        <Button
            android:id="@+id/title_bar_linear_rightBtn"
            android:layout_width="70dp"
            android:layout_height="30dp"
            android:background="@drawable/title_bar_linear_rightbtn_shape"/>
        
    </LinearLayout>
</RelativeLayout>
能够看到该布局的根布局是一个RelativeLayout,固然这个是和具体的组合控件的界面相关的,不过像这种标题栏咱们通常都使用RelativeLayout布局,而后在该布局中咱们基本上按照前面的分析组合了几个原生的控件,固然那个ImageView为了达到和腾讯QQ同样的效果,我采用的是开源的CircleImageView,这些组合控件之间的位置关系经过相对布局来控制。

接下来就是自定义组合控件了,代码以下:学习

public class TitleBarView extends RelativeLayout {

	private Context mContext;
	Button rightBtn;
	TextView center_tv;
	LinearLayout title_linearlayout;
	Button linear_leftBtn;
	Button linear_rightBtn;
	ImageView leftImg;
	
	public TitleBarView(Context context) {
		super(context);
		mContext=context;
		findView();
		// TODO Auto-generated constructor stub
	}

	public TitleBarView(Context context, AttributeSet attrs) {
		super(context, attrs);
		mContext=context;
		findView();
	}
	public void findView()
	{
		
		LayoutInflater.from(mContext).inflate(R.layout.common_title_bar, this);
		
		 leftImg=(ImageView) findViewById(R.id.title_bar_leftImg);
		 rightBtn=(Button)findViewById(R.id.title_bar_rightBtn);
		 center_tv=(TextView) findViewById(R.id.center_tv);
		 title_linearlayout=(LinearLayout) findViewById(R.id.title_bar_linearLayout);
		 linear_leftBtn=(Button) findViewById(R.id.title_bar_linear_leftBtn);
		 linear_rightBtn=(Button) findViewById(R.id.title_bar_linear_rightBtn);
		
		
		
	}
	public void setCommonTitle(int leftImg_vi,int centerLinear_vi,int textView_vi,int rightBtn_vi)
	{
	   
		leftImg.setVisibility(leftImg_vi);
		title_linearlayout.setVisibility(centerLinear_vi);
		center_tv.setVisibility(textView_vi);
		rightBtn.setVisibility(rightBtn_vi);
		
	}
	public void setDefaultImgLeft(int icon){
		Drawable img=mContext.getResources().getDrawable(icon);
		leftImg.setImageDrawable(img);;
	}
	public void setUserImgLeft(Bitmap bitmap)
	{
		leftImg.setImageBitmap(bitmap);
		
	}
	public void setBtnRight(int icon)
	{
		rightBtn.setText(icon);
		
	}
	public void setBtnRightText(String str)
	{
		rightBtn.setText(str);
		
	}
	
	public void setBtnRightIcon(int icon)
	{
		
		Drawable img=mContext.getResources().getDrawable(icon);
		rightBtn.setBackgroundDrawable(img);
		
	}
	public void setBtnRightDrawable(Drawable img)
	{
		
		rightBtn.setBackgroundDrawable(img);
		
	}
	
	public void setTitleLeft(int resId){
		linear_leftBtn.setText(resId);
	}
	
	public void setTitleRight(int resId){
		linear_rightBtn.setText(resId);
	}
	public void setTitleText(int txtRes){
		center_tv.setText(txtRes);
	}
	
	public void setLefImgtOnclickListener(OnClickListener listener){
		leftImg.setOnClickListener(listener);
	}
	
	public void setBtnRightOnclickListener(OnClickListener listener){
		rightBtn.setOnClickListener(listener);
	}
	
	public ImageView getTitleLeft(){
		return leftImg;
	}
	
	public Button getTitleRight(){
		return rightBtn;
	}

	
	
}
能够看到,自定义的TitleBarView继承自RelativeLayout,由于咱们前面布局文件中根布局使用的是RelativeLayout,固然也能够不这么作,但这样作规范一些,而后自定义控件TitleBarView的构造函数中使用LayoutInflater.from(mContext).inflate(R.layout.common_title_bar, this);语句将common_title_bar布局文件中的布局解析出来,固然我这里为了代码规范,在自定义控件TitleBarView的构造函数中使用的是findView()函数,而后在该函数中对控件进行初始化,这样作代码逻辑清晰。而后在该TitleBarView中提供一些

方法来控制组合控件的可见性与某些功能,由于咱们知道腾讯QQ的标题栏随着底部不一样button被点击标题栏中间会显示不一样的控件,这咱们在前面已经分析过,所以咱们须要提供一个控制这些组合控件可见性的方法,除了可见性外还需提供一些功能方法,这个视具体业务需求而定,这样会具有更好的扩展性。this


经过前面两个步骤,一个自定义的组合控件就已经完成了,余下的就是如何使用了,这个也很简单,在须要使用该自定义控件的布局文件中使用该自定义控件完整的路径名便可,即包名+类名,以下所示:spa

<com.example.view.TitleBarView
    android:id="@+id/title_bar"
    android:layout_width="fill_parent"
    android:layout_height="50dp"
    >
    
</com.example.view.TitleBarView>

运行以后效果以下:



这样一个高仿腾讯QQ的标题栏就作出来了,固然这个运行结果是个人高仿腾讯QQ即时IM项目的运行结果,前面的代码也是在该项目中用到的代码,该项目已开源,若是看官想体验完整的效果能够 follow个人github,start与fork个人开源项目,个人githubhttps://github.com/HuTianQi


若是你们以为不错记得小手一抖点个赞哦,欢迎你们关注个人博客帐号,将会不按期为你们分享技术干货,福利多多哦!

相关文章
相关标签/搜索