当前位置: 代码迷 >> Android >> Android阶篇3-自定义ListView实现底部View自动隐藏和消失的功能
  详细解决方案

Android阶篇3-自定义ListView实现底部View自动隐藏和消失的功能

热度:69   发布时间:2016-04-28 07:45:45.0
Android高手进阶篇3-自定义ListView实现底部View自动隐藏和消失的功能

  以后每一周会分享Android技术难点,今天主要分享这样一个功能:有这样一个ListView,要求在屏幕底部有一个筛选排序的浮动框:

1、手指下拉隐藏,上滑显示 ;

2、如果没做任何操作,2S之后,要自动显示;

3、滑动到最底部,始终显示。

首先看其效果图:

 

实现上述效果,其实现原理如下:

 1、在屏幕顶部固定一个BottomView,XML布局最好使用RelativeLayout(底部的BottomView并不是 ListView的footView,这个是和footView独立的,想想为什么?)

 2、然后自定义ListView控件,监听onTouchEvent事件,主要是监听手指下滑和上滑事件,同时实现onScrollListener,监听是否滑动到最底部和最顶部

3、 ListView监听事件中,控制bottomView的显示和隐藏,所以ListView提供一个接口,设置底部bootomView的内容,然后获之后,就可以对bottomView进行控制,同时加上动画效果。

接下来看是如何的具体实现这种效果:

1。底部BottomView的内容如下,这个XML文件的内容是自定义的,根据各项目的内容需求来定义的,我例子中bottom_view.xml:

<?xml version="1.0" encoding="UTF-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/button_layout"    android:layout_width="fill_parent"    android:layout_height="50dp"    android:background="#cbcbcb"    android:gravity="center_vertical"    android:orientation="horizontal" >        <Button android:layout_height="40dp"                  android:layout_width="wrap_content"                  android:layout_weight="1"                  android:text="价格"  />    <Button android:layout_height="40dp"              android:layout_width="wrap_content"              android:layout_weight="1"              android:text="好评"  />    <Button android:layout_height="40dp"            android:layout_width="wrap_content"            android:layout_weight="1"            android:text="筛选"  /></LinearLayout>


2、main.xml如下:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"              android:orientation="vertical"              android:layout_width="fill_parent"              android:layout_height="fill_parent"        >    <com.example.BottomFloatListView.BottomFloatListView            android:id="@+id/listView"            android:layout_width="fill_parent"            android:layout_height="fill_parent"            android:fadingEdge="none"            />    <include            android:id="@+id/bottombar"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_alignParentBottom="true"            layout="@layout/bottom_view"            >    </include></RelativeLayout>


main.xml中采用的RelativeLayout,有自定义的控件BottomFloatListView,然后屏幕底部放的是bottom_view,我是通过include的方式引用过来的,这样多处引用比较方便。

3、自定义ListView控件BottomFloatListView代码如下

package com.example.BottomFloatListView;import android.content.Context;import android.os.Handler;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.view.animation.Animation;import android.view.animation.OvershootInterpolator;import android.view.animation.TranslateAnimation;import android.widget.*;import android.widget.AbsListView.OnScrollListener;/** * 底部View自动隐藏和消失listview(其他ListView可以继承该类,如CtripBottomRefreshListView类等) *  * @author zhiwen.nan * @Date 2013-9-28 下午3:35:15 *  */public class BottomFloatListView extends ListView implements OnScrollListener {    public View mBottomBar;    private int mCurrentScrollState;    private boolean bIsMoved = false;    private boolean bIsDown = false;    private int mDeltaY;    private float mMotionY;	private int oldFirstVisibleItem = 0;    private Handler mHandler = new Handler();    private static final String TAG = "BottomFloatListView";	public BottomFloatListView(Context context) {		this(context, null);		super.setOnScrollListener(this);	}	public BottomFloatListView(Context context, AttributeSet attrs) {		this(context, attrs, 0);		super.setOnScrollListener(this);	}	public BottomFloatListView(Context context, AttributeSet attrs, int defStyle) {		super(context, attrs, defStyle);		super.setOnScrollListener(this);	}	@Override	public void setAdapter(ListAdapter adapter) {		super.setAdapter(adapter);	}	@Override	public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {        showBottomViewOnBottom(visibleItemCount, totalItemCount, firstVisibleItem);	}	@Override	public void onScrollStateChanged(AbsListView view, int scrollState) {        hideBottomViewOnScrollStateChanged(view, scrollState);	}    @Override	public boolean onTouchEvent(MotionEvent ev) {    	    	 float y = ev.getY();         float x = ev.getX();         Log.d("FloatListView", "onTouchEvent" + "" + x + "" + y);         int action = ev.getAction() & MotionEvent.ACTION_MASK;         switch (action) {             case MotionEvent.ACTION_DOWN:                 action_down(y);                 break;             case MotionEvent.ACTION_MOVE:                 mDeltaY = (int) (y - mMotionY);                 bIsMoved = true;                 //移动的时候,要移除掉显示bottomView的消息                 mHandler.removeCallbacks(showBottomBarRunnable);                 //补齐action_down事件,因为有的时候,action_down 事件没有执行                 action_down(y);                 break;             case MotionEvent.ACTION_UP:                 bIsMoved = false;                 bIsDown = false;                 if (!bIsMoved && !bIsDown) {                     // 如果屏幕上什么没做,则过2s之后要显示bottomView                     mHandler.postDelayed(showBottomBarRunnable, 2000);                 }                 if (mDeltaY < 0) { //下滑影藏                 	 hideBottomBar();                 } else {  //上滑显示                     showBottomBar();                 }                 bIsMoved = false;                 break;         }		return super.onTouchEvent(ev);	}            private void action_down(float y){    	  mMotionY = y;          bIsDown = true;          Log.d(TAG, "action down execed");          mHandler.removeCallbacks(showBottomBarRunnable);    }    /**     * 滑动到顶部时,要隐藏bottomView     * @param view     * @param scrollState     */    private void hideBottomViewOnScrollStateChanged(AbsListView view, int scrollState) {        mCurrentScrollState = scrollState;        if(view!=null){        	 if (view.getFirstVisiblePosition() == 0 && scrollState == SCROLL_STATE_IDLE) {                 hideBottomBar();                 Log.d(TAG, "hide bottom view");             }        }           }    /**     * 显示底部浮动栏     */    public void showBottomBar() {        if (mBottomBar != null && mBottomBar.getVisibility() == View.GONE) {            mBottomBar.setVisibility(View.INVISIBLE);            Animation translateAnimation = new TranslateAnimation(mBottomBar.getLeft(), mBottomBar.getLeft(),30, 0);            translateAnimation.setDuration(300);            translateAnimation.setInterpolator(new OvershootInterpolator(0.6f));            mBottomBar.startAnimation(translateAnimation);            translateAnimation.setAnimationListener(new Animation.AnimationListener() {                @Override                public void onAnimationStart(Animation animation) {                }                @Override                public void onAnimationRepeat(Animation animation) {                }                @Override                public void onAnimationEnd(Animation animation) {                    mBottomBar.setVisibility(View.VISIBLE);                }            });        }    }    /**     * 隐藏浮动底部栏     */    private void hideBottomBar() {                if (mBottomBar != null && mBottomBar.getVisibility() == View.VISIBLE) {            Animation translateAnimation = new TranslateAnimation(mBottomBar.getLeft(), mBottomBar.getLeft(), 0, 30);            translateAnimation.setDuration(300);            translateAnimation.setInterpolator(new OvershootInterpolator(0.6f));            mBottomBar.startAnimation(translateAnimation);            translateAnimation.setAnimationListener(new Animation.AnimationListener() {                @Override                public void onAnimationStart(Animation animation) {                }                @Override                public void onAnimationRepeat(Animation animation) {                }                @Override                public void onAnimationEnd(Animation animation) {                    mBottomBar.setVisibility(View.GONE);                }            });        }    }    /**     * 滑动到底部时直接显示bottomView     * @param visibleItemCount     * @param totalItemCount     * @param firstVisibleItem     */    private void showBottomViewOnBottom(int visibleItemCount, int totalItemCount, int firstVisibleItem) {                	Log.d(TAG, "visible bottem item count:"  + "firstVisibleItem:" +  firstVisibleItem + "oldFirstVisibleItem:" + oldFirstVisibleItem + mBottomBar);             if(getLastVisiblePosition() ==   totalItemCount -1 && mCurrentScrollState != SCROLL_STATE_IDLE){                 showBottomBar();             }    }    private Runnable showBottomBarRunnable = new Runnable() {        @Override        public void run() {            showBottomBar();        }    };    /**	 * 将需要隐藏显示的view传入	 * 	 * @param bottomBar	 */	public void setBottomBar(ViewGroup bottomBar) {		this.mBottomBar = bottomBar;	}}上述代码中,重要和难理解的地方,都加了注释,很好理解。

4、主界面测试的Activity,MainActivity代码如下

 

package com.example.BottomFloatListView;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.ViewGroup;import android.widget.ArrayAdapter;import java.util.ArrayList;import java.util.List;public class MainActivity extends Activity {    private  BottomFloatListView mBottomFloatListView;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        mBottomFloatListView = (BottomFloatListView)findViewById(R.id.listView)  ;        mBottomFloatListView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1,getData()));        ViewGroup bottomView = (ViewGroup)findViewById(R.id.bottombar) ;        mBottomFloatListView.setBottomBar(bottomView);    }    private List<String> getData(){        List<String> data = new ArrayList<String>();        for(int i = 0; i <100; i++)      {            data.add("测试数据" + i);        }        return data;    }}


上述Activity中告诉了如何使用了BottomFloatListView控件,下面两句代码比较关键:

ViewGroup bottomView = (ViewGroup)findViewById(R.id.bottombar) ;        mBottomFloatListView.setBottomBar(bottomView);


 

将底部的bottomView传入到ListView中,就可以让ListView具有底部View自动隐藏和消失的功能。

 集成到自己项目中,仅需1分钟搞定,有木有,如果有什么疑问,欢迎留言提问   。

 

源代码下载:

http://download.csdn.net/detail/nanzhiwen666/6392729


 

  相关解决方案