`

可动态布局的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) {}  
  
}

 

 

本文来自http://blog.csdn.net/hellogv/article/details/6828584

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics