在软件开发过程中,经常见到,就是APP 的标题栏样式几乎都是一样的,只是文字不同而已,两边图标不同。为了减少重复代码,提高效率, 方便大家使用,我们把标题栏通过组合的方式定义成一个控件。

例下图:

点击:

如不设置左边,右边图片:

下面说一下具体实现步骤:



步骤一:



导航栏包括:

* 返回按钮

* 标题

* 右侧按钮(功能不确定)



首先是布局文件,如下:

</pre><p></p><pre name="code" class="java"><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/holo_blue_light"
tools:context=".MainActivity" > <TextView
android:id="@+id/text_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:textSize="25sp"
android:gravity="center"
android:textColor="@android:color/white"
android:padding="2dp"
/> <ImageView
android:id="@+id/back_image"
android:layout_width="40dp"
android:layout_height="40dp"
android:scaleType="centerInside"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="12dp"
/> <ImageView
android:id="@+id/right_image"
android:layout_width="40dp"
android:layout_height="40dp"
android:scaleType="centerInside"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="12dp"
/> </RelativeLayout>

步骤二:在values下新建 attrs文件 定义控件要用到的属性,如下面的代码所示。这里我们定义了标题栏文字(textText),字体大小(textSize),字体颜色(textColor),左边按钮 (leftBtn ),右边按钮 (rightBtn )  。(当然你还要以给它添加其它属性如背景)

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="Topbar">
<attr name="titleText" format="string|reference" />
<attr name="titleSize" format="dimension|reference" />
<attr name="titleColor" format="color|reference" /> <attr name="leftBtn" format="reference"/>
<attr name="rightBtn" format=" reference"/> </declare-styleable>
</resources>

步骤三:定义类Topbar继承自RelativeLayout,重写构造函数并构造方法中获得我们自定义的属性,具体代码如下。代码中定义了一个TextView显示标题文字,一个Imageview 显示左侧按钮,一个Imageview 显示右侧按钮 ,其他字段对应attrs中声明的属性。

	private ImageView backView;
private ImageView rightView;
private TextView titleView; private String titleTextStr;
private int titleTextSize ;
private int titleTextColor ; private Drawable leftImage ;
private Drawable rightImage ; public TopBarView(Context context){
this(context, null);
} public TopBarView(Context context, AttributeSet attrs) {
this(context, attrs,R.style.AppTheme); } public TopBarView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
getConfig(context, attrs);
initView(context);
} /**
* 从xml中获取配置信息
*/
private void getConfig(Context context, AttributeSet attrs) {
//TypedArray是一个数组容器用于存放属性值
TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.Topbar); int count = ta.getIndexCount();
for(int i = 0;i<count;i++)
{
int attr = ta.getIndex(i);
switch (attr)
{
case R.styleable.Topbar_titleText:
titleTextStr = ta.getString(R.styleable.Topbar_titleText);
break;
case R.styleable.Topbar_titleColor:
// 默认颜色设置为黑色
titleTextColor = ta.getColor(attr, Color.BLACK);
break;
case R.styleable.Topbar_titleSize:
// 默认设置为16sp,TypeValue也可以把sp转化为px
titleTextSize = ta.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));
break; case R.styleable.Topbar_leftBtn: leftImage = ta.getDrawable(R.styleable.Topbar_leftBtn);
break;
case R.styleable.Topbar_rightBtn:
rightImage = ta.getDrawable(R.styleable.Topbar_rightBtn);
break;
}
} //用完务必回收容器
ta.recycle(); } private void initView(Context context)
{
View layout = LayoutInflater.from(context).inflate(R.layout.custom_groupwidget,
this,true); backView = (ImageView) layout.findViewById(R.id.back_image);
titleView = (TextView) layout.findViewById(R.id.text_title);
rightView = (ImageView) layout.findViewById(R.id.right_image);
backView.setOnClickListener(this);
rightView.setOnClickListener(this); if(null != leftImage)
backView.setImageDrawable(leftImage);
if(null != rightImage)
rightView.setImageDrawable(rightImage);
if(null != titleTextStr)
{
titleView.setText(titleTextStr);
titleView.setTextSize(titleTextSize);
titleView.setTextColor(titleTextColor);
}
}

步骤四:定义了一个OnClickListenner来监听ImageView的点击

   private onTitleBarClickListener onMyClickListener;

    /**
* 设置按钮点击监听接口
* @param callback
*/
public void setClickListener(onTitleBarClickListener listener) {
this.onMyClickListener = listener;
} /**
* 导航栏点击监听接口
*/
public static interface onTitleBarClickListener{
/**
* 点击返回按钮回调
*/
void onBackClick(); void onRightClick();
} @Override
public void onClick(View v) {
int id = v.getId();
switch(id)
{
case R.id.back_image:
if(null != onMyClickListener)
onMyClickListener.onBackClick();
break;
case R.id.right_image:
if(null != onMyClickListener)
onMyClickListener.onRightClick();
break;
}
}

步骤五:
再看一下主布局怎样使用自定义控件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:custom="http://schemas.android.com/apk/res/com.example.customgroupwidget"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" > <com.example.customgroupwidget.TopBarView
android:id="@+id/topbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
custom:titleText="我的消息"
custom:titleSize="15sp"
custom:titleColor="@android:color/white"
custom:leftBtn="@drawable/back_page"
custom:rightBtn="@drawable/edit_normal" /> </RelativeLayout>

步骤六:最后看一下Activity中的调用:

public class MainActivity extends Activity implements onTitleBarClickListener {

    private  TopBarView topbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); topbar = (TopBarView)findViewById(R.id.topbar); topbar.setClickListener(this);
}
@Override
public void onBackClick() {
Toast.makeText(MainActivity.this, "你点击了左侧按钮", Toast.LENGTH_LONG).show(); }
@Override
public void onRightClick() {
Toast.makeText(MainActivity.this, "你点击了右侧按钮", Toast.LENGTH_SHORT).show(); }
}

 demo下载

最后普及一下,attrs.xml中的属性的format(类型)说明

1. reference:参考某一资源ID。

(1)属性定义:

<declare-styleable name = "名称">

<attr name = "background" format = "reference" />

</declare-styleable>

(2)属性使用:

<ImageView

android:layout_width = "42dip"

                     android:layout_height = "42dip"

                     android:background = "@drawable/图片ID"

/>

2. color:颜色值。

(1)属性定义:

<declare-styleable name = "名称">

<attr name = "textColor" format = "color" />

</declare-styleable>

(2)属性使用:

<TextView

android:layout_width = "42dip"

                     android:layout_height = "42dip"

                     android:textColor = "#00FF00"

/>

3. boolean:布尔值。

(1)属性定义:

<declare-styleable name = "名称">

<attr name = "focusable" format = "boolean" />

</declare-styleable>

(2)属性使用:

<Button

android:layout_width = "42dip"

                    android:layout_height = "42dip"

android:focusable = "true"

/>

4. dimension:尺寸值。

(1)属性定义:

<declare-styleable name = "名称">

<attr name = "layout_width" format = "dimension" />

</declare-styleable>

(2)属性使用:

<Button

android:layout_width = "42dip"

                    android:layout_height = "42dip"

/>

5. float:浮点值。

(1)属性定义:

<declare-styleable name = "AlphaAnimation">

<attr name = "fromAlpha" format = "float" />

                   <attr name = "toAlpha" format = "float" />

</declare-styleable>

(2)属性使用:

<alpha

                   android:fromAlpha = "1.0"

                   android:toAlpha = "0.7"

/>

6. integer:整型值。

(1)属性定义:

<declare-styleable name = "AnimatedRotateDrawable">

<attr name = "visible" />

                   <attr name = "frameDuration" format="integer" />

                   <attr name = "framesCount" format="integer" />

                   <attr name = "pivotX" />

                   <attr name = "pivotY" />

                   <attr name = "drawable" />

</declare-styleable>

(2)属性使用:

<animated-rotate

xmlns:android = "http://schemas.android.com/apk/res/android

                   android:drawable = "@drawable/图片ID" 

                   android:pivotX = "50%" 

                   android:pivotY = "50%" 

                   android:framesCount = "12" 

                   android:frameDuration = "100"

/>

7. string:字符串。

(1)属性定义:

<declare-styleable name = "MapView">

                   <attr name = "apiKey" format = "string" />

            </declare-styleable>

(2)属性使用:

<com.google.android.maps.MapView

                    android:layout_width = "fill_parent"

                    android:layout_height = "fill_parent"

                    android:apiKey = "0jOkQ80oD1JL9C6HAja99uGXCRiS2CGjKO_bc_g"

/>

8. fraction:百分数。

(1)属性定义:

<declare-styleable name="RotateDrawable">

                   <attr name = "visible" />

                   <attr name = "fromDegrees" format = "float" />

                   <attr name = "toDegrees" format = "float" />

                   <attr name = "pivotX" format = "fraction" />

                   <attr name = "pivotY" format = "fraction" />

                   <attr name = "drawable" />

            </declare-styleable>

(2)属性使用:

<rotate

xmlns:android = "http://schemas.android.com/apk/res/android"

               android:interpolator = "@anim/动画ID"

android:fromDegrees = "0"

               android:toDegrees = "360"

android:pivotX = "200%"

android:pivotY = "300%"

               android:duration = "5000"

android:repeatMode = "restart"

android:repeatCount = "infinite"

/>

9. enum:枚举值。

(1)属性定义:

<declare-styleable name="名称">

                   <attr name="orientation">

                          <enum name="horizontal" value="0" />

                          <enum name="vertical" value="1" />

                   </attr>

</declare-styleable>

(2)属性使用:

<LinearLayout

xmlns:android = "http://schemas.android.com/apk/res/android"

                    android:orientation = "vertical"

                    android:layout_width = "fill_parent"

                    android:layout_height = "fill_parent"

                    >

            </LinearLayout>

10. flag:位或运算。

(1)属性定义:

<declare-styleable name="名称">

                    <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>

</declare-styleable>

(2)属性使用:

<activity

android:name = ".StyleAndThemeActivity"

                   android:label = "@string/app_name"

                   android:windowSoftInputMode = "stateUnspecified | stateUnchanged | stateHidden">

                   <intent-filter>

                          <action android:name = "android.intent.action.MAIN" />

                          <category android:name = "android.intent.category.LAUNCHER" />

                   </intent-filter>

             </activity>

特别要注意:

属性定义时可以指定多种类型值。

(1)属性定义:

<declare-styleable name = "名称">

<attr name = "background" format = "reference|color" />

</declare-styleable>

(2)属性使用:

<ImageView

android:layout_width = "42dip"

                     android:layout_height = "42dip"

                     android:background = "@drawable/图片ID|#00FF00"

/>

android 自定义组合控件 顶部导航栏的更多相关文章

  1. Android自定义组合控件详细示例 (附完整源码)

    在我们平时的Android开发中,有时候原生的控件无法满足我们的需求,或者经常用到几个控件组合在一起来使用.这个时候,我们就可以根据自己的需求创建自定义的控件了,一般通过继承View或其子类来实现. ...

  2. 014 Android 自定义组合控件

    1.需求介绍 将已经编写好的布局文件,抽取到一个类中去做管理,下次还需要使用类似布局时,直接使用该组合控件的对象. 优点:可复用. 例如要重复利用以下布局: <RelativeLayout an ...

  3. Android自定义组合控件

    今天和大家分享下组合控件的使用.很多时候android自定义控件并不能满足需求,如何做呢?很多方法,可以自己绘制一个,可以通过继承基础控件来重写某些环节,当然也可以将控件组合成一个新控件,这也是最方便 ...

  4. Android自定义组合控件内子控件无法显示问题

    今天自定义了一个组合控件,与到了个奇葩问题: 我自定义了一个RelativeLayout,这个layout内有多个子控件.但奇怪的是这些子控件一直显示不出来.调试了一下午,竟然是因为在获取(infla ...

  5. (转)android自定义组合控件

    原文地址:http://mypyg.iteye.com/blog/968646 目标:实现textview和ImageButton组合,可以通过Xml设置自定义控件的属性. 1.控件布局:以Linea ...

  6. Android自定义组合控件:UIScrollLayout(支持界面滑动及左右菜单滑动)

    一.前言: 我之前很早的时候,写过一篇<左右滑出菜单>的文章: http://blog.csdn.net/qingye_love/article/details/8776650 用的是对V ...

  7. Android 自定义组合控件

    1, you need to add this kind of code to the constructors of your custom view which must extend ViewG ...

  8. Android View体系(十)自定义组合控件

    相关文章 Android View体系(一)视图坐标系 Android View体系(二)实现View滑动的六种方法 Android View体系(三)属性动画 Android View体系(四)从源 ...

  9. Android自定义控件之自定义组合控件

    前言: 前两篇介绍了自定义控件的基础原理Android自定义控件之基本原理(一).自定义属性Android自定义控件之自定义属性(二).今天重点介绍一下如何通过自定义组合控件来提高布局的复用,降低开发 ...

随机推荐

  1. HTML 编辑器

    使用 Notepad 或 TextEdit 来编写 HTML 可以使用专业的 HTML 编辑器来编辑 HTML: Adobe Dreamweaver Microsoft Expression Web ...

  2. 关于iis站点无法读取 服务器共享目录的问题

    也是权限问题,具体解决方法如下: 1. 找到该站点所在的应用程序池>>高级设置>>进程模型>>设置标志账号,如下图所示 2. 设置账号之后,找到该共享目录>& ...

  3. 【Struts2学习笔记-6--】Struts2之拦截器

    简单拦截器的使用 拦截器最基本的使用: 拦截方法的拦截器 拦截器的执行顺序 拦截结果的监听器-相当于 后拦截器 执行顺序: 覆盖拦截器栈里特定拦截器的参数 使用拦截器完成-权限控制 主要完成两个功能: ...

  4. Centos5.5下安装cacti

    系统环境OS:CentOSDataBase:MySQL5.0PHP Apachenet-snmp部署CentOS cacti配置需要的环境安装MySQLyum -y install mysqlyum ...

  5. 49. Group Anagrams

    Given an array of strings, group anagrams together. For example, given: ["eat", "tea& ...

  6. 《黄聪:手机移动站SEO优化教程》3、如何禁止百度对PC网站进行自动转码

    视频地址:http://v.youku.com/v_show/id_XNzE2OTM0NzU2.html

  7. 0814JavaScript简介、基本语法、运算符、转换

    一.JavaScript简介 1.JavaScript是个什么东西? 它是个脚本语言,需要有宿主文件,它的宿主文件是HTML文件. 2.它与Java什么关系? 没有什么直接的联系,Java是Sun公司 ...

  8. [实变函数]3.1 外测度 (outer measure)

    1 并不是所有的集合都可求测度. 我们的想法是先对 $\bbR^n$ 中的任一集合定义一个``外 测度'' (outer measure), 然后再加上适当的条件 (Caratheodory 条件), ...

  9. 设置Excel的自动筛选功能

    单元格数字格式的问题 NPOI向Excel文件中插入数值时,可能会出现数字当作文本的情况(即左上角有个绿色三角),这样单元格的值就无法参与运算.这是因为在SetCellValue设置单元格值的时候使用 ...

  10. ci模板布局方式

    1.修改Loader链式加载header和footer方式 参考:http://stackoverflow.com/questions/9540576/header-and-footer-in-cod ...