android界面设计笔记(二)底部导航栏的两种实现方式_gabriel1210的博客-程序员宅基地

技术标签: 底部导航栏  android  BottomNavagationBar  

demo:https://github.com/linliangliang/BottomNavagationBar

android底部导航栏的实现方式比较多,今天学习其中两种方式:
一、使用tabLayout+Fragment实现。
二、使用BottomNavagationBar实现。

第一种方式:https://blog.csdn.net/qq_25066049/article/details/84646650
下面介绍BottomNavagationBar的实现:

compile 'com.ashokvarma.android:bottom-navigation-bar:2.0.3'

1、主界面activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context="com.zhengyuan.bottomnavigationbar.MainActivity">

    <FrameLayout
        android:id="@+id/layFrame"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <com.ashokvarma.bottomnavigation.BottomNavigationBar
        android:id="@+id/bottom_navigation_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom" />

</LinearLayout>

Fragment组件用于显示不同的界面这里先定义三个最简单的fragment.xml文件:fragment_con.xml

(还有fragment_don.xml,fragment_msg.xml,不再贴代码)

<?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="match_parent"
    android:gravity="center">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="con" />

</LinearLayout>

显示布局写好后,开始写代码,先分别为三个fragment定义对应的类:

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.zhengyuan.bottomnavigationbar.R;

/**
 * Created by 林亮 on 2018/11/29
 */

public class MsgFragment extends BaseFragment {
    /**
     * 标志位,标志已经初始化完成
     */
    private boolean isPrepared;
    /**
     * 是否已被加载过一次,第二次就不再去请求数据了
     */
    private boolean mHasLoadedOnce;
    TextView textView;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (mView == null) {
            // 需要inflate一个布局文件 填充Fragment
            mView = inflater.inflate(R.layout.fragment_msg, container, false);
            initView();
            isPrepared = true;
            //实现懒加载
            lazyLoad();
        }
        //缓存的mView需要判断是否已经被加过parent, 如果有parent需要从parent删除,要不然会发生这个mView已经有parent的错误。
        ViewGroup parent = (ViewGroup) mView.getParent();
        if (parent != null) {
            parent.removeView(mView);
        }
        return mView;
    }

    /**
     * 初始化控件
     */
    private void initView() {

    }

    @Override
    public void lazyLoad() {
        if (!isPrepared || !isVisible || mHasLoadedOnce) {
            return;
        }
        //填充各控件的数据
        mHasLoadedOnce = true;
    }

    public static MsgFragment newInstance(String param1) {
        MsgFragment fragment = new MsgFragment();
        Bundle args = new Bundle();
        args.putString("agrs1", param1);
        fragment.setArguments(args);
        return fragment;
    }
}

其他两个类一样,不再贴代码。其中有一个baseFragment:

import android.support.v4.app.Fragment;
import android.view.View;

/**
 * Created by 林亮 on 2018/11/29
 */
public abstract class BaseFragment extends Fragment {
    /**
     * Fragment当前状态是否可见
     */
    public boolean isVisible;

    /**
     * inflate布局文件 返回的view
     */
    public View mView;

    /**
     * 简化 findViewById
     *
     * @param viewId
     * @param <T>
     * @return
     */
    protected <T extends View> T find(int viewId) {
        return (T) mView.findViewById(viewId);
    }

    /**
     * setUserVisibleHint是在onCreateView之前调用的
     * 设置Fragment可见状态
     */
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        /**
         * 判断是否可见
         */
        if (getUserVisibleHint()) {
            isVisible = true;
            onVisible();
        } else {
            isVisible = false;
            onInvisible();
        }
    }

    /**
     * 可见
     */
    private void onVisible() {
        lazyLoad();
    }

    /**
     * 不可见
     */
    private void onInvisible() {
    }

    /**
     * 延迟加载
     * 子类必须重写此方法
     */
    public abstract void lazyLoad();
}

最后就是MainActivity.class了:

import android.graphics.Color;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;

import com.ashokvarma.bottomnavigation.BottomNavigationBar;
import com.ashokvarma.bottomnavigation.BottomNavigationItem;
import com.ashokvarma.bottomnavigation.ShapeBadgeItem;
import com.ashokvarma.bottomnavigation.TextBadgeItem;
import com.zhengyuan.bottomnavigationbar.fragment.ContactsFragment;
import com.zhengyuan.bottomnavigationbar.fragment.DongtaiFragment;
import com.zhengyuan.bottomnavigationbar.fragment.MsgFragment;

import java.util.ArrayList;

import static com.ashokvarma.bottomnavigation.ShapeBadgeItem.SHAPE_OVAL;

public class MainActivity extends AppCompatActivity implements BottomNavigationBar.OnTabSelectedListener {

    private ArrayList<Fragment> fragments;
    private BottomNavigationBar bottomNavigationBar;

    private MsgFragment msgFragment;
    private ContactsFragment contactsFragment;
    private DongtaiFragment dongtaiFragment;

    private FragmentManager fragmentManager;
    private FragmentTransaction transaction;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bottomNavigationBar = findViewById(R.id.bottom_navigation_bar);
        init();
    }

    private void init() {
        /*要先设计模式后再添加图标!
        设置按钮模式  MODE_FIXED表示固定   MODE_SHIFTING表示转移
        mode_default:如果选项大于3个,使用mode_shifting,否则使用mode_fixed
        mode_fixed:每个item对应名称,不选中也会显示
        mode_shifting:每个item对应名称,只有选中才会显示,不选中隐藏
        mode_fixed_no_title:相当于mode_fixed只是不显示所有文字
        mode_shifting_no_title:相当于mode_shifting只是不显示所有文字*/
        bottomNavigationBar.setMode(BottomNavigationBar.MODE_FIXED);
        /*设置背景风格
         BACKGROUND_STYLE_STATIC表示静态的
        BACKGROUND_STYLE_RIPPLE表示涟漪的,也就是可以变化的 ,跟随setActiveColor里面的颜色变化*/
        bottomNavigationBar.setBackgroundStyle(BottomNavigationBar.BACKGROUND_STYLE_STATIC);
       /* in-active color:图标和文本未被激活或选中的颜色;默认颜色为Theme’s Primary Color
        active color : 在BACKGROUND_STYLE_STATIC下,为图标和文本激活或选中的颜色;在BACKGROUND_STYLE_RIPPLE下,为整个控件的背景颜色;默认颜色为Color.LTGRAY
        background color :在BACKGROUND_STYLE_STATIC 下,为整个空控件的背景色;在 BACKGROUND_STYLE_RIPPLE 下为图标和文本被激活或选中的颜色;默认颜色为Color.WHITE
        */
        bottomNavigationBar.setInActiveColor(R.color.colorPrimaryDark);//文字图片的背景色
        bottomNavigationBar.setActiveColor(R.color.blue);//bar背景颜色


        /*其中item可以左右上角的数字:*/
        TextBadgeItem numberBadgeItem = new TextBadgeItem();
        ShapeBadgeItem shapeBadgeItem = new ShapeBadgeItem();
        numberBadgeItem.setText("9") //显示的文本
                .setBackgroundColor("#FF0000") //背景色
                .setTextColor("#FFFFFF") //文本颜色
                .setBorderColor("#000000") //border颜色
                .setBorderWidth(5) //border宽度px
                .setBackgroundColorResource(R.color.colorPrimaryDark) //背景色,资源文件获取
                .setBorderColorResource(R.color.colorPrimary) //border颜色,资源文件获取
                .setTextColorResource(R.color.colorAccent) //文本颜色,资源文件获取
                .setAnimationDuration(30) //隐藏和展示的动画速度,单位毫秒,和setHideOnSelect一起使用
                .setGravity(Gravity.RIGHT | Gravity.TOP) //位置,默认右上角
                .setHideOnSelect(true); //true:当选中状态时消失,非选中状态显示,moren false

        shapeBadgeItem.setShape(SHAPE_OVAL) //形状
                .setShapeColor(Color.BLUE) //颜色
                .setShapeColorResource(R.color.colorPrimaryDark) //颜色,资源文件获取
                .setEdgeMarginInDp(this, 0) //距离Item的margin,dp
                .setEdgeMarginInPixels(20) //距离Item的margin,px
                .setSizeInDp(this, 10, 10) //宽高,dp
                .setSizeInPixels(20, 20) //宽高,px
                .setAnimationDuration(200) //隐藏和展示的动画速度,单位毫秒,和setHideOnSelect一起使用
                .setGravity(Gravity.LEFT) //位置,默认右上角
                .setHideOnSelect(true); //true:当选中状态时消失,非选中状态显示,moren false

        //添加并设置图标、图标的颜色和文字
        bottomNavigationBar
                .addItem(new BottomNavigationItem(R.drawable.tab_attention_selector, "消息").setBadgeItem(numberBadgeItem))
                .addItem(new BottomNavigationItem(R.drawable.tab_discovery_selector, "联系人").setBadgeItem(shapeBadgeItem))
                .addItem(new BottomNavigationItem(R.drawable.tab_profile_selector, "动态"))
                .addItem(new BottomNavigationItem(R.drawable.tab_profile_selector, "动态2"))
                .addItem(new BottomNavigationItem(R.drawable.tab_profile_selector, "动态2"))
                .setFirstSelectedPosition(1)
                .initialise();

        bottomNavigationBar.setTabSelectedListener(this);
        setDefaultFragment();
    }

    //设置初始界面
    private void setDefaultFragment() {
        fragmentManager = getSupportFragmentManager();
        transaction = fragmentManager.beginTransaction();
        transaction.replace(R.id.layFrame, MsgFragment.newInstance("消息"));
        transaction.commit();
    }

    @Override
    public void onTabSelected(int position) {
        fragmentManager = getSupportFragmentManager();
        transaction = fragmentManager.beginTransaction();
        switch (position) {
            case 0:
                if (msgFragment == null) {
                    msgFragment = MsgFragment.newInstance("消息");
                }
                transaction.replace(R.id.layFrame, msgFragment);
                break;
            case 1:
                if (contactsFragment == null) {
                    contactsFragment = ContactsFragment.newInstance("联系人");
                }
                transaction.replace(R.id.layFrame, contactsFragment);
                break;
            case 2:
                if (dongtaiFragment == null) {
                    dongtaiFragment = DongtaiFragment.newInstance("动态");
                }
                transaction.replace(R.id.layFrame, dongtaiFragment);
                break;
            default:
                break;
        }
        // 事务提交
        transaction.commit();
    }

    @Override
    public void onTabUnselected(int position) {
        Log.d("dongtaiFragment", "onTabUnselected() called with: " + "position = [" + position + "]");
    }

    @Override
    public void onTabReselected(int position) {

    }

}

其中模仿QQ消息来了之后在导航栏的某个图标的左上角显示相应的消息数目。

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_25066049/article/details/84647988

智能推荐

oracle给表转表空间,oracle批改表空间(转)_ftggggc的博客-程序员宅基地

当前位置:我的异常网» 数据库»oracle批改表空间(转)oracle批改表空间(转)www.myexceptions.net网友分享于:2013-07-04浏览:4次oracle修改表空间(转)简单介绍在 Oracle 10g 以前的版本,更改表空间名字是几乎不可能的事情,除非删除,重新创建,大费周章。Oracle 10g 新添加了一项更改表空间名字的功能,使得更改表空间名字瞬间即...

FAQ(Run with --stacktrace option to get the stack trace. Run with --info pr --debug ...)_run with info_大于弱智的博客-程序员宅基地

1、android studio编译错误有时会遇到 Run with --stacktrace option to get the stack trace. Run with --info pr --debug ... 或者:Run with --debug option to get more log output. Run with --scan to get full ins...

TIS教程03-导出_周先森爱吃素的博客-程序员宅基地

本文简单介绍如何通过TorchScript将Python环境的PyTorch模型导出为C++部署环境的模型。

mysql where 条件中的字段有NULL值时的sql语句写法_idjl的博客-程序员宅基地

比如你有一个sql语句联表出来之后是这样的id           name            phone                  status1            张三            13212341234         12            李四            13312341234         03            王五  ...

MOSFET驱动器汇总 : 单个N-CHANNEL,半桥,全桥,3项桥_mos全桥驱动和半桥驱动_卓晴的博客-程序员宅基地

&nbsp;▌01 单N-沟道驱动不同MOS驱动芯片工作电压与驱动电流:型号工作电压输出峰值电流TC442618V1.5ATC443130V1.5ATC442118V9ATC445118V12AMD12114.5 ~ 13V2ALT1910&gt;6V高端MOS驱动器1. TC4426(7)(8)数据手册: TC4427▲ 功能描述2.TC4421(2)TC4421数据手册 :输出电流峰值:9A工作电压

MySql下视图的创建_涂作权的博客的博客-程序员宅基地

(1).第一类:create view v as select * from table;(2).第二类:create view v as select id,name,age from table;(3).第三类:create view v[vid,vname,vage] as select id,name,age from table;如果涉及到数据量过大,业务逻辑需要跨表

随便推点

NMAP_披萨好吃的博客-程序员宅基地

我们打开kali和Metasploitable2,查找kali的IP地址,IP域中Metasploitable2的IP利用nmap -u 靶机IP 扫描靶机端口扫描系统类型,sudo su获得管理员权限,nmap -O 靶机IP红色箭头指的是靶机系统类型获取Metasploitable2上dvwa上的账号密码利用http-auth-finder来查看站点上的登录授权界面输入命令nmap -p80 --script http-auth-finder 靶机IP可以看到有dv..

《东周列国志》第九十五回 说四国乐毅灭齐 驱火牛田单破燕_依吾左袒_夏商周的博客-程序员宅基地

话说燕昭王自即位之后,日夜以报齐雪耻为事,吊死问孤,与士卒同甘苦,尊礼贤士,四方豪杰,归者如市。有赵人乐毅,乃乐羊之孙,自幼好讲兵法。当初乐羊封于灵寿,子孙遂家焉。赵主父沙邱之乱,乐毅挈家去灵寿,奔大梁,事魏昭王,不甚信用;闻燕王筑黄金台,招致天下贤士,欲往投之,乃谋出使于燕,见燕昭王。说以兵法,燕王知其贤,待以客礼,乐毅谦让不敢当,燕王曰:“先生生于赵,仕于魏,在燕固当为客。”乐毅曰:“臣之仕魏,以避乱也,大王若不弃微末,请委质为燕臣。”燕王大喜,即拜毅为亚卿,位于剧辛诸人之上,乐毅悉召其宗族居燕,为燕人

强大的杀伤力武器--TX2嵌入式开发板_喜欢爱喝矿泉水的男孩的博客-程序员宅基地

Tegra X2:Jetson TX2 延续了该系列体积小巧、高度集成的特性,大小仅相当于一张信用卡。 与前一代Jetson TX1相比,TX2能提供两倍的功效。GPU、CPU都进行了升级,其中GPU变成了Pascal 架构(16 nm工艺)。 这意味着Jetson 系列进入了 Pascal 架构时代。内存、存储都增加了一倍,提供了 8G 内存、32G 固态存储器。 支持802.11ac...

swfupload 无法加载_SwfUpload在IE10上不出现上传按钮的解决方法_黄秋古的博客-程序员宅基地

在系统测试过程中,发现使用了SwfUpload实现的无刷新上传功能,在IE10上竟然无法使用了,难道SwfUpload不支持吗?还是需要换一种实现方式呢?最后通过了解SwfUplad.JS文件发现,我们是可以修改的,让其支持IE10,具体解决方案如下:打开SwfUpload.js,在js文件中找到// Private: getFlashHTML generates the object tag n...

mysql教程show_MYSQL教程:MySQLShow命令_黄一孟的博客-程序员宅基地

show tables或show tables from database_name; 解释:显示当前数据库中所有表的名称 show databases; 解释:显示mysql中所有数据库的名称 show processlist; 解释:显示系统中正在运行的所有进程,也就是当前正在执行的查询。大多数用户可以查看 他们自己的show tables或show tables from database_...

activiti笔记_for key 'act_hi_varinst.primary_golden_lion的博客-程序员宅基地

1、对流程设计器的使用说明打开菜单Windows->Preferences->Activiti->Save下流程流程图片的生成方式:虽然流程引擎在单独部署bpmn文件时会自动生成图片,但在实际开发过程中,自动生成的图片会导致和BPMN中的坐标有出入,在实际项目中展示流程当前位置图会有问题。所在完成以上配置后,会由我们自己来管理流程图片。在发布流程时把流程规则

推荐文章

热门文章

相关标签