Android自定义组合控件--底部多按钮切换

效果图:

现在市场上大多数软件都是类似于上面的结构,底部有几个按钮用于切换到不同的界面。基于OOP思想,我想把下面的一整块布局封装成一个类,也就是我们的自定义组合控件—底部多按钮切换布局,我把它叫做BottomLayout

看上面的布局,几个按钮横向排列,我们先看一下布局

最外面LinearLayout 方向 horizontal,然后5个weight相同的RelativeLayout,每个RelativeLayout里面有一个Button(用了显示选中状态)个ImageView(用来显示红点)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:orientation="horizontal" >

    <RelativeLayout
        android:id="@+id/rl_home"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:clickable="true" >

        <ImageView
            android:id="@+id/iv_new_home"
            android:layout_width="10dp"
            android:layout_height="10dp"
            android:layout_alignParentRight="true"
            android:layout_margin="3dp"
            android:src="@drawable/read_circle" />

        <Button
            android:id="@+id/btn_home"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_centerInParent="true"
            android:background="@drawable/tab_home_selector"
            android:clickable="false" />
    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/rl_encounter"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:clickable="true" >

        <Button
            android:id="@+id/btn_encounter"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_centerInParent="true"
            android:background="@drawable/tab_enconter_selector"
            android:clickable="false" />
    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/rl_community"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:clickable="true" >

        <ImageView
            android:id="@+id/iv_new_community"
            android:layout_width="10dp"
            android:layout_height="10dp"
            android:layout_alignParentRight="true"
            android:layout_margin="3dp"
            android:src="@drawable/read_circle" />

        <Button
            android:id="@+id/btn_community"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_centerInParent="true"
            android:background="@drawable/tab_community_selector"
            android:clickable="false" />
    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/rl_message"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:clickable="true" >

        <ImageView
            android:id="@+id/iv_new_message"
            android:layout_width="10dp"
            android:layout_height="10dp"
            android:layout_alignParentRight="true"
            android:layout_margin="3dp"
            android:src="@drawable/read_circle" />

        <Button
            android:id="@+id/btn_message"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_centerInParent="true"
            android:background="@drawable/tab_message_selector"
            android:clickable="false" />
    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/rl_user"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:clickable="true" >

        <Button
            android:id="@+id/btn_user"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_centerInParent="true"
            android:background="@drawable/tab_user_selector"
            android:clickable="false" />
    </RelativeLayout>

</LinearLayout>

下面就是代码了

package comzyh.bottomlayout;

import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;

/**
 * 主界面底部的按钮切换布局
 *
 * @version 1.0
 * @author zyh
 */
public class BottomLayout extends LinearLayout implements OnClickListener {

    public BottomLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    public BottomLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BottomLayout(Context context) {
        this(context, null, 0);
    }

    private Context context;
    private View rl_home, rl_encounter, rl_community, rl_message, rl_user;
    private View iv_new_message, iv_new_home;
    private Button btn_home, btn_encounter, btn_community, btn_message, btn_user;
    private OnItemClickListener listener;
    private int currentPosition = 0;

    /**
     * 初始化
     *
     * @version 1.0
     * @author zyh
     * @param context
     */
    private void init(Context context) {
        this.context = context;
        LayoutInflater.from(context).inflate(R.layout.layout_bottom, this);
        // 5块等分的布局
        rl_home = findViewById(R.id.rl_home);
        rl_encounter = findViewById(R.id.rl_encounter);
        rl_community = findViewById(R.id.rl_community);
        rl_message = findViewById(R.id.rl_message);
        rl_user = findViewById(R.id.rl_user);

        // 5个按钮
        btn_home = (Button) findViewById(R.id.btn_home);
        btn_encounter = (Button) findViewById(R.id.btn_encounter);
        btn_community = (Button) findViewById(R.id.btn_community);
        btn_message = (Button) findViewById(R.id.btn_message);
        btn_user = (Button) findViewById(R.id.btn_user);

        // 小圆点
        iv_new_home = findViewById(R.id.iv_new_home);
        iv_new_message = findViewById(R.id.iv_new_message);

        hideHomeCircle();
        hideMessageCircle();
        changeButtonStatus(0);// 默认是位置0
        setListener();
    }

    /**
     * 显示首页按钮旁边的小红圈
     *
     * @version 1.0
     * @author zyh
     */
    public void showHomeCircle() {
        iv_new_home.setVisibility(View.VISIBLE);
    }

    /**
     * 隐藏首页按钮旁边的小红圈
     *
     * @version 1.0
     * @author zyh
     */
    public void hideHomeCircle() {
        iv_new_home.setVisibility(View.GONE);
    }

    /**
     * 显示首页按钮旁边的小红圈
     *
     * @version 1.0
     * @author zyh
     */
    public void showMessageCircle() {
        iv_new_message.setVisibility(View.VISIBLE);
    }

    /**
     * 隐藏首页按钮旁边的小红圈
     *
     * @version 1.0
     * @author zyh
     */
    public void hideMessageCircle() {
        iv_new_message.setVisibility(View.GONE);
    }

    /**
     * 为按钮设计按下监听
     *
     * @version 1.0
     * @author zyh
     */
    private void setListener() {
        rl_home.setOnClickListener(this);
        rl_encounter.setOnClickListener(this);
        rl_community.setOnClickListener(this);
        rl_message.setOnClickListener(this);
        rl_user.setOnClickListener(this);
    }

    /**
     * 提供给外部设置点击Item的接口
     *
     * @version 1.0
     * @author zyh
     * @param listener
     */
    public void setOnItemClickListener(OnItemClickListener listener) {
        this.listener = listener;
    }

    public interface OnItemClickListener {
        public void onItemClick(int position);
    }

    @Override
    public void onClick(View v) {
        currentPosition = 0;
        switch (v.getId()) {
            case R.id.rl_home:
                currentPosition = 0;
                break;
            case R.id.rl_encounter:
                currentPosition = 1;
                break;
            case R.id.rl_community:
                currentPosition = 2;
                break;
            case R.id.rl_message:
                currentPosition = 3;
                break;
            case R.id.rl_user:
                currentPosition = 4;
                break;
        }
        if (listener == null) {
            return;
        }
        listener.onItemClick(currentPosition);
        changeButtonStatus(currentPosition);
    }

    /**
     * 根据当前位置改变按钮选中状态
     *
     * @version 1.0
     * @author zyh
     * @param position
     */
    private void changeButtonStatus(int position) {
        btn_home.setSelected(position == 0);
        btn_encounter.setSelected(position == 1);
        btn_community.setSelected(position == 2);
        btn_message.setSelected(position == 3);
        btn_user.setSelected(position == 4);
    }
}
  • 设置5个RelativeLayout为点击区域,防止有的地方点击没反应,设置到Button上(Button的background有可能变形)
  • 封装Item点击的监听器
  • 提供显示隐藏小圆点的方法

上面的布局可以进行一点优化

查看布局层次,发现中间多了一层LinearLayout,为什么呢?

因为我们的BottomLayout本身继承自LinearLayout,而且我们在代码中这样写的

LayoutInflater.from(context).inflate(R.layout.layout_bottom, this);

又添加了一层布局,怎么优化呢?

  • 使用merge节点来消除冗余节点

    所以布局文件我们可以写成下面

    <?xml version="1.0" encoding="utf-8"?>
    <merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:gravity="center"
    android:orientation="horizontal" >
    
    <RelativeLayout
        android:id="@+id/rl_home"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:clickable="true" >
    
        <ImageView
            android:id="@+id/iv_new_home"
            android:layout_width="10dp"
            android:layout_height="10dp"
            android:layout_alignParentRight="true"
            android:layout_margin="3dp"
            android:src="@drawable/read_circle" />
    
        <Button
            android:id="@+id/btn_home"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_centerInParent="true"
            android:background="@drawable/tab_home_selector"
            android:clickable="false" />
    </RelativeLayout>
    
    <RelativeLayout
        android:id="@+id/rl_encounter"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:clickable="true" >
    
        <Button
            android:id="@+id/btn_encounter"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_centerInParent="true"
            android:background="@drawable/tab_enconter_selector"
            android:clickable="false" />
    </RelativeLayout>
    
    <RelativeLayout
        android:id="@+id/rl_community"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:clickable="true" >
    
        <Button
            android:id="@+id/btn_community"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_centerInParent="true"
            android:background="@drawable/tab_community_selector"
            android:clickable="false" />
    </RelativeLayout>
    
    <RelativeLayout
        android:id="@+id/rl_message"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:clickable="true" >
    
        <ImageView
            android:id="@+id/iv_new_message"
            android:layout_width="10dp"
            android:layout_height="10dp"
            android:layout_alignParentRight="true"
            android:layout_margin="3dp"
            android:src="@drawable/read_circle" />
    
        <Button
            android:id="@+id/btn_message"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_centerInParent="true"
            android:background="@drawable/tab_message_selector"
            android:clickable="false" />
    </RelativeLayout>
    
    <RelativeLayout
        android:id="@+id/rl_user"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:clickable="true" >
    
        <Button
            android:id="@+id/btn_user"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_centerInParent="true"
            android:background="@drawable/tab_user_selector"
            android:clickable="false" />
    </RelativeLayout>
    </merge>

    关于merge可以看我的这篇Android 视图优化merge标签分析

下面在主界面中

<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="match_parent" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

    <comzyh.bottomlayout.BottomLayout
        android:id="@+id/layout_bottom"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:layout_alignParentBottom="true"
        android:background="@android:color/darker_gray" />

</RelativeLayout>

使用自定义组合控件

public class MainActivity extends Activity {

    private BottomLayout layout_bottom;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        layout_bottom = (BottomLayout) findViewById(R.id.layout_bottom);
        layout_bottom.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(int position) {
                Toast.makeText(MainActivity.this, "点击了" + position, 0).show();
            }
        });

        new Handler().postDelayed(new Runnable() {
            public void run() {
                layout_bottom.showHomeCircle();
            }
        }, 5000);

        new Handler().postDelayed(new Runnable() {
            public void run() {
                layout_bottom.showMessageCircle();
            }
        }, 8000);
    }

}

源代码下载

时间: 2024-10-10 06:19:45

Android自定义组合控件--底部多按钮切换的相关文章

Android 自定义组合控件小结

引言 接触Android UI开发的这段时间以来,对自定义组合控件有了一定的了解,为此小结一下,本文小结内容主要讨论的是如何使用Android SDK提供的布局和控件组成一个功能完整组合控件并将其封装为面向对象的类,而并非讨论如何继承自SDK提供的控件类(比如TextView),对其进行自定义扩展的问题. 进入正题前,我们先来看一组功能需求 假设在手机需求上,那么如上三个界面我们可以使用三个Activity,每个Activity一个布局文件,实现起来比较独立,但是假设在Android pad上要

android 自定义组合控件

自定义控件是一些android程序员感觉很难攻破的难点,起码对我来说是这样的,但是我们可以在网上找一些好的博客关于自定义控件好好拿过来学习研究下,多练,多写点也能找到感觉,把一些原理弄懂,今天就讲下自定义组合控件,这个特别适合在标题栏或者设置界面,看下面图: 就非常适合使用组合控件了,现在写一个玩玩: activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

Android自定义组合控件--图片加文字,类似视频播放软件的列表

分四步来写: 1,组合控件的xml; 2,自定义组合控件的属性; 3,自定义继承组合布局的class类,实现带两参数的构造器; 4,在xml中展示组合控件. 具体实现过程: 一.组合控件的xml 我接触的有两种方式,一种是普通的Activity的xml:一种是父节点为merge的xml.我项目中用的是第一种,但个人感觉第二种好,因为第一种多了相对或者绝对布局层. 我写的 custom_pictext.xml <?xml version="1.0" encoding="u

Android自定义组合控件的实现

需求:在黑马做安全卫士的时候,功能9设置中心界面如下: 在点击item的时候,复选框会反转状态,同时"自动更新已经关闭"会变换内容和颜色. 可以发现这个界面类似ListView,但又不是ListView,因为它的item数量是固定的,且最后一 item和之前的都不一样.虽然这个看着像是标准的List结构,实则每个item不是完全一样,因为 每个item的提示文本(如"自动更新已经关闭")的内容并不完全一样. 假如用一般方式来布局的话,4个item就会有3*4 = 1

Android自定义组合控件---教你如何自定义下拉刷新和左滑删除

绪论 最近项目里面用到了下拉刷新和左滑删除,网上找了找并没有可以用的,有比较好的左滑删除,但是并没有和下拉刷新上拉加载结合到一起,要不就是一些比较水的结合,并不能在项目里面使用,小编一着急自己组合了一个,做完了和QQ的对比了一下,并没有太大区别,今天分享给大家,其实并不难,但是不知道为什么网上没有比较好的Demo,当你的项目真的很急的时候,又没有比较好的Demo,那么"那条友谊的小船儿真是说翻就翻啊",好了,下面先来具体看一下实现后的效果吧: 代码已经上传到Github上了,小伙伴们记

Android自定义组合控件

今天和大家分享下组合控件的使用.很多时候android自定义控件并不能满足需求,如何做呢?很多方法,可以自己绘制一个,可以通过继承基础控件来重写某些环节,当然也可以将控件组合成一个新控件,这也是最方便的一个方法.今天就来介绍下如何使用组合控件,将通过两个实例来介绍.第一个实现一个带图片和文字的按钮,如图所示: 整个过程可以分四步走.第一步,定义一个layout,实现按钮内部的布局.代码如下: <?xml version="1.0" encoding="utf-8&quo

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

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

android 自定义组合控件 顶部导航栏

在软件开发过程中,经常见到,就是APP 的标题栏样式几乎都是一样的,只是文字不同而已,两边图标不同.为了减少重复代码,提高效率, 方便大家使用,我们把标题栏通过组合的方式定义成一个控件. 例下图: 点击: 如不设置左边,右边图片: 下面说一下具体实现步骤: 步骤一: 导航栏包括:* 返回按钮* 标题* 右侧按钮(功能不确定) 首先是布局文件,如下: </pre><p></p><pre name="code" class="java&q

(转)android自定义组合控件

原文地址:http://mypyg.iteye.com/blog/968646 目标:实现textview和ImageButton组合,可以通过Xml设置自定义控件的属性. 1.控件布局:以Linearlayout为根布局,一个TextView,一个ImageButton. Xml代码   <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://