前言
公司APP有需要要把底部导航栏做成中间大两边小的样式,其实这种样式挺多APP都有,但是在此之前我自己还没有写过这种样式的底部导航栏,因此自己自定义了一个控件用于制作这种样式的首页底部导航栏。文章中的代码亲测可用。
正文
TabItemView--自定义的单个tab控件:
/**
* @Description: 底部导航栏itemView
* @author: jesse_android
* @date: 2019/7/24
*/
public class TabItemView extends LinearLayout {
private static final String TAG = TabItemView.class.getSimpleName();
private ImageView imageView;
private TextView textView;
private boolean isSelect = false;
private Drawable selectedImgResId,unselectedImgResId;
private int selectedTextColor,unselectedTextColor;
private float tabItemWidth,tabItemHeight;
private float imgWidth,imgHeight;
private String tabName;
private int index = 0;
public TabItemView(Context context) {
super(context);
init(context,null,0);
}
public TabItemView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context,attrs,0);
}
public TabItemView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context,attrs,defStyleAttr);
}
private void init(Context context,AttributeSet attrs, int defStyleAttr){
imageView = new ImageView(context);
textView = new TextView(context);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TabItemView);
isSelect = ta.getBoolean(R.styleable.TabItemView_defaultSelected,false);
selectedImgResId = ta.getDrawable(R.styleable.TabItemView_selectedImgResId);
unselectedImgResId = ta.getDrawable(R.styleable.TabItemView_unselectedImgResId);
selectedTextColor = ta.getInt(R.styleable.TabItemView_selectedTextColor,Color.BLUE);
unselectedTextColor = ta.getInt(R.styleable.TabItemView_unselectedTextColor,Color.BLACK);
tabItemWidth = ta.getDimension(R.styleable.TabItemView_tabItemWidth,ScreenUtils.getScreenWidth()/5);
tabItemHeight = ta.getDimension(R.styleable.TabItemView_tabItemHeight,SizeUtils.dp2px(60));
imgWidth = ta.getDimension(R.styleable.TabItemView_imgWidth,ViewGroup.LayoutParams.WRAP_CONTENT);
imgHeight = ta.getDimension(R.styleable.TabItemView_imgHeight,ViewGroup.LayoutParams.WRAP_CONTENT);
tabName = ta.getString(R.styleable.TabItemView_tabName);
float textSize = ta.getDimension(R.styleable.TabItemView_textSize,9);
index = ta.getInteger(R.styleable.TabItemView_tabIndex,-1);
ta.recycle(); //注意回收
//配置ImageView
imageView.setImageDrawable(isSelect?selectedImgResId:unselectedImgResId);
if(imgWidth > 0 && imgHeight > 0){
LinearLayout.LayoutParams imgParams = new LayoutParams((int) imgWidth,(int) imgHeight);
imageView.setLayoutParams(imgParams);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
}
addView(imageView);
//配置TextView
textView.setText(tabName);
textView.setTextSize(textSize);
textView.setTextColor(isSelect?selectedTextColor:unselectedTextColor);
LayoutParams textParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
textParams.setMargins(0,SizeUtils.dp2px(2),0,0);
textView.setLayoutParams(textParams);
addView(textView);
}
/**
* 根据select状态改变UI
*/
public void resetSelectState(){
imageView.setImageDrawable(isSelect?selectedImgResId:unselectedImgResId);
textView.setTextColor(isSelect?selectedTextColor:unselectedTextColor);
}
public boolean isSelect() {
return isSelect;
}
public void setSelect(boolean select) {
if(isSelect == select){
return;
}
isSelect = select;
resetSelectState();
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
2.自定义属性:
<declare-styleable name="TabItemView">
<attr name="selectedImgResId" format="reference" />
<attr name="unselectedImgResId" format="reference" />
<attr name="selectedTextColor" format="color|reference" />
<attr name="unselectedTextColor" format="color|reference" />
<attr name="tabItemWidth" format="dimension|reference" />
<attr name="tabItemHeight" format="dimension|reference" />
<attr name="imgWidth" format="dimension|reference" />
<attr name="imgHeight" format="dimension|reference" />
<attr name="textSize" format="dimension|reference" />
<attr name="defaultSelected" format="boolean" />
<attr name="tabName" format="string" />
<attr name="tabIndex" format="integer" />
</declare-styleable>
3.布局文件写法:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:clipChildren="false"
android:orientation="vertical">
<FrameLayout
android:id="@+id/fl_content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<View
android:layout_width="match_parent"
android:layout_height="0.4dp"
android:background="#99cccccc"
android:visibility="visible" />
<!-- 底部导航栏 -->
<LinearLayout
android:id="@+id/ll_bottom"
android:layout_width="match_parent"
android:layout_height="55dp"
android:layout_alignParentBottom="true"
android:background="@color/white"
android:orientation="horizontal">
<com.example.zhouqiong.richeditotandroid.view.TabItemView
android:id="@+id/sync_teach_tab"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical"
app:defaultSelected="true"
app:imgHeight="24dp"
app:imgWidth="24dp"
app:selectedImgResId="@drawable/ic_sync_selected"
app:selectedTextColor="@color/color_selected_tags"
app:tabIndex="0"
app:tabName="同步教学"
app:unselectedImgResId="@drawable/ic_sync_unselected"
app:unselectedTextColor="@color/color_maintext_title"
android:visibility="gone"
/>
<com.example.zhouqiong.richeditotandroid.view.TabItemView
android:id="@+id/famous_teacher_tab"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical"
app:imgHeight="24dp"
app:imgWidth="24dp"
app:selectedImgResId="@drawable/ic_famous_teacher_selected"
app:selectedTextColor="@color/color_selected_tags"
app:tabIndex="1"
app:tabName="名师精讲"
app:unselectedImgResId="@drawable/ic_famous_teacher_unselected"
app:unselectedTextColor="@color/color_maintext_title"
android:visibility="gone"
/>
<com.example.zhouqiong.richeditotandroid.view.TabItemView
android:id="@+id/create_courseware_tab"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:layout_weight="1"
android:background="@color/transparent"
android:gravity="center"
android:orientation="vertical"
app:imgHeight="24dp"
app:imgWidth="24dp"
app:selectedImgResId="@drawable/ic_courseware_selected"
app:selectedTextColor="@color/color_maintext_title"
app:tabIndex="2"
app:tabName="做课件"
app:unselectedImgResId="@drawable/ic_courseware_unselected"
app:unselectedTextColor="@color/color_maintext_title"
android:visibility="gone"
/>
<com.example.zhouqiong.richeditotandroid.view.TabItemView
android:id="@+id/activity_tab"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical"
app:imgHeight="24dp"
app:imgWidth="24dp"
app:selectedImgResId="@drawable/ic_activity_selected"
app:selectedTextColor="@color/color_selected_tags"
app:tabIndex="3"
app:tabName="活动"
app:unselectedImgResId="@drawable/ic_activity_unselected"
app:unselectedTextColor="@color/color_maintext_title"
android:visibility="gone"
/>
<com.example.zhouqiong.richeditotandroid.view.TabItemView
android:id="@+id/live_tab"
android:layout_width="0dp"
android:layout_height="69dp"
android:layout_gravity="bottom"
android:layout_weight="1"
android:background="@color/transparent"
android:gravity="center"
android:orientation="vertical"
app:imgHeight="39dp"
app:imgWidth="39dp"
app:selectedImgResId="@drawable/ic_live_selected"
app:selectedTextColor="@color/color_selected_tags"
app:tabIndex="5"
app:tabName="直播吧"
app:unselectedImgResId="@drawable/ic_live_selected"
app:unselectedTextColor="@color/color_selected_tags"
android:visibility="gone"
/>
<com.example.zhouqiong.richeditotandroid.view.TabItemView
android:id="@+id/sspeech_tab"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical"
app:imgHeight="24dp"
app:imgWidth="24dp"
app:selectedImgResId="@drawable/ic_sspeech_selected"
app:selectedTextColor="@color/color_selected_tags"
app:tabIndex="6"
app:tabName="开课"
app:unselectedImgResId="@drawable/ic_sspeech_unselected"
app:unselectedTextColor="@color/color_maintext_title"
app:defaultSelected="true"
/>
<com.example.zhouqiong.richeditotandroid.view.TabItemView
android:id="@+id/teach_tab"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical"
app:imgHeight="24dp"
app:imgWidth="24dp"
app:selectedImgResId="@drawable/ic_teach_tab_selected"
app:selectedTextColor="@color/color_selected_tags"
app:tabIndex="7"
app:tabName="教研"
app:unselectedImgResId="@drawable/ic_teach_tab_unselected"
app:unselectedTextColor="@color/color_maintext_title"
/>
<com.example.zhouqiong.richeditotandroid.view.TabItemView
android:id="@+id/exam_tab"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical"
app:imgHeight="24dp"
app:imgWidth="24dp"
app:selectedImgResId="@drawable/ic_exam_tab_selected"
app:selectedTextColor="@color/color_selected_tags"
app:tabIndex="8"
app:tabName="测评"
app:unselectedImgResId="@drawable/ic_exam_tab_unselected"
app:unselectedTextColor="@color/color_maintext_title"
/>
<com.example.zhouqiong.richeditotandroid.view.TabItemView
android:id="@+id/mine_tab"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical"
app:imgHeight="24dp"
app:imgWidth="24dp"
app:selectedImgResId="@drawable/ic_mine_selected"
app:selectedTextColor="@color/color_selected_tags"
app:tabIndex="4"
app:tabName="我的"
app:unselectedImgResId="@drawable/ic_mine_unselected"
app:unselectedTextColor="@color/color_maintext_title" />
</LinearLayout>
</LinearLayout>
注意:
1.android:clipChildren="false" 这个属性是重点,为了防止底部导航栏遮挡住我们突出的item,如果要实现中间突出的效果必须要加。
2.中间突出的那一个item参考布局文件中的live_tab去设置。
4.java类中用法:
public class HomePageActivity extends SimpleActivity {
private static final String TAG = HomePageActivity.class.getSimpleName();
private String mIntentEvent = null;
@BindView(R.id.sync_teach_tab)
TabItemView sync_teach_tab;
@BindView(R.id.famous_teacher_tab)
TabItemView famous_teacher_tab;
@BindView(R.id.create_courseware_tab)
TabItemView create_courseware_tab;
@BindView(R.id.activity_tab)
TabItemView activity_tab;
@BindView(R.id.mine_tab)
TabItemView mine_tab;
@BindView(R.id.live_tab)
TabItemView live_tab;
@BindView(R.id.sspeech_tab)
TabItemView sspeech_tab;
@BindView(R.id.teach_tab)
TabItemView teach_tab;
@BindView(R.id.exam_tab)
TabItemView exam_tab;
private List<TabItemView> tabList;
private final int SYNC_TEACH_TAB_INDEX = 0;
private final int FAMOUS_TEACHER_TAB_INDEX = 1;
private final int CREATE_COURSEWARE_TAB_INDEX = 2;
private final int ACTIVITY_TAB_INDEX = 3;
private final int MINE_TAB_INDEX = 4;
private final int LIVE_TAB_INDEX = 5;
private final int START_SPEECH_INDEX = 6;
private final int TEACH_TAB_INDEX = 7;
private final int EXAM_TAB_INDEX = 8;
private int currentSelectIndex = START_SPEECH_INDEX;//默认选中项目序号
private FragmentManager fragmentManager;
//填充的fragments
private NewCoursewareFragment newCoursewareFragment;
private MeFragment meFragment;
private SyncTeachFragment syncTeachFragment;
private TopTeacherLectureFragment topTeacherLectureFragment;
private ActivitiesFragment activitiesFragment;
private LiveFragment liveFragment;
private StartSpeechFragment startSpeechFragment;
private TeachTabFragment teachTabFragment;
private ExamTabFragment examTabFragment;
private Fragment mCurrentFragment;
static {
SharedPreferencesUtil.setBooleanDate(Constant.SPKEY_SHOULD_VERSION_CHECKED, true);
}
@Override
protected int getLayout() {
return R.layout.activity_home_page;
}
@Override
protected void initEventAndData() {
//初始化变量
fragmentManager = getSupportFragmentManager();
tabList = new ArrayList<>();
tabList.add(sync_teach_tab);
tabList.add(famous_teacher_tab);
tabList.add(create_courseware_tab);
tabList.add(activity_tab);
tabList.add(mine_tab);
tabList.add(live_tab);
tabList.add(sspeech_tab);
tabList.add(teach_tab);
tabList.add(exam_tab);
//设置初始fragment
if (mIntentEvent != null && !mIntentEvent.isEmpty()) {
meFragment = new MeFragment();
fragmentManager.beginTransaction().replace(R.id.fl_content, meFragment).commit();
} else {
startSpeechFragment = new StartSpeechFragment();
fragmentManager.beginTransaction().replace(R.id.fl_content, startSpeechFragment).commit();
}
//设置监听
sync_teach_tab.setOnClickListener(onTabClickListener);
famous_teacher_tab.setOnClickListener(onTabClickListener);
create_courseware_tab.setOnClickListener(onTabClickListener);
activity_tab.setOnClickListener(onTabClickListener);
mine_tab.setOnClickListener(onTabClickListener);
live_tab.setOnClickListener(onTabClickListener);
sspeech_tab.setOnClickListener(onTabClickListener);
teach_tab.setOnClickListener(onTabClickListener);
exam_tab.setOnClickListener(onTabClickListener);
}
private boolean hasGotHeight;
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
try {
if (!hasGotHeight && hasFocus) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
DisplayCutout displayCutout = getWindow().getDecorView().getRootWindowInsets().getDisplayCutout();
SharedPreferencesUtil.setIntDate(Constant.SPKEY_NOTCH_HEIGHT, (displayCutout != null ? displayCutout.getSafeInsetTop() : 0));
LogUtil.d(TAG + " notchHeight = " + (displayCutout != null ? displayCutout.getSafeInsetTop() : 0));
}
hasGotHeight = true;
}
} catch (Exception e) {
e.printStackTrace();
LogUtil.e(TAG + " get notchHeight error : " + e.toString());
}
}
private View.OnClickListener onTabClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if (v instanceof TabItemView) {
if (currentSelectIndex == ((TabItemView) v).getIndex()) {
return;
}
currentSelectIndex = ((TabItemView) v).getIndex();
switch (((TabItemView) v).getIndex()) {
case SYNC_TEACH_TAB_INDEX:
sync_teach_tab.setSelect(!sync_teach_tab.isSelect());
//切换fragment
if (syncTeachFragment == null) {
syncTeachFragment = new SyncTeachFragment();
}
fragmentManager.beginTransaction().replace(R.id.fl_content, syncTeachFragment).commit();
mCurrentFragment = syncTeachFragment;
break;
case FAMOUS_TEACHER_TAB_INDEX:
famous_teacher_tab.setSelect(!famous_teacher_tab.isSelect());
//切换fragment
if (topTeacherLectureFragment == null) {
topTeacherLectureFragment = new TopTeacherLectureFragment();
}
fragmentManager.beginTransaction().replace(R.id.fl_content, topTeacherLectureFragment).commit();
mCurrentFragment = topTeacherLectureFragment;
// Toast.makeText(mContext, "尚未开放,敬请期待", Toast.LENGTH_SHORT).show();
break;
case CREATE_COURSEWARE_TAB_INDEX:
create_courseware_tab.setSelect(!create_courseware_tab.isSelect());
//切换fragment
if (newCoursewareFragment == null) {
newCoursewareFragment = new NewCoursewareFragment();
}
fragmentManager.beginTransaction().replace(R.id.fl_content, newCoursewareFragment).commit();
mCurrentFragment = newCoursewareFragment;
break;
case ACTIVITY_TAB_INDEX:
activity_tab.setSelect(!activity_tab.isSelect());
//切换fragment
// Toast.makeText(mContext, "尚未开放,敬请期待", Toast.LENGTH_SHORT).show();
if(activitiesFragment == null){
activitiesFragment = new ActivitiesFragment();
}
fragmentManager.beginTransaction().replace(R.id.fl_content, activitiesFragment).commit();
mCurrentFragment = activitiesFragment;
break;
case MINE_TAB_INDEX:
mine_tab.setSelect(!mine_tab.isSelect());
//切换fragment
if (meFragment == null) {
meFragment = new MeFragment();
}
fragmentManager.beginTransaction().replace(R.id.fl_content, meFragment).commit();
mCurrentFragment = meFragment;
break;
case LIVE_TAB_INDEX:
live_tab.setSelect(!live_tab.isSelect());
//切换fragment
if (liveFragment == null) {
liveFragment = new LiveFragment();
}
fragmentManager.beginTransaction().replace(R.id.fl_content, liveFragment).commit();
mCurrentFragment = liveFragment;
break;
case START_SPEECH_INDEX:
sspeech_tab.setSelect(!sspeech_tab.isSelect());
//切换fragment
if (startSpeechFragment == null) {
startSpeechFragment = new StartSpeechFragment();
}
fragmentManager.beginTransaction().replace(R.id.fl_content, startSpeechFragment).commit();
mCurrentFragment = startSpeechFragment;
break;
case TEACH_TAB_INDEX:
teach_tab.setSelect(!teach_tab.isSelect());
//切换fragment
if (teachTabFragment == null) {
teachTabFragment = new TeachTabFragment();
}
fragmentManager.beginTransaction().replace(R.id.fl_content, teachTabFragment).commit();
mCurrentFragment = teachTabFragment;
break;
case EXAM_TAB_INDEX:
exam_tab.setSelect(!exam_tab.isSelect());
//切换fragment
if (examTabFragment == null) {
examTabFragment = new ExamTabFragment();
}
fragmentManager.beginTransaction().replace(R.id.fl_content, examTabFragment).commit();
mCurrentFragment = examTabFragment;
break;
}
resetSelectState();
}
}
};
/**
* 除当前序号对应的tab和中间凸出的tab外,
* 其他tab都设置为未选中状态
*/
private void resetSelectState() {
for (int i = 0; i < tabList.size(); i++) {
if (i == currentSelectIndex /*|| i == START_SPEECH_INDEX*/) {
continue;
}
tabList.get(i).setSelect(false);
}
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
mIntentEvent = (String) Session.getSession().get(Constant.INTENT_EVENT);
if (mIntentEvent != null && !mIntentEvent.isEmpty()) {
if (mIntentEvent.equals(Constant.ACTIVITIES_FRAGMENT)) {
if(!live_tab.isSelect()){
live_tab.setSelect(!live_tab.isSelect());
if (startSpeechFragment == null) {
startSpeechFragment = new StartSpeechFragment();
}
fragmentManager.beginTransaction().replace(R.id.fl_content, startSpeechFragment).commit();
currentSelectIndex = LIVE_TAB_INDEX;
}
} else {
if (!mine_tab.isSelect()) {
mine_tab.setSelect(!mine_tab.isSelect());
if (meFragment == null) {
meFragment = new MeFragment();
}
fragmentManager.beginTransaction().replace(R.id.fl_content, meFragment).commit();
currentSelectIndex = MINE_TAB_INDEX;
}
}
} else {
sspeech_tab.setSelect(!sspeech_tab.isSelect());
if (startSpeechFragment == null) {
startSpeechFragment = new StartSpeechFragment();
}
fragmentManager.beginTransaction().replace(R.id.fl_content, startSpeechFragment).commit();
currentSelectIndex = START_SPEECH_INDEX;
}
resetSelectState();
}
private long lastMills,currentMills;
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(mCurrentFragment instanceof ActivitiesFragment){
((ActivitiesFragment)mCurrentFragment).onKeyDown(keyCode,event);
return true;
}
if(keyCode == KeyEvent.KEYCODE_BACK){
currentMills = System.currentTimeMillis();
if(lastMills > 0 && currentMills - lastMills <= 1500){
finish();
return true;
}else{
Toast.makeText(mContext, "再按一次退出应用", Toast.LENGTH_SHORT).show();
lastMills = currentMills;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
lastMills = 0;
}
},1500);
return true;
}
}
return super.onKeyDown(keyCode, event);
}
@Override
protected void onDestroy() {
super.onDestroy();
//退出APP 清除模板版本号
SharedPreferencesUtil.setStringDate(Constant.SPKEY_TEMPLATE_VERSION, "");
}
}
java类中包含了点击某个tab后将其他tab置灰,点击tab对fragment的切换等常规实现,可作为你移植的参考。
结语
以上就是全部内容了,如果有不懂的或者使用中遇到了问题欢迎在下方留言。
如果对你有帮助给我点个免费的赞和关注吧,这些都是我更博的动力啊,谢啦~