文档章节

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

htq
 htq
发布于 2016/07/26 09:41
字数 1920
阅读 14
收藏 0
点赞 0
评论 0


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

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

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

3自绘控件:即直接继承自View类,然后自己重写onDraw方法,某些情况下可能需要重写onMeasure方法。


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


可以看到在左侧是一个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被点击标题栏中间会显示不同的控件,这我们在前面已经分析过,因此我们需要提供一个控制这些组合控件可见性的方法,除了可见性外还需提供一些功能方法,这个视具体业务需求而定,这样会具备更好的扩展性。


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

<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


如果大家觉得不错记得小手一抖点个赞哦,欢迎大家关注我的博客账号,将会不定期为大家分享技术干货,福利多多哦!




本文转载自:http://blog.csdn.net/htq__/article/details/52014989

共有 人打赏支持
htq

htq

粉丝 19
博文 67
码字总数 1007
作品 3
武汉
Android系统源码分析团体项目BeesAndroid正式上线啦

嗨,BeesAndroid开源技术小组正式成立啦,Bees,即蜜蜂,取义分享、合作与奉献的意思,这也是BeesAndroid小组的宗旨,我们第一个团体项目BeesAndroid也于2018年3月6日同步上线,该项目的前 ...

郭孝星 ⋅ 03/08 ⋅ 0

android--------自定义控件 之 基本实现篇

前面简单的讲述了Android中自定义控件中的几个方法,今天通过代码来实现一个简单的案例 自定义一个扇形图 自定义控件示例: 这里先介绍继承View的方式为例 在布局中如何使用 我用了两种模式,...

切切歆语 ⋅ 05/02 ⋅ 0

Android自定义View全解

目录 1. 自定义View基础 1.1 分类 自定义View的实现方式有以下几种 1.2 View绘制流程 View的绘制基本由measure()、layout()、draw()这个三个函数完成 1.3 坐标系 在Android坐标系中,以屏幕左...

銀灬楓 ⋅ 05/10 ⋅ 0

android--------自定义控件 之 基本流程篇

在我们平常的Android开发中经常和控件打交道,有时Android提供的控件未必能满足业务的需求,这个时候就需要我们实现自定义一些控件 自定义控件可以设计出很多你想要的功能和模块,在开发中是...

切切歆语 ⋅ 04/30 ⋅ 0

android悬浮窗、收款二维码、相机处理、事件通知库、NFC读取等源码

Android精选源码 一个漂亮而强大的自定义view SeekBar(http://www.apkbus.com/thread-598080-1-1.html) 适用于Android的简单NFC读取源码(http://www.apkbus.com/thread-598082-1-1.html) 安卓......

逆鳞龙 ⋅ 04/24 ⋅ 0

Android文档水印之PDF水印

随着移动终端办公化的普及,在Android手机中阅读文档已经是很普遍的事情了,但是有些文档可能是涉及到一些企业机密与敏感的内容,不希望随意扩散出去。为了防止重要的文档被截屏或者拍照而泄...

sunrongxin.py ⋅ 2017/03/05 ⋅ 0

android--------自定义控件 之 属性篇

上篇介绍了自定义控件的一个简单案例,本篇文章主要介绍如何给自定义控件自定义一些属性。 Android 中使用自定义属性的一般步骤: 定义declare-styleable,添加attr 使用TypedArray获取自定义...

切切歆语 ⋅ 05/03 ⋅ 0

Android项目实战(三十八):2017最新 将AndroidLibrary提交到JCenter仓库(图文教程)

我们经常使用github上的开源项目,使用步骤也很简单 比如: compile 'acffo.xqx.xwaveviewlib:maven:1.0.0' 这里就学习一下如何将自己的类库做出这种可以供他人使用的开源项目。 一、Android...

听着music睡 ⋅ 2017/11/15 ⋅ 0

Android性能优化:那些不可忽略的绘制优化

前言 在 开发中,性能优化策略十分重要 本文主要讲解性能优化中的绘制优化,希望你们会喜欢。 目录 // 方式2:在 BaseActivity 的 onCreate() 方法中使用下面的代码移除 优化方案2:移除 控件...

Carson_Ho ⋅ 05/21 ⋅ 0

android--------自定义控件 之 方法篇

前面简单的讲述了Android中自定义控件的理论和流程图,今天通过代码来详细的讲解一下其中的方法 首先先创建一个类 CircularView 继承于 View,之后实现构造方法(初始化步骤) View的构造函数...

切切歆语 ⋅ 05/01 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

大数据工程师需要精通算法吗,要达到一个什么程度呢?

机器学习是人工智能的一个重要分支,而机器学习下最重要的就是算法,本文讲述归纳了入门级的几个机器学习算法,加大数据学习群:716581014一起加入AI技术大本营。 1、监督学习算法 这个算法由...

董黎明 ⋅ 27分钟前 ⋅ 0

Kylin 对维度表的的要求

1.要具有数据一致性,主键值必须是唯一的;Kylin 会进行检查,如果有两行的主键值相同则会报错。 2.维度表越小越好,因为 Kylin 会将维度表加载到内存中供查询;过大的表不适合作为维度表,默...

无精疯 ⋅ 30分钟前 ⋅ 0

58到家数据库30条军规解读

军规适用场景:并发量大、数据量大的互联网业务 军规:介绍内容 解读:讲解原因,解读比军规更重要 一、基础规范 (1)必须使用InnoDB存储引擎 解读:支持事务、行级锁、并发性能更好、CPU及...

kim_o ⋅ 34分钟前 ⋅ 0

代码注释中顺序更改 文件读写换行

`package ssh; import com.xxx.common.log.LogFactory; import com.xxx.common.log.LoggerUtil; import org.apache.commons.lang3.StringUtils; import java.io.*; public class DirErgodic ......

林伟琨 ⋅ 42分钟前 ⋅ 0

linux实用操作命令

参考 http://blog.csdn.net/qwe6112071/article/details/50806734 ls [选项] [目录名 | 列出相关目录下的所有目录和文件 -a 列出包括.a开头的隐藏文件的所有文件-A 同-a,但不列出"."和"...

简心 ⋅ 57分钟前 ⋅ 0

preg_match处理中文符号 url编码方法

之前想过直接用符号来替换,但失败了,或者用其他方式,但有有些复杂,这个是一个新的思路,亲测可用 <?php$str='637朗逸·超速新风王(300)(白光)'; $str=iconv("UTF-8","GBK",$s...

大灰狼wow ⋅ 今天 ⋅ 0

DevOps 资讯 | PostgreSQL 的时代到来了吗 ?

PostgreSQL是对象-关系型数据库,BSD 许可证。拼读为"post-gress-Q-L"。 作者: Tony Baer 原文: Has the time finally come for PostgreSQL?(有删节) 近30年来 PostgreSQL 无疑是您从未听...

RiboseYim ⋅ 今天 ⋅ 0

github太慢

1:用浏览器访问 IPAddress.com or http://tool.chinaz.com 使用 IP Lookup 工具获得github.com和github.global.ssl.fastly.net域名的ip地址 2:/etc/hosts文件中添加如下格式(IP最好自己查一...

whoisliang ⋅ 今天 ⋅ 0

非阻塞同步之 CAS

为解决线程安全问题,互斥同步相当于以时间换空间。多线程情况下,只有一个线程可以访问同步代码。这种同步也叫阻塞同步(Blocking Synchronization). 这种同步属于一种悲观并发策略。认为只...

长安一梦 ⋅ 今天 ⋅ 0

云计算的选择悖论如何对待?

人们都希望在工作和生活中有所选择。但心理学家的调查研究表明,在多种选项中进行选择并不一定会使人们更快乐,甚至不会产生更好的决策。心理学家Barry Schwartz称之为“选择悖论”。云计算为...

linux-tao ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部