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

本文简单介绍使用属性动画来实现上滑显示底部导航,下滑显示标题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进行向上或向下移动即可。够简单的吧...

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-19 00:00:28

Android 上滑显示底部导航,下滑显示标题bar的相关文章

Android上的MVP:如何组织显示层的内容

MVP(Model View Presenter)模式是著名的MVC(Model View Controller)模式的一个演化版本,目前它在Android应用开发中越来越重要了,大家也都在讨论关于MVP的理论,只是结构化的资料非常少.这就是我写这篇博客的原因,我想鼓励大家多参与讨论,然后把MVP模式运用在项目开发中. 什么是MVP? MVP模式可以分离显示层和逻辑层,所以功能接口如何工作与功能的展示可以实现分离,MVP模式理想化地可以实现同一份逻辑代码搭配不同的显示界面.首先要澄清就是MVP不

iOS 上滑隐藏导航,下滑显示导航,仿斗鱼导航效果

UItableView或 UIcollectionView 都是继承UIScrollView 滑动的时候,判断是上滑还是下滑 使用 UIScrollView 的代理方法 p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000 } span.s1 { color: #ba2da2 } span.s2 { } span.s3 { color: #703daa } func scrollViewWillEnd

RecyclerView 滑动检测 (上滑 up)(下滑 down)(顶部 top)(底部 bottom)

RecyclerView 给我们的可以检测滑动事件的接口 只有 一个方法 recyclerview.setOnScrollListener()或者 recyclerview.addOnScrollListener() set方法将会被弃用 deprecated 最好使用add方法但是这个也可以根据自己情况,如果自己当前的api中set方法没有被弃用,不存在add方法.就只能使用set方法了. 监听 上滑,下滑 这些都不是重点,接下来就分析如何监听,RecyclerView的滑动. Recycle

关于在Android中如何设置底部导航栏

Android应用底部导航栏(选项卡)实例 现在很多android的应用都采用底部导航栏的功能,这样可以使得用户在使用过程中随意切换不同的页面,现在我采用TabHost组件来自定义一个底部的导航栏的功能. 我们先看下该demo实例的框架图:   其中各个类的作用以及资源文件就不详细解释了,还有资源图片(在该Demo中借用了其它应用程序的资源图片)也不提供了,大家可以自行更换自己需要的资源图片.直接上各个布局文件或各个类的代码: [1]  res/layout目录下的maintabs.xml 源码

Android上滑手势触发和不增加布局层级扩大点击区域

最近项目中需要实现手势上滑或者点击滑出界面的效果,实现上是利用GestureDetector,然后在onFling中判断,但遇到一个问题:手势上滑是针对整个布局的,但如果有对单独的View设置点击监听,在该View上的手势上滑会失效. 如果这个View本身就是专门用于点击的,那并没有什么问题,可惜的是,这个View的尺寸不大,所以要求扩大点击区域. 我们首先能想到的方法就是用一个容器将该View包起来,类似RelativeLayout,LinearLayout等,但这样布局的层级就会再加多一层.

Android之framework修改底部导航栏NavigationBar动态显示和隐藏

大家都知道,Android从3.0版本开始就加入了NavigationBar,主要是为那些没有实体按键的设备提供虚拟按键,但是,它始终固定在底部,占用48dp的像素高度,尽管从android 4.4开始可以全透明,使用这一部分像素,但三个按钮始终悬浮在屏幕上,这对于有强迫症的朋友来说是无法忍受的.因此,本文的目的就是修改framework部分代码,可以动态隐藏和显示NavigationBar,同时又尽量不影响系统的正常. 主要思路: 在NavigationBar的布局左部加入一个Button(在

Android Fragment实现微信底部导航

1.XML布局 (1)主界面 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://

Android开发关闭虚拟按钮、底部导航条

在Android开发中,遇到了一系列大大小小的问题,其中一个就是屏蔽底部实体键,我找了很多的博客也尝试了许许多多的方法,但始终不能屏蔽 HOME键,后来看见一篇博客说在Android 4.0以后,屏蔽底部HOME键必须反编译,修改Android底部原生代码,于是我便放弃了.废话不多说,我先分享一个屏蔽Android虚拟按键的方法,以及最简单的屏蔽Android的Back按钮,适合所有版本(未测试,感觉是这样): 1. Android 屏蔽Back按键 只需要重写 onKeyDown 方法就可以了

[UI组件基础] 制作一个带有底部导航以及顶部导航的single view application

最近开始写博客了,把我学习到的东西进行汇总和总结. 很多初学iOS手机应用程序开发的刚开始肯定是抓头的,搞不好,是大片大片的头发往下扯. 因为很迷茫啊,都不知道要怎么弄,有真机有大神帮忙的人还好说,没有机器又没有朋友的人就惨了,完全不知道从何开始. 其实我觉得把,如果是真想学,最次最次,你最少弄个XCode用用看. 前期如果没有XCode,没有苹果电脑,也可以先从基础语法开始学起,其实oc语法也很蛋疼的,什么*啊,alloc啊init啊.估计跟大家想象的世界完全不同,学了java的人再来看oc,