編輯:Android開發實例
上次介紹了基礎篇,講解了自定義抽屜控件的基礎實現,這次就在基礎篇的基礎上加入拖拉功能。拖拉功能基於GestureDetector,GestureDetector的基本使用方式不是本文介紹的重點,有興趣的童鞋可以上網查詢相關的教程。
本文的抽屜控件相對於基礎篇的抽屜控件多了以下功能:
1.支持手勢拖拉
2.拖拉到一半時,可以自動展開或者收縮。
具體如下圖:
本文的源碼可以到這裡下載:http://download.csdn.net/detail/hellogv/3642418
只貼出抽屜組件的源碼,其他源文件與基礎篇的一樣:
- public class Panel extends LinearLayout implements GestureDetector.OnGestureListener{
- public interface PanelClosedEvent {
- void onPanelClosed(View panel);
- }
- public interface PanelOpenedEvent {
- void onPanelOpened(View panel);
- }
- private final static int HANDLE_WIDTH=30;
- private final static int MOVE_WIDTH=20;
- private Button btnHandler;
- private LinearLayout panelContainer;
- private int mRightMargin=0;
- private Context mContext;
- private GestureDetector mGestureDetector;
- private boolean mIsScrolling=false;
- private float mScrollX;
- private PanelClosedEvent panelClosedEvent=null;
- private PanelOpenedEvent panelOpenedEvent=null;
- public Panel(Context context,View otherView,int width,int height) {
- super(context);
- this.mContext=context;
- //定義手勢識別
- mGestureDetector = new GestureDetector(mContext,this);
- mGestureDetector.setIsLongpressEnabled(false);
- //改變Panel附近組件的屬性
- LayoutParams otherLP=(LayoutParams) otherView.getLayoutParams();
- otherLP.weight=1;
- otherView.setLayoutParams(otherLP);
- //設置Panel本身的屬性
- LayoutParams lp=new LayoutParams(width, height);
- lp.rightMargin=-lp.width+HANDLE_WIDTH;
- mRightMargin=Math.abs(lp.rightMargin);
- this.setLayoutParams(lp);
- this.setOrientation(LinearLayout.HORIZONTAL);
- //設置Handler的屬性
- btnHandler=new Button(context);
- btnHandler.setLayoutParams(new LayoutParams(HANDLE_WIDTH,height));
- //btnHandler.setOnClickListener(handlerClickEvent);
- btnHandler.setOnTouchListener(handlerTouchEvent);
- this.addView(btnHandler);
- //設置Container的屬性
- panelContainer=new LinearLayout(context);
- panelContainer.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
- LayoutParams.FILL_PARENT));
- this.addView(panelContainer);
- }
- private View.OnTouchListener handlerTouchEvent=new View.OnTouchListener() {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if(event.getAction()==MotionEvent.ACTION_UP && //onScroll時的ACTION_UP
- mIsScrolling==true)
- {
- LayoutParams lp=(LayoutParams) Panel.this.getLayoutParams();
- if (lp.rightMargin >= (-mRightMargin/2)) {//往左超過一半
- new AsynMove().execute(new Integer[] { MOVE_WIDTH });// 正數展開
- }
- else if (lp.rightMargin < (-mRightMargin/2)) {//往右拖拉
- new AsynMove().execute(new Integer[] { -MOVE_WIDTH });// 負數收縮
- }
- }
- return mGestureDetector.onTouchEvent(event);
- }
- };
- /**
- * 定義收縮時的回調函數
- * @param event
- */
- public void setPanelClosedEvent(PanelClosedEvent event)
- {
- this.panelClosedEvent=event;
- }
- /**
- * 定義展開時的回調函數
- * @param event
- */
- public void setPanelOpenedEvent(PanelOpenedEvent event)
- {
- this.panelOpenedEvent=event;
- }
- /**
- * 把View放在Panel的Container
- * @param v
- */
- public void fillPanelContainer(View v)
- {
- panelContainer.addView(v);
- }
- /**
- * 異步移動Panel
- * @author hellogv
- */
- class AsynMove extends AsyncTask<Integer, Integer, Void> {
- @Override
- protected Void doInBackground(Integer... params) {
- int times;
- if (mRightMargin % Math.abs(params[0]) == 0)// 整除
- times = mRightMargin / Math.abs(params[0]);
- else
- // 有余數
- times = mRightMargin / Math.abs(params[0]) + 1;
- for (int i = 0; i < times; i++) {
- publishProgress(params);
- try {
- Thread.sleep(Math.abs(params[0]));
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- return null;
- }
- @Override
- protected void onProgressUpdate(Integer... params) {
- LayoutParams lp = (LayoutParams) Panel.this.getLayoutParams();
- if (params[0] < 0)
- lp.rightMargin = Math.max(lp.rightMargin + params[0],
- (-mRightMargin));
- else
- lp.rightMargin = Math.min(lp.rightMargin + params[0], 0);
- if(lp.rightMargin==0 && panelOpenedEvent!=null){//展開之後
- panelOpenedEvent.onPanelOpened(Panel.this);//調用OPEN回調函數
- }
- else if(lp.rightMargin==-(mRightMargin) && panelClosedEvent!=null){//收縮之後
- panelClosedEvent.onPanelClosed(Panel.this);//調用CLOSE回調函數
- }
- Panel.this.setLayoutParams(lp);
- }
- }
- @Override
- public boolean onDown(MotionEvent e) {
- mScrollX=0;
- mIsScrolling=false;
- return false;
- }
- @Override
- public boolean onSingleTapUp(MotionEvent e) {
- LayoutParams lp = (LayoutParams) Panel.this.getLayoutParams();
- if (lp.rightMargin < 0)// CLOSE的狀態
- new AsynMove().execute(new Integer[] { MOVE_WIDTH });// 正數展開
- else if (lp.rightMargin >= 0)// OPEN的狀態
- new AsynMove().execute(new Integer[] { -MOVE_WIDTH });// 負數收縮
- return false;
- }
- @Override
- public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
- float distanceY) {
- mIsScrolling=true;
- mScrollX+=distanceX;
- LayoutParams lp=(LayoutParams) Panel.this.getLayoutParams();
- if (lp.rightMargin < -1 && mScrollX > 0) {//往左拖拉
- lp.rightMargin = Math.min((lp.rightMargin + (int) mScrollX),0);
- Panel.this.setLayoutParams(lp);
- Log.e("onScroll",lp.rightMargin+"");
- }
- else if (lp.rightMargin > -(mRightMargin) && mScrollX < 0) {//往右拖拉
- lp.rightMargin = Math.max((lp.rightMargin + (int) mScrollX),-mRightMargin);
- Panel.this.setLayoutParams(lp);
- }
- if(lp.rightMargin==0 && panelOpenedEvent!=null){//展開之後
- panelOpenedEvent.onPanelOpened(Panel.this);//調用OPEN回調函數
- }
- else if(lp.rightMargin==-(mRightMargin) && panelClosedEvent!=null){//收縮之後
- panelClosedEvent.onPanelClosed(Panel.this);//調用CLOSE回調函數
- }
- Log.e("onScroll",lp.rightMargin+"");
- return false;
- }
- @Override
- public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
- float velocityY) {return false;}
- @Override
- public void onLongPress(MotionEvent e) {}
- @Override
- public void onShowPress(MotionEvent e) {}
- }
登錄應用程序的屏幕,詢問憑據登錄到一些特定的應用。可能需要登錄到Facebook,微博等本章介紹了,如何創建一個登錄界面,以及如何管理安全問題和錯誤嘗試。首先,必須定義兩
本文實例講述了Android編程實現監聽EditText變化的方法。分享給大家供大家參考,具體如下: 監聽EditText中的內容的變化。在EditText沒有找
可以顯示在的Android任務,通過加載進度條的進展。進度條有兩種形狀。加載欄和加載微調(spinner)。在本章中,我們將討論微調(spinner)。Spinner 用
可以顯示在的Android任務,通過加載進度條的進展。進度條有兩種形狀。加載欄和加載微調(spinner)。在本章中,我們將討論微調(spinner)。Spinner 用