多条目选择下落动画-使用于条件筛选
1.先看效果图
多条目选择下落动画.gif2.分析
根部局是一个Linearlayout
其中包含:
第一个布局是一个 LinearLayout 用于包含TabView
第二个是一个FrameLayout,这个frameLayout中包含背景View,和内容view是FrameLayout
private void initLayout() {
//设置方向
setOrientation(VERTICAL);
mTabView = new LinearLayout(getContext());
mTabView.setOrientation(HORIZONTAL);
ViewGroup.LayoutParams mTabViewParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,mTabViewHeight);
mTabView.setLayoutParams(mTabViewParams);
addView(mTabView);
View mLineView = new View(getContext());
mLineView.setBackgroundColor(mLineViewColor);
mLineView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1));
addView(mLineView);
mMenuView = new FrameLayout(getContext());
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0);
layoutParams.weight = 1;
mMenuView.setLayoutParams(layoutParams);
addView(mMenuView);
mBottomView = new View(getContext());
mBottomView.setBackgroundColor(Color.parseColor("#80000000"));
mBottomView.setVisibility(GONE);
mBottomView.setAlpha(0f);
mMenuView.addView(mBottomView);
mBottomView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
closeContentView();
}
});
mContentView = new FrameLayout(getContext());
mContentView.setBackgroundColor(Color.WHITE);
mMenuView.addView(mContentView);
}
3.效果分析
一开始都是隐藏,当用户点击的时候才显示
mBottomView.setVisibility(GONE);
mBottomView.setAlpha(0f);
//因为 设置View的 setVisibility 会重复调用这个方法
if(mContentViewHeight == 0) {
int height = MeasureSpec.getSize(heightMeasureSpec);
mContentViewHeight = (int) (height * 0.76f);
ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams();
layoutParams.height = mContentViewHeight;
mContentView.setLayoutParams(layoutParams);
//往上移动这个布局 达到隐藏的功能
mContentView.setTranslationY(-mContentViewHeight);
}
设置点击事件
/**
* 设置tab的点击事件
* @param tabView
*/
private void setTabViewOnclickListener( View tabView) {
tabView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
mOnClickPosition = (int) view.getTag(-100);
//关闭状态
if (mCurrentPosition == -1) {
openContentView();
} else {
//不是同一个,先把上一个隐藏 切换显示
if (mCurrentPosition != mOnClickPosition) {
View currentView = mContentView.getChildAt(mCurrentPosition);
if (currentView != null) {
currentView.setVisibility(GONE);
mAdapter.contentViewClose(mTabView.getChildAt(mCurrentPosition));
}
mCurrentPosition = mOnClickPosition;
View showView = mContentView.getChildAt(mCurrentPosition);
if (showView != null) {
showView.setVisibility(VISIBLE);
mAdapter.contentViewOpen(mTabView.getChildAt(mCurrentPosition));
}
} else {
closeContentView();
}
}
}
});
}
4.打开和关闭动画
4.1打开动画
/**
* 打开动画
*/
public void openContentView(){
if(mAnimationExecute){
return;
}
if(mOpenAnimatorSet == null) {
mOpenAnimatorSet = new AnimatorSet();
ObjectAnimator contentViewAnimation = ObjectAnimator.ofFloat(mContentView, "translationY", -mContentViewHeight, 0);
ObjectAnimator bottomViewAnimation = ObjectAnimator.ofFloat(mBottomView, "alpha", 0f, 1f);
mOpenAnimatorSet.setDuration(mAnimationDuration);
mOpenAnimatorSet.playTogether(contentViewAnimation, bottomViewAnimation);
mOpenAnimatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
mAnimationExecute = true;
View view = mContentView.getChildAt(mOnClickPosition);
if (view != null) {
view.setVisibility(VISIBLE);
}
mBottomView.setVisibility(VISIBLE);
mAdapter.contentViewOpen(mTabView.getChildAt(mOnClickPosition));
}
@Override
public void onAnimationEnd(Animator animation) {
mAnimationExecute = false;
mCurrentPosition = mOnClickPosition;
}
});
}
if(!mAnimationExecute) {
mOpenAnimatorSet.start();
}
}
4.2关闭动画
/**
* 关闭动画
*/
public void closeContentView(){
if(mCloseAnimatorSet == null) {
mCloseAnimatorSet = new AnimatorSet();
ObjectAnimator contentViewAnimation = ObjectAnimator.ofFloat(mContentView, "translationY", 0, -mContentViewHeight);
ObjectAnimator bottomViewAnimation = ObjectAnimator.ofFloat(mBottomView, "alpha", 1f, 0f);
mCloseAnimatorSet.setDuration(mAnimationDuration);
mCloseAnimatorSet.playTogether(contentViewAnimation, bottomViewAnimation);
mCloseAnimatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
View view = mContentView.getChildAt(mCurrentPosition);
if (view != null) {
view.setVisibility(GONE);
}
mBottomView.setVisibility(GONE);
mCurrentPosition = -1;
mAnimationExecute = false;
}
@Override
public void onAnimationStart(Animator animation) {
mAnimationExecute = true;
mAdapter.contentViewClose(mTabView.getChildAt(mCurrentPosition));
}
});
}
if(!mAnimationExecute) {
mCloseAnimatorSet.start();
}
}
5.设置tabView的布局显示(Adapter设计模式)
使用Adapter设计模式,给tabVIew添加布局并且也给内容也添加布局
看代码:
/**
* 设置adapter
* @param adapter
*/
public void setAdapter(BaseListMenuAdapter adapter){
if(adapter == null){
throw new IllegalArgumentException("请设置->BaseListMenuAdapter");
}
this.mAdapter = adapter;
for (int i = 0; i < mAdapter.getCount(); i++) {
View tabView = mAdapter.getTabView(i, mTabView);
if(tabView != null){
LayoutParams layoutParams = new LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT);
layoutParams.weight = 1;
layoutParams.gravity = Gravity.CENTER;
tabView.setLayoutParams(layoutParams);
mTabView.addView(tabView);
tabView.setTag(-100,i);
setTabViewOnclickListener(tabView);
}
View contentView = mAdapter.getContentView(i, mContentView);
if(contentView != null){
contentView.setVisibility(GONE);
mContentView.addView(contentView);
}
}
}
循环列表,然后添加view。一般列表数据都是从后台接口返回的。
下面再看一下baseAdapter的代码,可以自己在添加一些功能,我这里想到了几个就写了几个而已。findViewById还是可以再优化的,比如可以建立一个集合来进行缓存就可以了。还有数据改变之后去刷新tabView的数据,可以自己写一个notifyDataSetChanged的方法,自己想想应该怎么写?
/**
* created by panshimu
* on 2019/8/23
*/
public abstract class BaseListMenuAdapter {
public abstract int getCount();
public abstract View getTabView(int position, ViewGroup parent);
public abstract View getContentView(int position,ViewGroup parent);
public abstract void contentViewClose(View tabView);
public abstract void contentViewOpen(View tabView);
}
下面就是 ListMenuAdapter 继承 BaseListMenuAdapter 类似 ListView的adapter,这种就是模仿listView写的。可以自己再去添加很多很多方法
/**
* created by panshimu
* on 2019/8/23
*/
public class ListMenuAdapter extends BaseListMenuAdapter{
private List<String> mData;
private LayoutInflater mInflater;
public ListMenuAdapter(Context context,List<String> mData) {
this.mData = mData;
this.mInflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return mData.size();
}
@Override
public View getTabView(int position, ViewGroup parent) {
View tabView = mInflater.inflate(R.layout.ui_tab_view,parent,false);
TextView tvTab = tabView.findViewById(R.id.tv_tab);
tvTab.setText(mData.get(position));
return tabView;
}
@Override
public View getContentView(int position, ViewGroup parent) {
View contentView = mInflater.inflate(R.layout.ui_content_view,parent,false);
TextView tvContent = contentView.findViewById(R.id.tv_content);
tvContent.setText(mData.get(position));
return contentView;
}
@Override
public void contentViewClose(View tabView) {
TextView tvTab = tabView.findViewById(R.id.tv_tab);
tvTab.setTextColor(Color.GRAY);
}
@Override
public void contentViewOpen(View tabView) {
TextView tvTab = tabView.findViewById(R.id.tv_tab);
tvTab.setTextColor(Color.RED);
}
}
6.如果使用
是不是很简单?
public class MainActivity extends AppCompatActivity {
private ListMenuView mListMenuView;
private List<String> mData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addData();
mListMenuView = findViewById(R.id.list_menu_view);
ListMenuAdapter listMenuAdapter = new ListMenuAdapter(this, mData);
mListMenuView.setAdapter(listMenuAdapter);
}
private void addData() {
mData = new ArrayList<>();
mData.add("推荐");
mData.add("热点");
mData.add("关注");
mData.add("视频");
mData.add("游戏");
}
}
下面再贴出布局xml的代码:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
android:background="#fff"
tools:context=".MainActivity">
<TextView
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
/>
<com.miaozi.listmenuview.ListMenuView
android:id="@+id/list_menu_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView
android:layout_marginBottom="50dp"
android:layout_centerHorizontal="true"
android:textColor="#000"
android:layout_alignParentBottom="true"
android:text="我是底部"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
ui_content_view.xml
这里可以根据项目的需要自行设计和修改,比如是一个列表模式的listView或是等等其他联动的布局都是可以的,它的根部局是 FrameLayout 所以可以随便设计
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_content"
android:textColor="#000"
android:textSize="15sp"
android:text="wo de "
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
剩下的就是 ui_tab_view.xml 这个是tabView的每一个item的布局,我这里是一个TextView,在项目的开发中一个都是一个TextView和一个Imageview配合使用 当选中的时候 imageview箭头向下或是向上等等效果
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_tab"
android:textColor="@android:color/darker_gray"
android:textSize="15sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
好了就这么多了。
我写这个主要是为了练习属性动画的使用。
最后在留下源码地址,需要的同学可以自己下载
https://github.com/panshimu/ListMenuView
有问题随时问,看到会答复的,谢谢!
QQ:362976241