Android 上滑显示底部导航,下滑显示标题bar

 本文简单介绍使用属性动画来实现上滑显示底部导航,下滑显示标题bar。先上图看效果,再分析:

Android 上滑显示底部导航,下滑显示标题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>

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());
	}
	
}

转自:http://blog.csdn.net/chenshufei2/article/details/47317491


扩展:

android ListView向上滑动隐藏标题,下拉显示标题栏,完美解决滑动出现的空白问题。


http://download.csdn.net/detail/tuibiansoar/8153269

上一篇:Toast使用详解0


下一篇:【COCOS2DX-LUA 脚本开发之六】Lua强转函数解决报错及介绍两款框架