博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
TabBottomFragmentLayout【自定义底部选项卡区域(搭配Fragment)】
阅读量:5088 次
发布时间:2019-06-13

本文共 10853 字,大约阅读时间需要 36 分钟。

版权声明:本文为HaiyuKing原创文章,转载请注明出处!

前言

自定义底部选项卡布局LinearLayout类,然后配合Fragment,实现切换Fragment功能。

缺点:

1、底部选项卡区域的高度值需要使用一个固定值,并且和使用的图片资源的高度相匹配。

比如,Demo中设置的底部选项卡的高度值为52dp,那么就需要使用drawable-xxhdpi目录下的72X72大小的图片资源。并且在图片资源中设计好内边距:

2、activity_main.xml布局文件中引用TabBottomLayout的时候,需要注意使用当前项目的TabBottomFragmentLayout的完整路径

效果图

代码分析

TabBottomFragmentLayout:底部选项卡布局类——自定义的LinearLayout子类;实现了各个选项卡的布局、状态切换、点击事件的回调。

切换Fragment采用的是add-hide-show方式,而不是replace方式。所以fragment会在add的时候初始化一次,切换的时候不会重加载。

使用步骤

一、项目组织结构图

注意事项:

1、导入类文件后需要change包名以及重新import R文件路径

2、Values目录下的文件(strings.xml、dimens.xml、colors.xml等),如果项目中存在,则复制里面的内容,不要整个覆盖

二、导入步骤

将TabBottomFragmentLayout.java文件复制到项目中

package com.why.project.tabbottomfragmentlayoutdemo.views.tab;import android.content.Context;import android.graphics.drawable.Drawable;import android.support.v4.content.ContextCompat;import android.util.AttributeSet;import android.view.Gravity;import android.view.LayoutInflater;import android.view.View;import android.widget.CheckedTextView;import android.widget.LinearLayout;import com.why.project.tabbottomfragmentlayoutdemo.R;import java.util.ArrayList;import java.util.Arrays;import java.util.List;/** * @Create By HaiyuKing * @Used 底部选项卡布局类(注意:这个是tab_bottom_item的父布局) */public class TabBottomFragmentLayout extends LinearLayout{    private Context mContext;        //选项卡的CheckedTextView控件的android:drawableTop属性的数组【是一系列selector选择器xml文件】,所以类型是int    //底部选项卡对应的图标    private int[] bottomtab_IconIds = {R.drawable.home_tab_home_selector,R.drawable.home_tab_message_selector,R.drawable.home_tab_contact_selector};    //底部选项卡对应的文字    //CharSequence与String都能用于定义字符串,但CharSequence的值是可读可写序列,而String的值是只读序列。    private CharSequence[] bottomtab_Titles = {getResources().getString(R.string.home_function_home),getResources().getString(R.string.home_function_message),getResources().getString(R.string.home_function_contact)};        //选项卡的各个选项的view的集合:用于更改背景颜色    private List
bottomtab_Items = new ArrayList
(); //选项卡的各个选项的CheckedTextView的集合:用于切换时改变图标和文字颜色 private List
bottomTab_checkeds = new ArrayList
(); public TabBottomFragmentLayout(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; List
tab_titleList = new ArrayList
(); tab_titleList = Arrays.asList(bottomtab_Titles); //初始化view:创建多个view对象(引用tab_bottom_item文件),设置图片和文字,然后添加到这个自定义类的布局中 initAddBottomTabItemView(tab_titleList); } //初始化控件 private void initAddBottomTabItemView(List
tabTitleList){ int countChild = this.getChildCount(); if(countChild > 0){ this.removeAllViewsInLayout();//清空控件 //将各个选项的view添加到集合中 bottomtab_Items.clear(); //将各个选项卡的各个选项的标题添加到集合中 bottomTab_checkeds.clear(); } //设置要添加的子布局view的参数 LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); params.weight = 1;//在tab_bottom_item文件的根节点RelativeLayout中是无法添加的,而这个是必须要写上的,否则只会展现一个view params.gravity = Gravity.CENTER; for(int index=0;index
TabBottomFragmentLayout

 后续可根据实际情况修改图标的selector文件、选项卡的文字内容:

//选项卡的CheckedTextView控件的android:drawableTop属性的数组【是一系列selector选择器xml文件】,所以类型是int    //底部选项卡对应的图标    private int[] bottomtab_IconIds = {
R.drawable.home_tab_home_selector,R.drawable.home_tab_message_selector,R.drawable.home_tab_contact_selector}; //底部选项卡对应的文字 //CharSequence与String都能用于定义字符串,但CharSequence的值是可读可写序列,而String的值是只读序列。 private CharSequence[] bottomtab_Titles = {
getResources().getString(R.string.home_function_home),getResources().getString(R.string.home_function_message),getResources().getString(R.string.home_function_contact)};

将tab_bottom_item.xml文件复制到项目中

tab_bottom_item

将图片资源和selector文件复制到项目中【后续可根据实际情况更换图片

 

在colors.xml文件中添加以下代码:【后续可根据实际情况更改背景颜色、文字颜色值】

#3F51B5
#303F9F
#FF4081
#00000000
#00000000
#8a8a8a
#38ADFF

在dimens.xml文件中添加以下代码:【后续可根据实际情况更改底部选项卡区域的高度值、文字大小值】

16dp
16dp
52dp
14sp
16sp
18sp
20sp

在strings.xml文件中添加以下代码:【后续可根据实际情况更改底部选项卡的文字内容】

TabBottomFragmentLayoutDemo
首页
消息
我的

至此,TabBottomFragmentLayout类集成到项目中了。

三、使用方法

在Activity布局文件中引用TabBottomFragmentLayout布局类【注意:需要重新引用TabBottomFragmentLayout类的完整路径】

创建需要用到的fragment类和布局文件【后续可根据实际情况更改命名,并且需要重新import R文件】

 

MainFragment的布局文件:

在Activity中使用如下【继承FragmentActivity或者其子类

package com.why.project.tabbottomfragmentlayoutdemo;import android.os.Bundle;import android.support.v4.app.FragmentActivity;import android.support.v4.app.FragmentManager;import android.support.v4.app.FragmentTransaction;import android.util.Log;import com.why.project.tabbottomfragmentlayoutdemo.fragment.HomeFragment;import com.why.project.tabbottomfragmentlayoutdemo.fragment.MessageFragment;import com.why.project.tabbottomfragmentlayoutdemo.fragment.ContactFragment;import com.why.project.tabbottomfragmentlayoutdemo.views.tab.TabBottomFragmentLayout;public class MainActivity extends FragmentActivity {    private static final String TAG = "MainActivity";    //自定义底部选项卡    private TabBottomFragmentLayout mBottomTabLayout;    private FragmentManager fragmentManager;//碎片管理器    /**碎片声明*/    private HomeFragment homeFragment;//首页    private MessageFragment messageFragment;//消息    private ContactFragment contactFragment;//我的    /**首页fragment索引值--需要和TabBottomLayout中的数组的下标值对应*/    public static final int Home_Fragment_Index = 0;    /**消息fragment索引值*/    public static final int Message_Fragment_Index = 1;    /**我的fragment索引值*/    public static final int Contact_Fragment_Index = 2;    /**保存的选项卡的下标值*/    private int savdCheckedIndex = Home_Fragment_Index;    /**当前的选项卡的下标值*/    private int mCurrentIndex = -1;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //初始化控件        initView();        //初始化数据        initData();        //初始化控件的点击事件        initEvent();        //初始化碎片管理器        fragmentManager = getSupportFragmentManager();    }    @Override    protected void onResume() {        // TODO Auto-generated method stub        super.onResume();        Log.w(TAG, "{onResume}");        //设置保存的或者初始的选项卡标红显示        SwitchTab(savdCheckedIndex);        mCurrentIndex = -1;//解决按home键后长时间不用,再次打开显示空白的问题        //设置保存的或者初始的选项卡展现对应的fragment        ShowFragment(savdCheckedIndex);    }    /**     * 初始化控件     * */    private void initView(){        mBottomTabLayout = (TabBottomFragmentLayout) findViewById(R.id.bottomtab_Layout);    }    /**初始化数据*/    private void initData() {    }    /**     * 初始化点击事件     * */    private void initEvent(){        //每一个选项卡的点击事件        mBottomTabLayout.setOnBottomTabSelectedListener(new TabBottomFragmentLayout.OnBottomTabSelectListener() {            @Override            public void onBottomTabSelected(int index) {                ShowFragment(index);//独立出来,用于OnResume的时候初始化展现相应的Fragment            }        });    }    /**控制切换选项卡*/    public void SwitchTab(int checkedIndex){        if(mBottomTabLayout != null){            mBottomTabLayout.setTabsDisplay(checkedIndex);        }    }    /**     * 显示选项卡对应的Fragment*/    public void ShowFragment(int checkedIndex){        if(mCurrentIndex == checkedIndex) {            return;        }        //开启一个事务        FragmentTransaction transcation = fragmentManager.beginTransaction();        //隐藏全部碎片        hideFragments(transcation);        switch (checkedIndex) {            case Home_Fragment_Index:                if(homeFragment == null){                    homeFragment = HomeFragment.getInstance(HomeFragment.class,null);                    transcation.add(R.id.center_layout, homeFragment);                }else{                    transcation.show(homeFragment);                }                break;            case Message_Fragment_Index:                if(messageFragment == null){                    messageFragment = MessageFragment.getInstance(MessageFragment.class,null);                    transcation.add(R.id.center_layout, messageFragment);                }else{                    transcation.show(messageFragment);                }                break;            case Contact_Fragment_Index:                if(contactFragment == null){                    contactFragment = ContactFragment.getInstance(ContactFragment.class,null);                    transcation.add(R.id.center_layout, contactFragment);                }else{                    transcation.show(contactFragment);                }                break;            default:                break;        }        savdCheckedIndex = checkedIndex;        mCurrentIndex = checkedIndex;        transcation.commitAllowingStateLoss();    }    /**隐藏全部碎片     * 需要注意:不要在OnResume方法中实例化碎片,因为先添加、显示,才可以隐藏。否则会出现碎片无法显示的问题*/    private void hideFragments(FragmentTransaction transaction) {        if (null != homeFragment) {            transaction.hide(homeFragment);        }        if (null != messageFragment) {            transaction.hide(messageFragment);        }        if (null != contactFragment) {            transaction.hide(contactFragment);        }    }    /**     * http://blog.csdn.net/caesardadi/article/details/20382815     * */    // 自己记录fragment的位置,防止activity被系统回收时,fragment错乱的问题【按home键返回到桌面一段时间,然后在进程里面重新打开,会发现RadioButton的图片选中状态在第二个,但是文字和背景颜色的选中状态在第一个】    //onSaveInstanceState()只适合用于保存一些临时性的状态,而onPause()适合用于数据的持久化保存。    protected void onSaveInstanceState(Bundle outState) {        //http://www.cnblogs.com/chuanstone/p/4672096.html?utm_source=tuicool&utm_medium=referral        //总是执行这句代码来调用父类去保存视图层的状态”。其实到这里大家也就明白了,就是因为这句话导致了重影的出现        //super.onSaveInstanceState(outState);        outState.putInt("selectedCheckedIndex", savdCheckedIndex);        outState.putInt("mCurrentIndex", mCurrentIndex);    }    @Override    protected void onRestoreInstanceState(Bundle savedInstanceState) {        savdCheckedIndex = savedInstanceState.getInt("selectedCheckedIndex");        mCurrentIndex = savedInstanceState.getInt("mCurrentIndex");        super.onRestoreInstanceState(savedInstanceState);    }}

 

混淆配置

参考资料

暂时空缺

项目demo下载地址

转载于:https://www.cnblogs.com/whycxb/p/7183055.html

你可能感兴趣的文章
第二次作业
查看>>
【input】 失去焦点时 显示默认值 focus blur ★★★★★
查看>>
Java跟Javac,package与import
查看>>
day-12 python实现简单线性回归和多元线性回归算法
查看>>
Json格式的字符串转换为正常显示的日期格式
查看>>
[转]使用 Razor 进行递归操作
查看>>
[转]Android xxx is not translated in yyy, zzz 的解决方法
查看>>
docker入门
查看>>
Android系统--输入系统(十一)Reader线程_简单处理
查看>>
监督学习模型分类 生成模型vs判别模型 概率模型vs非概率模型 参数模型vs非参数模型...
查看>>
Mobiscroll脚本破解,去除Trial和注册时间限制【转】
查看>>
实验五 Java网络编程及安全
查看>>
32位与64位 兼容编程
查看>>
iframe父子页面通信
查看>>
ambari 大数据安装利器
查看>>
java 上传图片压缩图片
查看>>
magento 自定义订单前缀或订单起始编号
查看>>
ACM_拼接数字
查看>>
计算机基础作业1
查看>>
Ubuntu 深度炼丹环境配置
查看>>