listview上拉隐藏标题与下拉显示标题

这个功能非常普遍了,主要是用户在下拉列表的时候,隐藏标题来扩大用户浏览列表的范围

本方法的设计思路是在列表上覆盖标题栏,然后当列表滑到顶部的时候,在列表的顶部设置一个padding控件来占和标题一样的高度,防止列表顶部被标题覆盖,当列表往下滑动的时候,通过动画隐藏标题,只要列表的第一个item不可视,就把padding控件给隐藏掉,这样达到列表填充整个屏幕的效果

先看布局

<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:animateLayoutChanges="true"
    tools:context="com.example.showhidetitlelistview.MainActivity" >

    <View
        android:id="@+id/padding"
        android:layout_width="match_parent"
        android:layout_height="@dimen/title_height" />

    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/padding"
        android:background="#F4F1F1" >
    </ListView>

    <LinearLayout
        android:id="@+id/titleLayout"
        android:layout_width="match_parent"
        android:layout_height="@dimen/title_height"
        android:background="@android:color/white"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_weight="1"
            android:gravity="center"
            android:text="标题" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_weight="1"
            android:gravity="center"
            android:text="标题" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_weight="1"
            android:gravity="center"
            android:text="标题" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_weight="1"
            android:gravity="center"
            android:text="标题" />
    </LinearLayout>

</RelativeLayout>

listview在padding下方,而标题是在屏幕上方,覆盖所有控件

值得注意的是在根布局中设置的动画属性

android:animateLayoutChanges="true"

原因是设置padding控件消失会出现的时候,产生动画的效果,但是padding本身是透明的,所以我不关心它的效果如何(实际上,系统会给它一个淡入淡出的效果),我关心的是这个动画是占用一定时间的,列表在调整自身位置的时候,也会产生向上滑动的效果。网上有一些方法是通过设置根布局paddingtop属性,这个方法在调用的时候,listview会瞬间调整好当前的位置,导致屏幕闪了一下,如果用户缓缓向下滑动不松手的话,滑动某个位置触发了setpadding方法,屏幕会一直闪啊坑爹!

 

接着看代码

/**
	 * 由于标题是覆盖在列表上面的,需要设置一个padding来防止列表被标题被覆盖
	 */
	public void setPadding() {
		padding.setVisibility(View.VISIBLE);
	}

	/**
	 * 当列表往下滑动的时候,标题隐藏了,为了调整列表的高度使其填充整个屏幕,只需要去除padding控件即可
	 * 之前使用设置跟布局padding的方法,交互不友好,会闪屏,所以采取隐藏padding控件和根布局动画属性的方法
	 */
	public void reMovePadding() {
		padding.setVisibility(View.GONE);
	}
/**
	 * 隐藏标题,通过属性动画实现,和补间动画相比,属性动画真实改变了控件的位置,补间动画只是障眼法
	 * 个人比较嫌弃补间动画
	 */


	private boolean isTitleMenuOpen=true;
	private int titleMenuHeight;
	public void hideTitle() {
		if (isTitleMenuOpen) {
			ObjectAnimator
					.ofFloat(titleLayout, "translationY", 0.0F,
							-titleMenuHeight).setDuration(300).start();
			isTitleMenuOpen = false;
		}

	}

	
	/**
	 * 显示标题
	 */
	public void showTitle() {
		if (!isTitleMenuOpen) {
			ObjectAnimator
					.ofFloat(titleLayout, "translationY", -titleMenuHeight,
							0.0F).setDuration(300).start();
			isTitleMenuOpen = true;
		}
	}

在这里,细心的人就会发现,为什么我不把设置padding控件和标题动画放在同一个方法里面呢?

这是因为他们的调用时机是有很大差别的,只有滑动的时候在执行标题动画,设置padding控件属性只能是列表第一个item可视的时候设置

不然每次滑动都调整padding,列表会莫名的滑动标题高度的距离,用户会崩溃的

 

下面是核心代码:

/**
	 * 列表的滑动监听,关键在于监听列表是否滑动到顶部,如果是,就把padding控件显示出来,防止标题覆盖列表
	 * 其他情况下,隐藏padding,达到列表填充整个屏幕的效果
	 * 千万要记住,padding的出现和隐藏都会让列表的位置发生调整,这样给用户的体验很差,所以不要频繁调用setpadding和removepadding方法
	 */

	private boolean isFirstVisiable=true;
	
	private OnScrollListener myOnScrollListener=new OnScrollListener() {
		
		@Override
		public void onScrollStateChanged(AbsListView view, int scrollState) {
			// TODO Auto-generated method stub
			
		}
		
		@Override
		public void onScroll(AbsListView view, int firstVisibleItem,
				int visibleItemCount, int totalItemCount) {
			// TODO Auto-generated method stub
			if (firstVisibleItem == 0) {
				setPadding();
				showTitle();
				isFirstVisiable=true;
			} else {
				reMovePadding();
				isFirstVisiable=false;
			}
		}
	};
/**
	 * 判断滑动方向,如果方向向上并且第一个item不可视,就隐藏标题
	 * 为什么要判断第一个标题不可视呢,因为第一个标题可视是设置padding控件显示的关键,
	 */
    private float y_tmp1, y_tmp2;

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		// 获取当前坐标
		float y = event.getY();
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			y_tmp1 = y;
			break;
		case MotionEvent.ACTION_MOVE:
			y_tmp2 = y;
			if (y_tmp1 != 0 && y_tmp2 != 0) {
				if (y_tmp1 - y_tmp2 > 8
						&&! isFirstVisiable	) {// 向上滑动隐藏标题和导航栏
					hideTitle();
					Log.i("scolling", "向上滑动");
				}
				if (y_tmp2 - y_tmp1 > 8) {// 向下滑动显示标题和导航栏
					showTitle();
					Log.i("scolling", "向下滑动");
				}
			}
			break;
		}
		return false;
	}

在onCreate方法里面的一些初始化操作

@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mContext = this;
		initData();
		padding=findViewById(R.id.padding);
		titleLayout=findViewById(R.id.titleLayout);
		titleMenuHeight=getResources().getDimensionPixelSize(R.dimen.title_height);
		listview = (ListView) findViewById(R.id.listview);
		listview.addHeaderView(View
				.inflate(mContext, R.layout.item_blank, null));
		listview.setAdapter(new Myadapter());
		listview.setOnTouchListener(this);
		listview.setOnScrollListener(myOnScrollListener);
	}

以上操作基本实现了本博文题目的功能,但是有个问题,实际项目中,listview的item可能会很大,高度超过100dp的,当第一个item可视的时候,向上滑动,标题隐藏了,padding却不隐藏起来,因为它只有第一个item不可视的时候才隐藏啊,这就尴尬了。之前的东西就白看了呢!不用灰心!既然只要第一个可视的item不可视,padding就能隐藏起来对吧,那我来个瞒天过海,通过插入一个空白的头部就好了,并且这个头部很窄,只有1dp,只要手一滑动,基本就能把这个头部给划走,列表自然会填充整个屏幕;同理,当列表向下滑动的时候,只要这个很窄的头部出现,padding控件就会出现,列表的位置也调整过来了。这是比较取巧的地方!!!

源码:

http://pan.baidu.com/s/1c2Ntkas

转载于:https://my.oschina.net/carbenson/blog/725972

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值