效果图
自定义属性
属性名 | 说明 | 默认值 |
---|---|---|
mm_tabHolderHeight | tab所在layout高度,必填 | 48dp |
mm_tabHolderColor | tablayout背景色 | 0xffffffff |
mm_underLineHeight | tablayout底部线条 | 0.6dp |
mm_underLineColor | tablayout底部线条颜色 | 0xffe0e0e0 |
mm_tabTitleDefaultColor | tabtitle默认颜色 | 0xff252525 |
mm_tabTitletSelectedColor | tabtitle选中颜色 | 0xff5da6f0 |
mm_tabTitleDefaultSize | tab默认字体大小 | 14dp |
mm_tabTitleSelectedSize | tab选中字体大小 | 14dp |
mm_tabIconDefault | tab未选中时icon | R.mipmap.tab_icon_default |
mm_tabIconSelected | tab选中时icon | R.mipmap.tab_icon_selected |
mm_tabIconLeftmargin | icon左边距 | 6dp |
mm_dividerWidth | tab 间隔线宽度 | 0.6dp |
mm_dividerTopmargin | tab 间隔线上边距 | 8dp |
mm_dividerBottommargin | tab 间隔线下边距 | 8dp |
mm_dividerColor | tab 间隔线颜色 | 0xffe0e0e0 |
mm_maskColor | 阴影颜色 | 0x40000000 |
mm_menuAnimateIn | menu进入动画 | R.anim.scale_in |
mm_menuAnimateOut | menu退出动画 | R.anim.scale_out |
使用
注意:
menu_layout和content_view的父控件使用FrameLayout或RelativeLayout,content_view设置topmargin为menu_layout的高度。
<FrameLayout 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"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="50dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="多选菜单"
android:textSize="20sp" />
</LinearLayout>
<com.beiing.library.MultipleMenu
android:id="@+id/multiple_menu"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:mm_tabHolderHeight="50dp"
app:mm_underLineHeight="2dp"
app:mm_underLineColor="#FF09A63B"
app:mm_tabTitleDefaultColor="#FF09A63B"
app:mm_tabTitletSelectedColor="#dc0f57"
app:mm_tabTitleDefaultSize="15sp"
app:mm_tabTitleSelectedSize="16sp"
app:mm_tabIconDefault="@mipmap/ic_default"
app:mm_tabIconSelected="@mipmap/ic_selected"
app:mm_tabIconLeftmargin="10dp"
app:mm_dividerWidth="1dp"
app:mm_dividerTopmargin="10dp"
app:mm_dividerBottommargin="10dp"
app:mm_dividerColor="#882DB91B"
app:mm_maskColor="#889a9ae6"
app:mm_menuAnimateIn="@anim/scale_in"
app:mm_menuAnimateOut="@anim/scale_out">
</com.beiing.library.MultipleMenu>
</FrameLayout>
代码:
private List<MultipleMenu.MenuPage> initMenuPages(){
ListView timeMenu = new ListView(this);
timeMenu.setBackgroundColor(Color.WHITE);
ArrayAdapter<String> timeAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, times);
timeMenu.setAdapter(timeAdapter);
ListView kindMenu = new ListView(this);
kindMenu.setBackgroundColor(Color.WHITE);
ArrayAdapter<String> kindAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, kinds);
kindMenu.setAdapter(kindAdapter);
ListView priceMenu = new ListView(this);
priceMenu.setBackgroundColor(Color.WHITE);
ArrayAdapter<String> priceAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, prices);
priceMenu.setAdapter(priceAdapter);
List<MultipleMenu.MenuPage> menuPages = new ArrayList<>(3);
menuPages.add(new MultipleMenu.MenuPage("时间", timeMenu));
menuPages.add(new MultipleMenu.MenuPage("户型", kindMenu));
menuPages.add(new MultipleMenu.MenuPage("价格", priceMenu));
return menuPages;
}
multipleMenu.setMultipleMenu(initMenuPages());
其他方法
closeMenu();
: 关闭当前打开菜单
setTabTitle(String text)
:设置当前打开菜单tabtitle
setTbaTitle(int position, String text)
:设置指定位置tabtitle
实现
- 继承LinearLayout,竖直排列。
- 添加顶部tab布局(是一个横向的LinearLayout)tabHolderView。
- 添加menu布局(一个FrameLayout)menuHolderView。
初始化控件的方法:
private void initView(Context context) {
//初始化view
tabHolderView = new LinearLayout(context);
tabHolderView.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, config.tabHolderHeight));
tabHolderView.setOrientation(HORIZONTAL);
tabHolderView.setGravity(Gravity.CENTER);
tabHolderView.setBackgroundColor(config.tabHolderColor);
View underLineView = new View(context);
underLineView.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, config.underLineHeight));
underLineView.setBackgroundColor(config.underLineColor);
menuHolderView = new FrameLayout(context);
menuHolderView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
//添加view
addView(tabHolderView);
addView(underLineView);
addView(menuHolderView);
maskView = new View(context);
maskView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
maskView.setBackgroundColor(config.maskColor);
}
当调用setMultipleMenu方法时,开始初始化各个tab和menu。
public void setMultipleMenu(List<MenuPage> menuPages){
if(menuPages.isEmpty()) return;
this.menuPages = menuPages;
tabList = new ArrayList<>(menuPages.size());
maskView.setOnClickListener(this);
menuHolderView.addView(maskView);
LayoutInflater inflater = LayoutInflater.from(getContext());
for (int i = 0, size = menuPages.size(); i < size; i++) {
MenuPage mp = menuPages.get(i);
addTab(mp.getMenuTitle(), inflater, i);
if(i != size - 1){
addDivider();
}
addMenuView(mp.getMenuView());
}
maskView.setVisibility(GONE);
menuHolderView.setVisibility(GONE);
}
addTab方法便是添加一个tab,R.layout.item_tab_layout由一个TextView和一个ImageView组成,为了减少findviewbyid操作,添加了一个ItemTabHolder类。每个itemholder记录当前tab的index。
private void addTab(String menuTitle, LayoutInflater inflater, int position) {
View itemTab = inflater.inflate(R.layout.item_tab_layout, tabHolderView, false);
ItemTabHolder itemTabHolder = new ItemTabHolder(itemTab, position);
itemTabHolder.setTitleText(menuTitle)
.setTitleTextSize(config.tabTitleDefaultSize)
.setTitleTextColor(config.tabTitleDefaultColor)
.setIconResource(config.tabIconDefault);
final LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lp.leftMargin = config.tabIconLeftmargin;
itemTabHolder.tvIcon.setLayoutParams(lp);
itemTab.setTag(itemTabHolder);
itemTab.setOnClickListener(this);
tabHolderView.addView(itemTab);
tabList.add(itemTab);
}
然后就是添加tab,添加divider,添加underline。在添加各个menuview和maskview…
最重要的操作是打开和关闭menu,menu打开关闭均以动画过渡,tabicon有旋转动画,当然,这些动画都可以自己设置。
/**
* 关闭菜单
*/
public void closeMenu() {
if(currentPosition != INVALID_POSITION){
//tab状态改变
View itemTab = tabList.get(currentPosition);
ItemTabHolder itemHolder = (ItemTabHolder) itemTab.getTag();
if (itemHolder != null) {
itemHolder.setTitleTextSize(config.tabTitleDefaultSize)
.setTitleTextColor(config.tabTitleDefaultColor)
.setIconResource(config.tabIconDefault);
//icon动画
itemHolder.tvIcon.startAnimation(iconOutAnimation);
}
//动画退出
final View menuView = menuHolderView.getChildAt(currentPosition + 1);
menuOutAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
menuView.setVisibility(GONE);
maskView.setVisibility(GONE);
menuHolderView.setVisibility(GONE);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
menuHolderView.startAnimation(menuOutAnimation);
currentPosition = INVALID_POSITION;
}
}
/**
* 打开指定位置menu
* @param position
*/
private void openMenu(int position) {
View itemTab = tabList.get(position);
ItemTabHolder itemHolder = (ItemTabHolder) itemTab.getTag();
if (itemHolder != null) {
itemHolder.setTitleTextSize(config.tabTitleSelectedSize)
.setTitleTextColor(config.tabTitletSelectedColor)
.setIconResource(config.tabIconSelected);
//icon动画
itemHolder.tvIcon.startAnimation(iconInAnimation);
}
for (MenuPage page :
menuPages) {
page.getMenuView().setVisibility(GONE);
}
//动画进入
menuHolderView.setVisibility(VISIBLE);
maskView.setVisibility(VISIBLE);
menuHolderView.getChildAt(position + 1).setVisibility(VISIBLE);
menuHolderView.startAnimation(menuInAnimation);
currentPosition = position;
}
说明:
MenuPage是为了让tabtitle和menuView一一对应而写的一个类。
public static class MenuPage{
private String menuTitle;
private View menuView;
public MenuPage(String menuTitle, View menuView) {
this.menuTitle = menuTitle;
this.menuView = menuView;
}
public MenuPage() {
}
public String getMenuTitle() {
return menuTitle;
}
public void setMenuTitle(String menuTitle) {
this.menuTitle = menuTitle;
}
public View getMenuView() {
return menuView;
}
public void setMenuView(View menuView) {
this.menuView = menuView;
}
}
实现比较简单,就不做过多解释了。