本文简单介绍使用属性动画来实现上滑显示底部导航,下滑显示标题bar。先上图看效果,再分析:
可以看出这是个listview有标题和底部,有点像下拉刷新和上拉加载更多。只不过下拉或上拉一定时位置固定拉不动,且只在list的第一个item出现显示时,才平滑动画的让标题或底部显示或隐藏。
实现思路:
1、整个布局有三个部分构成,上部由一个RelativeLayout放ImageView或TextView.中间部分是个listView,下部是一个TextView.
2、采用LinearLayout摆放中下部分,让屏幕初始时把上部分移出屏幕外面。中间listview与底部往上移。
3、采用平移动画,移动动画有两种一种tween动画一种属性动画。而tween动画是假移事件焦点还在原来地方,而属性动画则是3.0支持的为了兼容3.0以下的这里采用nineoldandroids。
4、通过给listview设置touch listener,监听手掼是向下滑动的(Y比X移动距离大)且滑动距离足够大时,判断是向下反之亦然是向上。event move过程会有多次回调,为了保证在一次dowm 向下滑动时,需要在down 时设置标志,来保证一次down 向下滑动时只调用动画一次 做显示标题动作。
上代码:
布局文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/id_content" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <!-- 上部分 --> <RelativeLayout android:id="@+id/rl_title" android:layout_width="match_parent" android:layout_height="50dp" android:background="#A8A8A8" > <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_marginLeft="20dp" android:layout_centerVertical="true" android:src="@drawable/icon_back" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="标题111" android:layout_centerInParent="true" android:textColor="#000000" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_marginRight="20dp" android:layout_centerVertical="true" android:src="@drawable/icon_search" /> </RelativeLayout> <ListView android:id="@+id/lv_data" android:layout_width="fill_parent" android:layout_height="fill_parent" android:listSelector="@null" android:dividerHeight="1dp" android:divider="#a5a5a5" /> <!-- 下部分 --> <TextView android:id="@+id/tv_bottom" android:layout_width="match_parent" android:layout_height="50dp" android:text="我是底部的栏目" android:textSize="18sp" android:textColor="#ffffff" android:background="#a3a3a3" android:gravity="center" /> </LinearLayout>
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
</pre><p></p><pre>
package com.test.projecta; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.util.TypedValue; import android.view.MotionEvent; import android.view.TextureView; import android.view.View; import android.view.View.OnTouchListener; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.TextView; import com.nineoldandroids.animation.ObjectAnimator; public class HideShowTitleActivity extends Activity { private RelativeLayout rl_title; private ListView lv_data; private List<String> mListDatas; private boolean mIsShowTitle = false; private float mTranslateY; private boolean mIsfirstVisible = true; private TextView tv_bottom; private float mBottomHeight; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_newhideshowtitlelist_back); findView(); setListener(); doLogic(); } private void findView() { rl_title = (RelativeLayout) findViewById(R.id.rl_title); lv_data = (ListView) findViewById(R.id.lv_data); tv_bottom = (TextView) findViewById(R.id.tv_bottom); } @Override public void onWindowFocusChanged(boolean hasFocus) { if(hasFocus){ //获取listview的高度 那么bottom开始的位置是mTranslateY+height值 int height = lv_data.getHeight(); mBottomHeight = mTranslateY + height; showHideTitle(false,0); } } private void setListener() { lv_data.setOnScrollListener(new OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { //判断当前是否在显示list的第一项数据 mIsfirstVisible = firstVisibleItem==0; //手掼滑动太快时非显示第一项还显示标题时,隐藏掉标题 if(mIsShowTitle && !mIsfirstVisible){ showHideTitle(false,500); } } }); lv_data.setOnTouchListener(new OnTouchListener() { private float lastX; private float lastY; boolean isChange = false; @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: lastX = event.getX(); lastY = event.getY(); isChange = false; return false; case MotionEvent.ACTION_MOVE: float x = event.getX(); float y = event.getY(); float xGapDistance = Math.abs(x-lastX); float yGapDistance = Math.abs(y-lastY); boolean isDown = y-lastY>5; //没有显示标题时,且是向下的,就显示 boolean isShow = yGapDistance > 8 && xGapDistance<8 && !mIsShowTitle && isDown; boolean isHide = yGapDistance > 8 && xGapDistance<8 && mIsShowTitle && !isDown; lastX = x; lastY = y; //一次down,只变化一次,防止一次滑动时抖动下,造成某一个的向下时,y比lastY小 if(!isChange&&mIsfirstVisible&&isShow){ // 显示此标题 showHideTitle(true,500); isChange = true; }//显示标题时,且是向上的,就隐蔽 else if(!isChange&&mIsfirstVisible&&isHide){ // 隐蔽标题 showHideTitle(false,500); isChange = true; } break; default: break; } return false; } }); } private void showHideTitle(boolean isShow,int duration) { if(isShow){ ObjectAnimator.ofFloat(lv_data, "y",0,mTranslateY).setDuration(duration).start(); ObjectAnimator.ofFloat(rl_title, "y", -mTranslateY,0).setDuration(duration).start(); ObjectAnimator.ofFloat(tv_bottom, "y", mBottomHeight-mTranslateY,mBottomHeight).setDuration(duration).start(); }else{//隐藏时,把标题隐藏了,底部出来了 ObjectAnimator.ofFloat(lv_data, "y", mTranslateY,0).setDuration(duration).start(); ObjectAnimator.ofFloat(rl_title, "y", 0f,-mTranslateY).setDuration(duration).start(); ObjectAnimator.ofFloat(tv_bottom, "y", mBottomHeight,mBottomHeight-mTranslateY).setDuration(duration).start(); } mIsShowTitle = isShow; } private void doLogic() { mListDatas = new ArrayList<String>(); for(int i=0;i<50;i++){ mListDatas.add("数据"+i); } ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mListDatas); lv_data.setAdapter(adapter); //将标题栏高度50dp转成显示的高度 mTranslateY = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, getResources().getDisplayMetrics()); } }
OK。。。。。。其实,这个还有更简单的实现,直接将整个布局ll_content进行向上或向下移动即可。够简单的吧...
版权声明:本文为博主原创文章,未经博主允许不得转载。