先看一下 BottomNavigationView的结构:
本来想录成gif呢 无奈最大只能上传5M 所以就不传了 所代码贴出来
menuView = (BottomNavigationMenuView) navView.getChildAt(0);
// BottomNavigationItemView
//BottomNavigationItemView 这才是一个子条目
Class<? extends BottomNavigationMenuView> aClass = menuView.getClass();
Field presenter = null;
Field menu = null;
try {
presenter = aClass.getDeclaredField("presenter");
menu = aClass.getDeclaredField("menu");
menu.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
presenter.setAccessible(true);
menu.setAccessible(true);
try {
myPresenter = (BottomNavigationPresenter) presenter.get(menuView);
myMenu = (MenuBuilder) menu.get(menuView);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
menuView.findViewById(R.id.navigation_home).setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
v.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_UP){
BottomNavigationItemView itemView = (BottomNavigationItemView) v; //向源码学习
@SuppressLint("RestrictedApi") MenuItem item = itemView.getItemData();
if (!myMenu.performItemAction(item, myPresenter, 0)) {
item.setChecked(true);
}
}
return true;
}
});
return true;
}
});
// menuView.findViewById(R.id.navigation_home).setBackground(null);
menuView.findViewById(R.id.navigation_home).setBackgroundResource(0);//去除水波纹的效果
menuView.findViewById(R.id.navigation_dashboard).setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
v.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_UP){
BottomNavigationItemView itemView = (BottomNavigationItemView) v;
@SuppressLint("RestrictedApi") MenuItem item = itemView.getItemData();
if (!myMenu.performItemAction(item, myPresenter, 0)) {
item.setChecked(true);
}
}
return true;
}
});
return true;
}
});
menuView.findViewById(R.id.navigation_dashboard).setBackgroundResource(0);
menuView.findViewById(R.id.navigation_notifications).setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
v.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_UP) {
BottomNavigationItemView itemView = (BottomNavigationItemView) v;
@SuppressLint("RestrictedApi") MenuItem item = itemView.getItemData();
if (!myMenu.performItemAction(item, myPresenter, 0)) {
item.setChecked(true);
}
}
return true;
}
});
return true;
}
});
menuView.findViewById(R.id.navigation_notifications).setBackgroundResource(0);
思路:
我们通过查看 BottomNavigationView的结构可以看出
它包了一层才是我们的 tab
所以 我们把 gitChild把这一层找出来
BottomNavigationView navView = findViewById(R.id.nav_view);
// closeAnimation(navView);
menuView = (BottomNavigationMenuView) navView.getChildAt(0);
找出之后
我们会发现 tab的 容器是一个 BottomNavigationItemView 我们去这个类的源码里面 没有到的 Click事件 (如标题我们的目录 是要把 长按事件处理成和点击事件一样所以我们要看一下 它的点击事件是如何写的)
但你发现 BottomNavigationItemView 里面根本没有找到处理点击事件的地方 。
我们去 BottomNavigationItemView的上层去找找看结果有发现
找到入口了但还有个问题 就是下面这两个变量
私有并没有提供获取方法 (所以只能通过反射获取了)
反射获取
设置三个Tab的长按事件这里只贴一个(其它的都一样)
onLongClick 返回true 是自己把事件消费掉不再上层传递,后台只又加上了 setOnTouchListener 是因为如果不处理的话 用户按下不松手的话长按事件直接响应了 我想要的效果是用户抬起手指后再做响应。