在软件开发过程中,经常见到,就是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. Bouncycastle中的RSA技术以及解决之道

    一个使用bouncycastle进行安全操作的实用类 2007-04-13 12:54 import java.io.*;import java.security.*;import java.secu ...

  2. bzoj3034: Heaven Cow与God Bull

    Description __int64 ago,there's a heaven cow called sjy...A god bull named wzc fell in love with her ...

  3. PHP替换,只替换匹配到的第一个

    function str_replace_limit($search, $replace, $subject, $limit=-1) { if (is_array($search)) { foreac ...

  4. android学习笔记22——Notification

    Notification ==> Notification是显示在手机状态栏的消息,位于手机屏幕的最上方: 一般显示手机当前网络.电池状态.时间等: Notification所代表的是一种全局效 ...

  5. beego里面自定义配置文件

    beego编译好的exe通过全路径调用会crash,看了半天,发现是解析不到配置文件,研究了下 发现beego自定义配置文件以后,需要手工parse,我表示,以为是自动化的,没想到是半自动化的…… 追 ...

  6. hist和bar画图关系

    1.hist是绘制直方图,直方图显示了数据值的分布情况.  1>n = hist(Y,n)      将向量Y中的元素分到n个等间隔的范围内(默认为10个间隔),并返回每个范围内元素的个数作为一 ...

  7. 编译在arm板上使用的sqlite3的静动态库

    采用的是sqlite-autoconf-3080002.tar.gz 解压 tar xvf sqlite-autoconf-3080002.tar.gz 进入 cd sqlite-autoconf-3 ...

  8. 常​用​的​邮​箱​服​务​器​(​S​M​T​P​、​P​O​P​3​)​地​址​、​端​口

    常用的邮箱服务器(SMTP.POP3)地址.端口 gmail(google.com)  POP3服务器地址:pop.gmail.com(SSL启用 端口:995)  SMTP服务器地址:smtp.gm ...

  9. C++库大全(转)

    基础类1. Dinkumware C++ Library 参考站点:http://www.dinkumware.com P.J. Plauger编写的高品质的标准库.P.J. Plauger博士是Dr ...

  10. Form_Form Builder本地部署运行的实现(案例)

    2014-08-09 Created By BaoXinjian