最近項目中需要實現上拉功能,首先想到的就是Android本身內建的抽屜SlidingDrawer,最後也實現了不過,出現的問題就是設定背景色問題,handler和content是兩個不同的部分,這就造成圖片要做成兩部分,從而產生兩個部分圖片看起來不是一個整體,而且我這個上拉功能,裡面要實現一個水平滾動功能,而SlidingDrawer還有其他的限制,同時官方給出api 17以後,這個功能已經廢棄,所以自己自定這樣一個上拉功能是必須的。
這裡我是繼承LinearLayout同時實現GestureDetector.OnGestureListener來實現上拉功能。下面是代碼:
package com.example.test;import android.content.Context;import android.os.AsyncTask;import android.util.AttributeSet;import android.view.GestureDetector;import android.view.MotionEvent;import android.widget.LinearLayout;import android.widget.RelativeLayout;public class PanelBom extends LinearLayout implements GestureDetector.OnGestureListener{GestureDetector mGesture = null;private boolean isScrolling = false;private int MAX_HEIGHT = 80;//拖動的最大高度,當前布局位於父布局下面-80位置,這個僅僅是調試參數,這個變數是動態設定的。private float mScrollX; // 滑塊滑動距離public PanelBom(Context context) {super(context);init();}public PanelBom(Context context, AttributeSet attrs) {super(context, attrs);init();}//初始化一些參數public void init(){mGesture = new GestureDetector(this);mGesture.setIsLongpressEnabled(false);setBackgroundResource(R.drawable.button_bar);}@Overridepublic boolean onTouchEvent(MotionEvent event) {if (MotionEvent.ACTION_UP == event.getAction() && isScrolling == true) {RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)getLayoutParams();// 縮回去if (layoutParams.bottomMargin < -MAX_HEIGHT / 2) {new AsynMove().execute(-20);//負--往下} else {new AsynMove().execute(20);//正--往上}}return mGesture.onTouchEvent(event);}//Touch down時觸發 @Overridepublic boolean onDown(MotionEvent e) {mScrollX = 0;isScrolling = false;// 將之改為true,不然事件不會向下傳遞.return true;}//Touch了還沒有滑動時觸發 @Overridepublic void onShowPress(MotionEvent e) {}@Overridepublic boolean onSingleTapUp(MotionEvent e) {RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();// 說明在上面,要往下if (layoutParams.bottomMargin >= 0) {new AsynMove().execute(-20);//負--往下} else {new AsynMove().execute(20);//正--往上}return true;}//Touch了滑動時觸發@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,float distanceY) {isScrolling = true;mScrollX += distanceY;RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)getLayoutParams();layoutParams.bottomMargin += mScrollX;if (layoutParams.bottomMargin >= 0) {isScrolling = false;// 拖過頭了不需要再執行AsynMove了layoutParams.bottomMargin = 0;} else if (layoutParams.bottomMargin <= -MAX_HEIGHT) {// 拖過頭了不需要再執行AsynMove了isScrolling = false;layoutParams.bottomMargin = -MAX_HEIGHT;}setLayoutParams(layoutParams);return false;}//Touch了不移動一直Touch down時觸發 @Overridepublic void onLongPress(MotionEvent e) {}//Touch了滑動一點距離後,up時觸發。@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {return false;}//非同步更新布局的位置class AsynMove extends AsyncTask<Integer, Integer, Void> {@Overrideprotected Void doInBackground(Integer... params) {int times = 0;int divi = Math.abs(params[0]);if (MAX_HEIGHT % divi == 0)// 整除times = MAX_HEIGHT / Math.abs(params[0]);elsetimes = MAX_HEIGHT / divi + 1;// 有餘數for (int i = 0; i < times; i++) {publishProgress(params[0]);try {Thread.sleep(divi);} catch (InterruptedException e) {e.printStackTrace();}}return null;}@Overrideprotected void onProgressUpdate(Integer... values) {RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();if (values[0] < 0) {layoutParams.bottomMargin = Math.max(layoutParams.bottomMargin + values[0], -MAX_HEIGHT);} else {layoutParams.bottomMargin = Math.min(layoutParams.bottomMargin + values[0], 0);}setLayoutParams(layoutParams);super.onProgressUpdate(values);}}}
主介面:
package com.example.test;import android.app.Activity;import android.os.Bundle;import android.widget.RelativeLayout;public class Main5 extends Activity{RelativeLayout Parent;PanelBom panelBom;RelativeLayout.LayoutParams parentParams;RelativeLayout.LayoutParams paneBomParams;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Parent = new RelativeLayout(getApplicationContext());panelBom = new PanelBom(getApplicationContext());parentParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);paneBomParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, 150);paneBomParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);paneBomParams.bottomMargin = -80;Parent.addView(panelBom, paneBomParams);setContentView(Parent, parentParams);}}
實現的效果是:
拖拉,點擊實現上拉功能,如下: