在软件开发过程中,经常见到,就是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. 关于 Android导出apk时碰到的[Unable to execute dex: Multiple dex files define]

    这是一个编译错误,在ADT的编译器和SDK的工具有差异或是版本不一致时常会出现的一个问题,解决的方案如下: 第一步: updated eclipse (Help->Check for updat ...

  2. 股票自用指标 boll 菜刀

    BI:=(H+L+O+C)/; BOL:EMA(BI,N); UPPER:BOLL+N1*STD(CLOSE,N); LOWER:BOLL-N1*STD(CLOSE,N); MA1:MA(CLOSE, ...

  3. Load an X509 PEM file into Windows CryptoApi

    http://stackoverflow.com/questions/1231178/load-an-x509-pem-file-into-windows-cryptoapi I discovered ...

  4. jQ的toggle()方法示例

    定义和用法toggle() 方法切换元素的可见状态.如果被选元素可见,则隐藏这些元素,如果被选元素隐藏,则显示这些元素. 语法$(selector).toggle(speed,callback,swi ...

  5. c++的历史-异常

    1.异常出现的目的 在c++语言的设计和演化中,Bjarne Stroustrup说过异常的设计假定如下情况: 基本上是为了处理错误 与函数定义相比,异常处理是很少的 与函数调用相比,异常出现的频率较 ...

  6. chmod 权限777 是什么意思(Unix和Linux的各种操作系统下)

    在Unix和Linux的各种操作系统下,每个文件(文件夹也被看作是文件)都按读.写.运行设定权限.例如我用ls -l命令列文件表时,得到如下输出:-rw-r--r-- 1 bu users 2254 ...

  7. ORA-04031案例一则

    ORA-04031这个错误,几乎每一个专业的DBA都遇到过.这是一个相当严重的错误,Oracle进程在向SGA申请内存时,如果申请失败,则会报这个错误.大部分情况下是在向SGA中的shared poo ...

  8. 在Huawei USG2100 上配置通过Huawei VPN客户端的接入

    USG2100 设置 一.本地策略 中允许 Untrust 对 L2TP 的访问: 二.勾选 VPN-->L2TP 启用: 三.设置参数: 1.组类型选择LNS,本端隧道名称LNS,对端隧道名称 ...

  9. 黄聪:chrome扩展开发《AJAX请求》

    chrome在一次更新之后,出于安全考虑,完全的禁止了content_script从https向http发起ajax请求,即使正常情况下也会在console里给出提示.这对于WEB来讲是好事,但对于扩 ...

  10. MySQL key/value存储方案(转)

    需求 250M entities, entities表共有2.5亿条记录,当然是分库的. 典型解决方案:RDBMS 问题:由于业务需要不定期更改表结构,但是在2.5亿记录的表上增删字段.修改索引需要锁 ...