关闭

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

标签: android
554人阅读 评论(0) 收藏 举报
分类:

 以后每一周会分享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:

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:id="@+id/button_layout"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="50dp"  
  6.     android:background="#cbcbcb"  
  7.     android:gravity="center_vertical"  
  8.     android:orientation="horizontal" >  
  9.   
  10.         <Button android:layout_height="40dp"  
  11.                   android:layout_width="wrap_content"  
  12.                   android:layout_weight="1"  
  13.                   android:text="价格"  />  
  14.   
  15.     <Button android:layout_height="40dp"  
  16.               android:layout_width="wrap_content"  
  17.               android:layout_weight="1"  
  18.               android:text="好评"  />  
  19.   
  20.     <Button android:layout_height="40dp"  
  21.             android:layout_width="wrap_content"  
  22.             android:layout_weight="1"  
  23.             android:text="筛选"  />  
  24.   
  25.   
  26. </LinearLayout>  


2、main.xml如下:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.               android:orientation="vertical"  
  4.               android:layout_width="fill_parent"  
  5.               android:layout_height="fill_parent"  
  6.         >  
  7.   
  8.     <com.example.BottomFloatListView.BottomFloatListView  
  9.             android:id="@+id/listView"  
  10.             android:layout_width="fill_parent"  
  11.             android:layout_height="fill_parent"  
  12.             android:fadingEdge="none"  
  13.             />  
  14.   
  15.   
  16.     <include  
  17.             android:id="@+id/bottombar"  
  18.             android:layout_width="match_parent"  
  19.             android:layout_height="wrap_content"  
  20.             android:layout_alignParentBottom="true"  
  21.             layout="@layout/bottom_view"  
  22.             >  
  23.     </include>  
  24. </RelativeLayout>  


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

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

  1. package com.example.BottomFloatListView;  
  2.   
  3. import android.content.Context;  
  4. import android.os.Handler;  
  5. import android.util.AttributeSet;  
  6. import android.util.Log;  
  7. import android.view.MotionEvent;  
  8. import android.view.View;  
  9. import android.view.ViewGroup;  
  10. import android.view.animation.Animation;  
  11. import android.view.animation.OvershootInterpolator;  
  12. import android.view.animation.TranslateAnimation;  
  13. import android.widget.*;  
  14. import android.widget.AbsListView.OnScrollListener;  
  15.   
  16.   
  17.   
  18. /** 
  19.  * 底部View自动隐藏和消失listview(其他ListView可以继承该类,如CtripBottomRefreshListView类等) 
  20.  *  
  21.  * @author zhiwen.nan 
  22.  * @Date 2013-9-28 下午3:35:15 
  23.  *  
  24.  */  
  25. public class BottomFloatListView extends ListView implements OnScrollListener {  
  26.   
  27.     public View mBottomBar;  
  28.     private int mCurrentScrollState;  
  29.     private boolean bIsMoved = false;  
  30.     private boolean bIsDown = false;  
  31.     private int mDeltaY;  
  32.     private float mMotionY;  
  33.     private int oldFirstVisibleItem = 0;  
  34.     private Handler mHandler = new Handler();  
  35.     private static final String TAG = "BottomFloatListView";  
  36.   
  37.   
  38.     public BottomFloatListView(Context context) {  
  39.         this(context, null);  
  40.         super.setOnScrollListener(this);  
  41.     }  
  42.   
  43.     public BottomFloatListView(Context context, AttributeSet attrs) {  
  44.         this(context, attrs, 0);  
  45.         super.setOnScrollListener(this);  
  46.     }  
  47.   
  48.     public BottomFloatListView(Context context, AttributeSet attrs, int defStyle) {  
  49.         super(context, attrs, defStyle);  
  50.         super.setOnScrollListener(this);  
  51.     }  
  52.   
  53.   
  54.     @Override  
  55.     public void setAdapter(ListAdapter adapter) {  
  56.         super.setAdapter(adapter);  
  57.     }  
  58.   
  59.   
  60.     @Override  
  61.     public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {  
  62.   
  63.         showBottomViewOnBottom(visibleItemCount, totalItemCount, firstVisibleItem);  
  64.   
  65.     }  
  66.   
  67.     @Override  
  68.     public void onScrollStateChanged(AbsListView view, int scrollState) {  
  69.   
  70.         hideBottomViewOnScrollStateChanged(view, scrollState);  
  71.   
  72.     }  
  73.   
  74.   
  75.     @Override  
  76.     public boolean onTouchEvent(MotionEvent ev) {  
  77.           
  78.          float y = ev.getY();  
  79.          float x = ev.getX();  
  80.          Log.d("FloatListView""onTouchEvent" + "" + x + "" + y);  
  81.          int action = ev.getAction() & MotionEvent.ACTION_MASK;  
  82.          switch (action) {  
  83.              case MotionEvent.ACTION_DOWN:  
  84.                  action_down(y);  
  85.                  break;  
  86.              case MotionEvent.ACTION_MOVE:  
  87.                  mDeltaY = (int) (y - mMotionY);  
  88.                  bIsMoved = true;  
  89.                  //移动的时候,要移除掉显示bottomView的消息  
  90.                  mHandler.removeCallbacks(showBottomBarRunnable);  
  91.                  //补齐action_down事件,因为有的时候,action_down 事件没有执行  
  92.                  action_down(y);  
  93.                  break;  
  94.              case MotionEvent.ACTION_UP:  
  95.                  bIsMoved = false;  
  96.                  bIsDown = false;  
  97.                  if (!bIsMoved && !bIsDown) {  
  98.                      // 如果屏幕上什么没做,则过2s之后要显示bottomView  
  99.                      mHandler.postDelayed(showBottomBarRunnable, 2000);  
  100.                  }  
  101.                  if (mDeltaY < 0) { //下滑影藏  
  102.                      hideBottomBar();  
  103.                  } else {  //上滑显示  
  104.                      showBottomBar();  
  105.                  }  
  106.   
  107.                  bIsMoved = false;  
  108.                  break;  
  109.   
  110.          }  
  111.   
  112.         return super.onTouchEvent(ev);  
  113.     }  
  114.       
  115.       
  116.     private void action_down(float y){  
  117.           mMotionY = y;  
  118.           bIsDown = true;  
  119.           Log.d(TAG, "action down execed");  
  120.           mHandler.removeCallbacks(showBottomBarRunnable);  
  121.     }  
  122.   
  123.   
  124.     /** 
  125.      * 滑动到顶部时,要隐藏bottomView 
  126.      * @param view 
  127.      * @param scrollState 
  128.      */  
  129.     private void hideBottomViewOnScrollStateChanged(AbsListView view, int scrollState) {  
  130.         mCurrentScrollState = scrollState;  
  131.         if(view!=null){  
  132.              if (view.getFirstVisiblePosition() == 0 && scrollState == SCROLL_STATE_IDLE) {  
  133.                  hideBottomBar();  
  134.                  Log.d(TAG, "hide bottom view");  
  135.              }  
  136.         }  
  137.          
  138.   
  139.     }  
  140.   
  141.     /** 
  142.      * 显示底部浮动栏 
  143.      */  
  144.     public void showBottomBar() {  
  145.   
  146.         if (mBottomBar != null && mBottomBar.getVisibility() == View.GONE) {  
  147.             mBottomBar.setVisibility(View.INVISIBLE);  
  148.             Animation translateAnimation = new TranslateAnimation(mBottomBar.getLeft(), mBottomBar.getLeft(),300);  
  149.             translateAnimation.setDuration(300);  
  150.             translateAnimation.setInterpolator(new OvershootInterpolator(0.6f));  
  151.             mBottomBar.startAnimation(translateAnimation);  
  152.             translateAnimation.setAnimationListener(new Animation.AnimationListener() {  
  153.                 @Override  
  154.                 public void onAnimationStart(Animation animation) {  
  155.                 }  
  156.   
  157.                 @Override  
  158.                 public void onAnimationRepeat(Animation animation) {  
  159.                 }  
  160.   
  161.                 @Override  
  162.                 public void onAnimationEnd(Animation animation) {  
  163.                     mBottomBar.setVisibility(View.VISIBLE);  
  164.                 }  
  165.             });  
  166.         }  
  167.     }  
  168.   
  169.     /** 
  170.      * 隐藏浮动底部栏 
  171.      */  
  172.     private void hideBottomBar() {  
  173.   
  174.           
  175.         if (mBottomBar != null && mBottomBar.getVisibility() == View.VISIBLE) {  
  176.             Animation translateAnimation = new TranslateAnimation(mBottomBar.getLeft(), mBottomBar.getLeft(), 030);  
  177.             translateAnimation.setDuration(300);  
  178.             translateAnimation.setInterpolator(new OvershootInterpolator(0.6f));  
  179.             mBottomBar.startAnimation(translateAnimation);  
  180.             translateAnimation.setAnimationListener(new Animation.AnimationListener() {  
  181.                 @Override  
  182.                 public void onAnimationStart(Animation animation) {  
  183.                 }  
  184.   
  185.                 @Override  
  186.                 public void onAnimationRepeat(Animation animation) {  
  187.                 }  
  188.   
  189.                 @Override  
  190.                 public void onAnimationEnd(Animation animation) {  
  191.                     mBottomBar.setVisibility(View.GONE);  
  192.                 }  
  193.             });  
  194.         }  
  195.     }  
  196.   
  197.     /** 
  198.      * 滑动到底部时直接显示bottomView 
  199.      * @param visibleItemCount 
  200.      * @param totalItemCount 
  201.      * @param firstVisibleItem 
  202.      */  
  203.     private void showBottomViewOnBottom(int visibleItemCount, int totalItemCount, int firstVisibleItem) {  
  204.           
  205.             Log.d(TAG, "visible bottem item count:"  + "firstVisibleItem:" +  firstVisibleItem + "oldFirstVisibleItem:" + oldFirstVisibleItem + mBottomBar);  
  206.              if(getLastVisiblePosition() ==   totalItemCount -1 && mCurrentScrollState != SCROLL_STATE_IDLE){  
  207.                  showBottomBar();  
  208.              }  
  209.     }  
  210.   
  211.     private Runnable showBottomBarRunnable = new Runnable() {  
  212.   
  213.         @Override  
  214.         public void run() {  
  215.             showBottomBar();  
  216.         }  
  217.   
  218.     };  
  219.   
  220.   
  221.     /** 
  222.      * 将需要隐藏显示的view传入 
  223.      *  
  224.      * @param bottomBar 
  225.      */  
  226.     public void setBottomBar(ViewGroup bottomBar) {  
  227.         this.mBottomBar = bottomBar;  
  228.     }  
  229.   
  230. }  
  231.   
  232.   
  233.   
  234.   
  235. 上述代码中,重要和难理解的地方,都加了注释,很好理解。  

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

 

  1. package com.example.BottomFloatListView;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.view.View;  
  6. import android.view.ViewGroup;  
  7. import android.widget.ArrayAdapter;  
  8.   
  9. import java.util.ArrayList;  
  10. import java.util.List;  
  11.   
  12. public class MainActivity extends Activity {  
  13.     private  BottomFloatListView mBottomFloatListView;  
  14.   
  15.     @Override  
  16.     public void onCreate(Bundle savedInstanceState) {  
  17.         super.onCreate(savedInstanceState);  
  18.         setContentView(R.layout.main);  
  19.         mBottomFloatListView = (BottomFloatListView)findViewById(R.id.listView)  ;  
  20.         mBottomFloatListView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1,getData()));  
  21.         ViewGroup bottomView = (ViewGroup)findViewById(R.id.bottombar) ;  
  22.         mBottomFloatListView.setBottomBar(bottomView);  
  23.     }  
  24.   
  25.     private List<String> getData(){  
  26.   
  27.         List<String> data = new ArrayList<String>();  
  28.   
  29.         for(int i = 0; i <100; i++)      {  
  30.             data.add("测试数据" + i);  
  31.         }  
  32.   
  33.         return data;  
  34.   
  35.     }  
  36. }  


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

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


 

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

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

 

源代码下载:

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


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:192790次
    • 积分:2624
    • 等级:
    • 排名:第14878名
    • 原创:34篇
    • 转载:237篇
    • 译文:1篇
    • 评论:8条
    最新评论