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

来源:互联网 发布:手机捏人软件 编辑:程序博客网 时间:2024/06/05 19:07

效果图:
这里写图片描述
现在市场上大多数软件都是类似于上面的结构,底部有几个按钮用于切换到不同的界面。基于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);    }}

源代码下载

0 0