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消息来了之后在导航栏的某个图标的左上角显示相应的消息数目。