1. 要仿照的效果
Gif_20180715_150056.gif
2.效果分析
2.1 是一個組合布局 ,分成上下兩部分,上面部分為Tab,下面部分為菜單內容和陰影,所以繼承LinearLayout
2.2 默認菜單內容是看不到的,也就是說向上位移菜單內容的高度
2.3 點擊Tab 打開菜單(菜單內容向下位移菜單內容高度同時陰影的透明度從完全透明到完全不透明),同時Tab字體變色
2.4 已經打開的菜單內容,再次點擊同一個Tab關閉菜單內容和Tab顏色值變成默認顏色.菜單內容向上位移菜單內容高度,陰影的透明度從不透明變成透明
2.5 打開菜單內容情況下,點擊陰影關閉菜單.
2.6 打開菜單內容打開的情況下,點擊另一個Tab,菜單內容切換成另外一個菜單內容.
3.代碼實現(xiàn)
package com.zsj.listdatascreenview;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Color;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
/**
* @author 朱勝軍
* @date 2018/7/15
* 描述 菜單篩選
* <p>
* 更新者 $Author$
* 更新時間 $Date$
* 更新描述 TODO
*/
//是一個組合布局租幕,extends LinearLayout 兩層結構徽鼎,上的Tab,下面菜單內容和陰影
public class ListDataScreenView extends LinearLayout implements View.OnClickListener {
private static final String TAG = "ZsjTAG";
/**
* 陰影的顏色
*/
private int mShadowColor = Color.parseColor("#88888888");
private BaseMenuAdapter mAdapter;
private LinearLayout mTabContainer;
private FrameLayout mMenuContentContainer;
private int mMenuContentHeight;
/**
* 當前的點擊位置
*/
private int mCurrentPosition = -1;
private long ANIMATOR_DURATION = 350;
private View mShadowView;
/**
* 動畫在執(zhí)行
*/
private boolean mIsAnimatorRun = false;
private FrameLayout mMenuContainer;
public ListDataScreenView(Context context) {
this(context, null);
}
public ListDataScreenView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public ListDataScreenView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initLayout();
}
private void initLayout() {
//設置垂直布局
setOrientation(VERTICAL);
//組合布局可以分成兩種寫法
//1 inflate 一個 Lyaout布局
// LayoutInflater.from(getContext()).inflate()
//2 代碼實現(xiàn)
//上面的TabLayout 是一個線性布局俱饿,然后均分。
mTabContainer = new LinearLayout(getContext());
//給TabContainer設置大小
mTabContainer.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
//添加到自己中
addView(mTabContainer);
//下面剩下的內容是陰影和菜單內容
//用FrameLayout作為容器
mMenuContainer = new FrameLayout(getContext());
mMenuContainer.setVisibility(GONE);
//先添加一個陰影谋逻,用View設置背景即可
mShadowView = new View(getContext());
mShadowView.setBackgroundColor(mShadowColor);
mShadowView.setAlpha(0f);
// 添加到menuContainer中
mMenuContainer.addView(mShadowView);
mShadowView.setOnClickListener(this);
//添加菜單內容
mMenuContentContainer = new FrameLayout(getContext());
mMenuContentContainer.setBackgroundColor(Color.WHITE);
mMenuContainer.addView(mMenuContentContainer);
LinearLayout.LayoutParams menuContainerParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0);
menuContainerParams.weight = 1;
mMenuContainer.setLayoutParams(menuContainerParams);
//把才菜單陰影容器添加到自己身上塔插。
addView(mMenuContainer);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Log.e(TAG, "onMeasure ");
////菜單的高度應該的屏幕寬度的75%
int height = MeasureSpec.getSize(heightMeasureSpec);
if ((mMenuContentHeight == 0) && height > 0) {
mMenuContentHeight = (int) (height * 0.75);
ViewGroup.LayoutParams params = mMenuContentContainer.getLayoutParams();
params.height = mMenuContentHeight;
mMenuContentContainer.setLayoutParams(params);
//菜單內容默認收起來,向上位移 - mMenuContentHeight
mMenuContentContainer.setTranslationY(-mMenuContentHeight);
}
}
public void setAdapter(BaseMenuAdapter adapter) {
mAdapter = adapter;
int count = mAdapter.getCount();
for (int i = 0; i < count; i++) {
View tabView = mAdapter.getTabView(i, mTabContainer);
setTabClickListener(i, tabView);
mTabContainer.addView(tabView);
// TabLayout布局均分
LinearLayout.LayoutParams params = (LayoutParams) tabView.getLayoutParams();
params.weight = 1;
tabView.setLayoutParams(params);
View menuContentView = mAdapter.getMenuContentView(i, mMenuContentContainer);
//菜單內容疊在一起了
//一開始全部菜單內容全部隱藏
menuContentView.setVisibility(GONE);
mMenuContentContainer.addView(menuContentView);
}
//遇到的問題
//TabLayout布局均分
//菜單內容疊在一起了
//菜單的高度應該的屏幕寬度的75%
//菜單內容默認收起來
//點擊Tab打開菜單或者關閉菜單
//點擊陰影關閉菜單
//菜單打開,Tab的顏色值變化,丟給Adapter處理
//打開或者關閉菜單的動畫還在執(zhí)行就不處理東湖
//菜單已打開,點擊其他的TAB,切換而也不是關閉菜單
}
private void setTabClickListener(final int position, final View tabView) {
tabView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mCurrentPosition == -1) {
//沒有打開菜單,去打開菜單
openMenu(position, tabView);
} else {
//打開過菜單,去關閉菜單
if (position != mCurrentPosition) {
//菜單已打開,點擊其他的TAB,切換而也不是關閉菜單
//切換菜單內容
//隱藏上一個菜單內容
View preMenuContent = mMenuContentContainer.getChildAt(mCurrentPosition);
preMenuContent.setVisibility(GONE);
//把上一個Tab設置為默認顏色
View tabView = mTabContainer.getChildAt(mCurrentPosition);
mAdapter.closeMenu(tabView);
mCurrentPosition = position;
View currentMenuContent = mMenuContentContainer.getChildAt(mCurrentPosition);
currentMenuContent.setVisibility(VISIBLE);
//把當期Tab設置點擊顏色
View tabView2 = mTabContainer.getChildAt(mCurrentPosition);
mAdapter.openMenu(tabView2);
} else {
closeMenu();
}
}
}
});
}
private void closeMenu() {
mMenuContainer.setVisibility(GONE);
if (mIsAnimatorRun) {
return;
}
// 給菜單內容啟動移動動畫,同時給陰影啟動一個透明度動畫
//位移動畫
AnimatorSet animatorSet = new AnimatorSet();
ObjectAnimator translationAnimator = ObjectAnimator.ofFloat(mMenuContentContainer,
"translationY", 0, -mMenuContentHeight);
//透明度動畫
ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(mShadowView, "alpha", 1f, 0f);
animatorSet.playTogether(translationAnimator, alphaAnimator);
animatorSet.setDuration(ANIMATOR_DURATION);
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
mIsAnimatorRun = true;
View tabView = mTabContainer.getChildAt(mCurrentPosition);
mAdapter.closeMenu(tabView);
}
@Override
public void onAnimationEnd(Animator animation) {
mIsAnimatorRun = false;
//關閉菜單,隱藏菜單內容
View menuContentView = mMenuContentContainer.getChildAt(mCurrentPosition);
menuContentView.setVisibility(GONE);
mCurrentPosition = -1;
}
});
animatorSet.start();
}
/**
* 打開菜單
*
* @param position
* @param tabView
*/
private void openMenu(final int position, final View tabView) {
mMenuContainer.setVisibility(VISIBLE);
if (mIsAnimatorRun) {
return;
}
// 給菜單內容啟動移動動畫,同時給陰影啟動一個透明度動畫
//位移動畫
AnimatorSet animatorSet = new AnimatorSet();
ObjectAnimator translationAnimator = ObjectAnimator.ofFloat(mMenuContentContainer,
"translationY", -mMenuContentHeight, 0);
//透明度動畫
ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(mShadowView, "alpha", 0f, 1f);
animatorSet.playTogether(translationAnimator, alphaAnimator);
animatorSet.setDuration(ANIMATOR_DURATION);
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
mIsAnimatorRun = true;
mAdapter.openMenu(tabView);
mCurrentPosition = position;
//打開菜單顯示菜單內容
View menuContentView = mMenuContentContainer.getChildAt(position);
menuContentView.setVisibility(VISIBLE);
}
@Override
public void onAnimationEnd(Animator animation) {
mIsAnimatorRun = false;
}
});
animatorSet.start();
}
@Override
public void onClick(View v) {
closeMenu();
}
}
模仿效果
Gif_20180715_183059.gif