Commit 42d3d4af by 段启岩

重写底部导航栏组件,替代Android支持库自带的导航栏

parent 8df7d04a
...@@ -2,15 +2,11 @@ package cn.yunliyunwai.beyondclouds; ...@@ -2,15 +2,11 @@ package cn.yunliyunwai.beyondclouds;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MenuItem;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction; import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
...@@ -25,9 +21,10 @@ import cn.yunliyunwai.beyondclouds.ui.ProjectFragment; ...@@ -25,9 +21,10 @@ import cn.yunliyunwai.beyondclouds.ui.ProjectFragment;
import cn.yunliyunwai.beyondclouds.ui.QAFragment; import cn.yunliyunwai.beyondclouds.ui.QAFragment;
import cn.yunliyunwai.beyondclouds.ui.listener.OnNavigationReselectedListener; import cn.yunliyunwai.beyondclouds.ui.listener.OnNavigationReselectedListener;
import cn.yunliyunwai.beyondclouds.util.StatusBarUtils; import cn.yunliyunwai.beyondclouds.util.StatusBarUtils;
import cn.yunliyunwai.beyondclouds.view.BeyondBottomNavigationView;
import cn.yunliyunwai.beyondclouds.viewmodel.MainActivityViewModel; import cn.yunliyunwai.beyondclouds.viewmodel.MainActivityViewModel;
public class MainActivity extends BaseActivity<MainActivityViewModel, ActivityMainBinding> implements BottomNavigationView.OnNavigationItemSelectedListener, BottomNavigationView.OnNavigationItemReselectedListener { public class MainActivity extends BaseActivity<MainActivityViewModel, ActivityMainBinding> implements BeyondBottomNavigationView.OnNavigationItemReselectedListener, BeyondBottomNavigationView.OnNavigationItemSelectedListener {
private static final String MAIN_NAV_FRAGMENT_TAG_PREFIX = "main_nav_fragment:"; private static final String MAIN_NAV_FRAGMENT_TAG_PREFIX = "main_nav_fragment:";
private static final String TAG = MainActivity.class.getCanonicalName(); private static final String TAG = MainActivity.class.getCanonicalName();
...@@ -61,7 +58,8 @@ public class MainActivity extends BaseActivity<MainActivityViewModel, ActivityMa ...@@ -61,7 +58,8 @@ public class MainActivity extends BaseActivity<MainActivityViewModel, ActivityMa
private void initBottomNavigation(Bundle savedInstanceState) { private void initBottomNavigation(Bundle savedInstanceState) {
binding.bottomNavigationView.setOnNavigationItemSelectedListener(this); binding.bottomNavigationView.setOnNavigationItemSelectedListener(this);
binding.bottomNavigationView.setOnNavigationItemReselectedListener(this); binding.bottomNavigationView.setOnNavigationItemReselectedListener(this);
binding.bottomNavigationView.setItemIconTintList(null); // binding.bottomNavigationView.setItemIconTintList(null);
// binding.bottomNavigationView.setItemHorizontalTranslationEnabled(false);
fragments = new ArrayList<>(5); fragments = new ArrayList<>(5);
fragments.add(new HomeFragment()); fragments.add(new HomeFragment());
...@@ -87,49 +85,6 @@ public class MainActivity extends BaseActivity<MainActivityViewModel, ActivityMa ...@@ -87,49 +85,6 @@ public class MainActivity extends BaseActivity<MainActivityViewModel, ActivityMa
} }
} }
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.home_fragment:
switchFragment(0);
break;
case R.id.project_fragment:
switchFragment(1);
break;
case R.id.dynamic_fragment:
switchFragment(2);
break;
case R.id.qa_fragment:
switchFragment(3);
break;
case R.id.my_fragment:
switchFragment(4);
break;
}
return true;
}
@Override
public void onNavigationItemReselected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.home_fragment:
dispatchReSelectEvent(0);
break;
case R.id.project_fragment:
dispatchReSelectEvent(1);
break;
case R.id.dynamic_fragment:
dispatchReSelectEvent(2);
break;
case R.id.qa_fragment:
dispatchReSelectEvent(3);
break;
case R.id.my_fragment:
dispatchReSelectEvent(4);
break;
}
}
private void dispatchReSelectEvent(int index) { private void dispatchReSelectEvent(int index) {
Fragment fragment = fragments.get(index); Fragment fragment = fragments.get(index);
if (fragment instanceof OnNavigationReselectedListener) { if (fragment instanceof OnNavigationReselectedListener) {
...@@ -154,4 +109,14 @@ public class MainActivity extends BaseActivity<MainActivityViewModel, ActivityMa ...@@ -154,4 +109,14 @@ public class MainActivity extends BaseActivity<MainActivityViewModel, ActivityMa
transaction.commit(); transaction.commit();
binding.getViewModel().switchFrame(index); binding.getViewModel().switchFrame(index);
} }
@Override
public void onNavigationItemReselected(int index) {
dispatchReSelectEvent(index);
}
@Override
public void onNavigationItemSelected(int index) {
switchFragment(index);
}
} }
package cn.yunliyunwai.beyondclouds.view;
import android.content.Context;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import java.util.ArrayList;
import java.util.List;
import cn.yunliyunwai.beyondclouds.databinding.BeyondBottomNavigationViewBinding;
public class BeyondBottomNavigationView extends FrameLayout {
public interface OnNavigationItemReselectedListener {
void onNavigationItemReselected(int index);
}
public interface OnNavigationItemSelectedListener {
void onNavigationItemSelected(int index);
}
private static class SavedState extends BaseSavedState {
private int currentIndex;
public SavedState(Parcel source) {
super(source);
currentIndex = source.readInt();
}
public int getCurrentIndex() {
return currentIndex;
}
public void setCurrentIndex(int currentIndex) {
this.currentIndex = currentIndex;
}
@RequiresApi(api = Build.VERSION_CODES.N)
public SavedState(Parcel source, ClassLoader loader) {
super(source, loader);
}
public SavedState(Parcelable superState) {
super(superState);
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeValue(currentIndex);
}
public static final Parcelable.Creator<SavedState> CREATOR
= new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
private BeyondBottomNavigationViewBinding binding;
private int previousSelectedIndex = 0;
private List<View> mNavItems;
private OnNavigationItemReselectedListener mOnNavigationItemReselectedListener;
private OnNavigationItemSelectedListener mOnNavigationItemSelectedListener;
public BeyondBottomNavigationView(@NonNull Context context) {
super(context);
initView(context);
}
public BeyondBottomNavigationView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initAttrs(context, attrs);
initView(context);
}
public BeyondBottomNavigationView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttrs(context, attrs);
initView(context);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public BeyondBottomNavigationView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initAttrs(context, attrs);
initView(context);
}
private void initAttrs(Context context, AttributeSet attrs) {
}
private void initView(Context context) {
binding = BeyondBottomNavigationViewBinding.inflate(LayoutInflater.from(context), this, true);
initDefaultListeners();
bindEvent();
}
private void initDefaultListeners() {
mOnNavigationItemReselectedListener = new OnNavigationItemReselectedListener() {
@Override
public void onNavigationItemReselected(int index) {
}
};
mOnNavigationItemSelectedListener = new OnNavigationItemSelectedListener() {
@Override
public void onNavigationItemSelected(int index) {
}
};
}
private void bindEvent() {
mNavItems = new ArrayList<>(binding.bottomNavRoot.getChildCount());
int navCount = 0;
for (int i = 0; i < binding.bottomNavRoot.getChildCount(); i++) {
View view = binding.bottomNavRoot.getChildAt(i);
if (view instanceof FrameLayout) {
mNavItems.add(view);
view.setTag(navCount);
if (navCount == 0) {
// 设置第一个为默认选中
view.setSelected(true);
previousSelectedIndex = 0;
}
navCount++;
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String tag = view.getTag().toString();
int clickedIndex = Integer.valueOf(tag);
// 触发重新点击事件
if (clickedIndex == previousSelectedIndex) {
mOnNavigationItemReselectedListener.onNavigationItemReselected(clickedIndex);
} else {
// 取消先前导航的选中状态,设置当前导航的选中状态触发其点击事件
mNavItems.get(previousSelectedIndex).setSelected(false);
mNavItems.get(clickedIndex).setSelected(true);
mOnNavigationItemSelectedListener.onNavigationItemSelected(clickedIndex);
previousSelectedIndex = clickedIndex;
}
}
});
}
}
}
public void setOnNavigationItemSelectedListener(OnNavigationItemSelectedListener onNavigationItemSelectedListener) {
this.mOnNavigationItemSelectedListener = onNavigationItemSelectedListener;
}
public void setOnNavigationItemReselectedListener(OnNavigationItemReselectedListener onNavigationItemReselectedListener) {
this.mOnNavigationItemReselectedListener = onNavigationItemReselectedListener;
}
public void setCurrentNavIndex(int index) {
if (null != mNavItems && index < mNavItems.size()) {
mNavItems.get(previousSelectedIndex).setSelected(false);
mNavItems.get(index).setSelected(true);
previousSelectedIndex = index;
}
}
@Nullable
@Override
protected Parcelable onSaveInstanceState() {
SavedState savedState = new SavedState(super.onSaveInstanceState());
savedState.setCurrentIndex(previousSelectedIndex);
return savedState;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (! (state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
}
SavedState savedState = (SavedState) state;
super.onRestoreInstanceState(savedState.getSuperState());
setCurrentNavIndex(savedState.getCurrentIndex());
}
}
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/colorPrimary" android:state_selected="true"/> <item android:color="#000000" android:state_selected="true"/>
<item android:color="#999999"/> <item android:color="#999999"/>
</selector> </selector>
\ No newline at end of file
...@@ -22,10 +22,10 @@ ...@@ -22,10 +22,10 @@
app:layout_constraintBottom_toTopOf="@id/bottom_navigation_view" app:layout_constraintBottom_toTopOf="@id/bottom_navigation_view"
app:layout_constraintEnd_toEndOf="parent"/> app:layout_constraintEnd_toEndOf="parent"/>
<com.google.android.material.bottomnavigation.BottomNavigationView <cn.yunliyunwai.beyondclouds.view.BeyondBottomNavigationView
android:id="@+id/bottom_navigation_view" android:id="@+id/bottom_navigation_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="50dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:itemBackground="@null" app:itemBackground="@null"
app:itemHorizontalTranslationEnabled="false" app:itemHorizontalTranslationEnabled="false"
......
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/bottom_nav_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<View
android:id="@+id/line_top"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/colorSplitLine" />
<FrameLayout
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginBottom="2dp"
app:layout_constraintEnd_toStartOf="@id/nav_project"
app:layout_constraintHorizontal_chainStyle="spread"
android:id="@+id/nav_home"
android:layout_width="0dp"
android:layout_height="40dp">
<ImageView
android:layout_gravity="top|center_horizontal"
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/ic_home" />
<TextView
android:text="首页"
android:textSize="10dp"
android:textColor="@color/color_bottom_nav_text"
android:layout_gravity="bottom|center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
<FrameLayout
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/nav_home"
app:layout_constraintEnd_toStartOf="@id/nav_dynamic"
android:layout_marginBottom="2dp"
android:id="@+id/nav_project"
android:layout_width="0dp"
android:layout_height="40dp">
<ImageView
android:layout_gravity="top|center_horizontal"
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/ic_project" />
<TextView
android:text="项目"
android:textSize="10dp"
android:textColor="@color/color_bottom_nav_text"
android:layout_gravity="bottom|center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
<FrameLayout
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/nav_project"
app:layout_constraintEnd_toStartOf="@id/nav_qa"
android:layout_marginBottom="2dp"
android:id="@+id/nav_dynamic"
android:layout_width="0dp"
android:layout_height="40dp">
<ImageView
android:layout_gravity="top|center_horizontal"
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/ic_dynamic" />
<TextView
android:text="动态"
android:textSize="10dp"
android:textColor="@color/color_bottom_nav_text"
android:layout_gravity="bottom|center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
<FrameLayout
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/nav_dynamic"
app:layout_constraintEnd_toStartOf="@id/nav_my"
android:layout_marginBottom="2dp"
android:id="@+id/nav_qa"
android:layout_width="0dp"
android:layout_height="40dp">
<ImageView
android:layout_gravity="top|center_horizontal"
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/ic_qa" />
<TextView
android:text="问答"
android:textSize="10dp"
android:textColor="@color/color_bottom_nav_text"
android:layout_gravity="bottom|center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
<FrameLayout
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/nav_qa"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginBottom="2dp"
android:id="@+id/nav_my"
android:layout_width="0dp"
android:layout_height="40dp">
<ImageView
android:layout_gravity="top|center_horizontal"
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/ic_my" />
<TextView
android:text="我的"
android:textSize="10dp"
android:textColor="@color/color_bottom_nav_text"
android:layout_gravity="bottom|center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
...@@ -17,4 +17,5 @@ ...@@ -17,4 +17,5 @@
<color name="colorPopupMenuItem">#374246</color> <color name="colorPopupMenuItem">#374246</color>
<color name="colorIconTouched">#E7E5E5</color> <color name="colorIconTouched">#E7E5E5</color>
<color name="colorIcon">#00000000</color> <color name="colorIcon">#00000000</color>
<color name="colorSplitLine">#efefef</color>
</resources> </resources>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment