抽屉 Panel 研究

来源:互联网 发布:知乎怎么提问提交不了 编辑:程序博客网 时间:2024/05/17 20:37

android默认抽屉效果

 

其实 该控件的原理说白了 很简单 即:

* ViewGroup 如:LinearLayout 用于放置各种View

* Button 用于 展开/收起 ViewGroup

 

所以该控件的大致布局应如下:

 

Java代码 复制代码
  1. <Panel>   
  2.   
  3. <Button />   
  4.   
  5. <LinearLayout >   
  6.     <TextView />   
  7.     <ImageView />   
  8. </LinearLayout>   
  9.   
  10. </Panel>  

 

 

为了降低开发难度 我打算 定义 Panel extends LinearLayout

 

 

[代码 步骤]

 

1. 定义一些XML用到的属性

Xml代码 复制代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.     <declare-styleable name="Panel">  
  4.          //动画演变时长   
  5.         <attr name="animationDuration" format="integer" />  
  6.         //摆放位置 只能取下面的4个值   
  7.         <attr name="position">  
  8.             <enum name="top" value="0" />  
  9.             <enum name="bottom" value="1" />  
  10.             <enum name="left" value="2" />  
  11.             <enum name="right" value="3" />  
  12.         </attr>  
  13.         //开合是否有动画效果   
  14.         <attr name="animationEnable" format="boolean" />  
  15.     </declare-styleable>  
  16.   
  17. </resources>  

 

 

2. 一个标准的XML为:

Xml代码 复制代码
  1. <org.panel.Panel  
  2.             android:id="@+id/leftPanel"    
  3.             android:layout_width="wrap_content"    
  4.             android:layout_height="wrap_content"    
  5.             panel:position="left"  
  6.             panel:animationDuration="10"  
  7.             panel:animationEnable="true"  
  8.             android:layout_gravity="left"  
  9.         >  
  10.             <Button  
  11.                 android:layout_width="wrap_content"    
  12.                 android:layout_height="wrap_content"    
  13.             />  
  14.             <LinearLayout  
  15.                 android:orientation="vertical"  
  16.                 android:layout_width="wrap_content"  
  17.                 android:layout_height="wrap_content"  
  18.             >  
  19.                 <CheckBox  
  20.                     android:layout_width="fill_parent"    
  21.                     android:layout_height="wrap_content"    
  22.                     android:text="Top Panel!"  
  23.                     android:textSize="16dip"  
  24.                     android:textColor="#eee"  
  25.                     android:textStyle="bold"  
  26.                 />  
  27.                 <EditText  
  28.                     android:layout_width="200dip"    
  29.                     android:layout_height="wrap_content"    
  30.                 />  
  31.                 <Button  
  32.                     android:layout_width="100dp"    
  33.                     android:layout_height="wrap_content"    
  34.                     android:text="OK!"  
  35.                 />  
  36.             </LinearLayout>  
  37.         </org.panel.Panel>  

 

 

3. 解析该XML 并设置之

Java代码 复制代码
  1. public Panel(Context context, AttributeSet attrs) {   
  2.         super(context, attrs);   
  3.            
  4.         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Panel);   
  5.            
  6.         mDuration = a.getInteger(R.styleable.Panel_animationDuration, 750);   
  7.         mPosition = a.getInteger(R.styleable.Panel_position, BOTTOM);   
  8.         isAnimation = a.getBoolean(R.styleable.Panel_animationEnable, true);   
  9.         a.recycle();   
  10.            
  11.         //根据mPosition 决定LinearLayout的android:orientation属性   
  12.         mOrientation = (mPosition == TOP || mPosition == BOTTOM)? VERTICAL : HORIZONTAL;   
  13.         setOrientation(mOrientation);   
  14.            
  15.         //初始化mHandle 背景图   
  16.         initialHandlerBg();   
  17.            
  18.     }  

 

 

4. 设定Button 背景图

Java代码 复制代码
  1. //设置mHandle所用背景图       
  2.     private void initialHandlerBg(){   
  3.         if(mPosition == TOP){   
  4.             mOpenedHandle = getResources().getDrawable(R.drawable.top_switcher_expanded_background);   
  5.             mClosedHandle = getResources().getDrawable(R.drawable.top_switcher_collapsed_background);   
  6.            
  7.         }   
  8.         else if(mPosition == BOTTOM) {   
  9.             mOpenedHandle = getResources().getDrawable(R.drawable.bottom_switcher_expanded_background);   
  10.             mClosedHandle = getResources().getDrawable(R.drawable.bottom_switcher_collapsed_background);   
  11.            
  12.         }   
  13.         else if(mPosition == LEFT) {   
  14.             mOpenedHandle = getResources().getDrawable(R.drawable.left_switcher_expanded_background);   
  15.             mClosedHandle = getResources().getDrawable(R.drawable.left_switcher_collapsed_background);   
  16.            
  17.         }   
  18.         else if(mPosition == RIGHT) {   
  19.             mOpenedHandle = getResources().getDrawable(R.drawable.right_switcher_expanded_background);   
  20.             mClosedHandle = getResources().getDrawable(R.drawable.right_switcher_collapsed_background);   
  21.            
  22.         }   
  23.     }  

 

 

5. 取出其中的 ViewGroup & Button

Java代码 复制代码
  1. //回调函数 界面初始化快结束时调用 用于得到 mHandle/mContent   
  2.     protected void onFinishInflate() {   
  3.         super.onFinishInflate();   
  4.            
  5.         //得到mHandle实例   
  6.         mHandle = this.getChildAt(0);   
  7.            
  8.         if (mHandle == null) {   
  9.             throw new RuntimeException("Your Panel must have a View - mHandle");   
  10.         }   
  11.            
  12.         mHandle.setOnClickListener(clickListener);   
  13.            
  14.         //得到mContent实例   
  15.         mContent = this.getChildAt(1);   
  16.         if (mContent == null) {   
  17.             throw new RuntimeException("Your Panel must have a View - mContent");   
  18.         }   
  19.   
  20.            
  21.         //先移除mHandle/mContent 然后根据position决定二者的添加次序   
  22.         removeView(mHandle);   
  23.         removeView(mContent);   
  24.         if (mPosition == TOP || mPosition == LEFT) {   
  25.             addView(mContent);   
  26.             addView(mHandle);   
  27.         } else {   
  28.             addView(mHandle);   
  29.             addView(mContent);   
  30.         }   
  31.   
  32.         if (mClosedHandle != null) {   
  33.             mHandle.setBackgroundDrawable(mClosedHandle);   
  34.         }   
  35.            
  36.         //隐藏 mContent   
  37.         mContent.setVisibility(GONE);   
  38.     }  

 

6. 得到ViewGroup 宽度/高度 以决定动画演变范围

   注意其位置 并非放在开始地方 因为那时候返回值都是0

 

Java代码 复制代码
  1. @Override //回调函数 此时其内所有子View 宽度/高度 都已确定   
  2.     protected void onLayout(boolean changed, int l, int t, int r, int b) {   
  3.         super.onLayout(changed, l, t, r, b);   
  4.            
  5.         mContentWidth = mContent.getWidth();   
  6.         mContentHeight = mContent.getHeight();   
  7.            
  8.         paddingTop = this.getPaddingTop();   
  9.         paddingLeft = this.getPaddingLeft();   
  10.     }  

 

 

7.  定义Button 响应事情 执行 开合ViewGroup

Java代码 复制代码
  1. // 定义mHandle监听器 用于开合mContent   
  2.     OnClickListener clickListener = new OnClickListener(){   
  3.         public void onClick(View v) {   
  4.                 // TODO Auto-generated method stub   
  5.             if(!isContentExpand){   
  6.                 open();   
  7.             }   
  8.             else {   
  9.                 close();   
  10.             }   
  11.                
  12.             //置反 即:开-合-开-合-开-...   
  13.             isContentExpand = !isContentExpand;   
  14.         }   
  15.     };  

 

 

8. 定义开合的回调函数 具体效果 见:setOnClickListener(OnClickListener listener)

Java代码 复制代码
  1. //回调函数 用于监听 Panel 的开合 效果见:setOnClickLstener(OnClickListener listener)   
  2.     public static interface OnPanelListener {   
  3.         //- open   
  4.         public void onPanelOpened(Panel panel);   
  5.            
  6.         //- close   
  7.         public void onPanelClosed(Panel panel);   
  8.     }  

 

 

10. 开 即: 打开ViewGroup

Java代码 复制代码
  1. public void open(){   
  2.         if(isAnimation){   
  3.             doAnimationOpen();   
  4.         }   
  5.         else {   
  6.             doOpen();   
  7.         }   
  8.            
  9.     }   
  10.     public void doOpen(){   
  11.         mContent.setVisibility(VISIBLE);   
  12.            
  13.     }   
  14.        
  15.     public void doAnimationOpen(){   
  16.         mContent.setVisibility(VISIBLE);   
  17.         post(aOpen);   
  18.     }  

 

11. 定义开的Animation

Java代码 复制代码
  1. //- open   
  2.     Runnable aOpen = new Runnable() {   
  3.         public void run() {   
  4.             TranslateAnimation animation;   
  5.             int fromXDelta = 0, toXDelta = 0, fromYDelta = 0, toYDelta = 0;   
  6.             int calculatedDuration = 0;   
  7.                
  8.             if(mPosition == TOP){   
  9.                 fromYDelta = -1 * mContentHeight;   
  10.                 toXDelta = 0;   
  11.                    
  12.                 calculatedDuration = mDuration * Math.abs(toYDelta - fromYDelta) / mContentHeight;   
  13.             }   
  14.             else if(mPosition == BOTTOM){   
  15.                 fromYDelta = paddingTop;   
  16.                 toYDelta = fromYDelta + 1 * mContentHeight;   
  17.                    
  18.                 calculatedDuration = mDuration * Math.abs(toYDelta - fromYDelta) / mContentHeight;   
  19.             }   
  20.             else if(mPosition == LEFT){   
  21.                 fromXDelta = -1 * mContentWidth;   
  22.                 toXDelta = 0;   
  23.                    
  24.                 calculatedDuration = mDuration * Math.abs(toXDelta - fromXDelta) / mContentWidth;   
  25.             }   
  26.             else if(mPosition == RIGHT){   
  27.                 fromXDelta = paddingLeft;   
  28.                 toXDelta = fromYDelta + 1 * mContentHeight;   
  29.                    
  30.                 calculatedDuration = mDuration * Math.abs(toYDelta - fromYDelta) / mContentHeight;   
  31.             }   
  32.                
  33.             animation = new TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelta);   
  34.             animation.setDuration(calculatedDuration);   
  35.             animation.setAnimationListener(aOListener);   
  36.   
  37.             startAnimation(animation);   
  38.         }   
  39.     };  

 

 

12. 合 即:关闭ViewGroup

Java代码 复制代码
  1. public void close(){   
  2.         if(isAnimation){   
  3.             doAnimationClose();   
  4.         }   
  5.         else {   
  6.             doClose();   
  7.         }   
  8.     }   
  9.     public void doClose(){   
  10.         mContent.setVisibility(GONE);   
  11.            
  12.     }   
  13.     public void doAnimationClose(){   
  14.         post(aClose);   
  15.            
  16.     }  

 

13. 定义合的Animation

Java代码 复制代码
  1. //- close   
  2.     Runnable aClose = new Runnable() {   
  3.         public void run() {   
  4.             TranslateAnimation animation;   
  5.             int fromXDelta = 0, toXDelta = 0, fromYDelta = 0, toYDelta = 0;   
  6.             int calculatedDuration = 0;   
  7.                
  8.             if(mPosition == TOP){   
  9.                 toYDelta = -1 * mContentHeight;   
  10.                    
  11.                 calculatedDuration = mDuration * Math.abs(toYDelta - fromYDelta) / mContentHeight;   
  12.             }   
  13.             else if(mPosition == BOTTOM){   
  14.                 fromYDelta = 1 *  mContentHeight;   
  15.                 toYDelta = paddingTop;   
  16.                    
  17.                 calculatedDuration = mDuration * Math.abs(toYDelta - fromYDelta) / mContentHeight;   
  18.             }   
  19.             else if(mPosition == LEFT){   
  20.                 toXDelta = -1 * mContentWidth;   
  21.                    
  22.                 calculatedDuration = mDuration * Math.abs(toXDelta - fromXDelta) / mContentWidth;   
  23.             }   
  24.             else if(mPosition == RIGHT){   
  25.                    
  26.             }   
  27.                
  28.             animation = new TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelta);   
  29.             animation.setDuration(calculatedDuration);   
  30.             animation.setAnimationListener(aCListener);   
  31.                
  32.             startAnimation(animation);   
  33.         }   
  34.     };  

 

 

14. 定义二者Animation 的回调函数 即:结束后 更改Button背景图 通知OnPanelListener

Java代码 复制代码
  1. //善后工作 比如:改变mHandle背景图 通知开合监听器   
  2.     private void postProcess() {   
  3.         // to update mHandle 's background    
  4.         if (!isContentExpand ) {   
  5.             mHandle.setBackgroundDrawable(mClosedHandle);   
  6.         }    
  7.         else {   
  8.             mHandle.setBackgroundDrawable(mOpenedHandle);   
  9.         }   
  10.            
  11.         // invoke listener if any   
  12.         if (panelListener != null) {   
  13.             if (isContentExpand) {   
  14.                 panelListener.onPanelOpened(Panel.this);   
  15.             }   
  16.             else {   
  17.                 panelListener.onPanelClosed(Panel.this);   
  18.             }   
  19.         }   
  20.     }  

 

 

15. emulator 运行截图:

* 先贴其布局

Xml代码 复制代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2.   
  3. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  4.     xmlns:panel="http://schemas.android.com/apk/res/org.panel"  
  5.     android:layout_width="fill_parent"  
  6.     android:layout_height="fill_parent"  
  7.     android:orientation="vertical"  
  8. >  
  9.   
  10.         <org.panel.Panel  
  11.             android:id="@+id/leftPanel"    
  12.             android:layout_width="wrap_content"    
  13.             android:layout_height="wrap_content"    
  14.             panel:position="left"  
  15.             panel:animationDuration="10"  
  16.             panel:animationEnable="true"  
  17.             android:layout_gravity="left"  
  18.         >  
  19.             <Button  
  20.                 android:layout_width="wrap_content"    
  21.                 android:layout_height="wrap_content"    
  22.             />  
  23.             <LinearLayout  
  24.                 android:orientation="vertical"  
  25.                 android:layout_width="wrap_content"  
  26.                 android:layout_height="wrap_content"  
  27.             >  
  28.                 <CheckBox  
  29.                     android:layout_width="fill_parent"    
  30.                     android:layout_height="wrap_content"    
  31.                     android:text="Top Panel!"  
  32.                     android:textSize="16dip"  
  33.                     android:textColor="#eee"  
  34.                     android:textStyle="bold"  
  35.                 />  
  36.                 <EditText  
  37.                     android:layout_width="200dip"    
  38.                     android:layout_height="wrap_content"    
  39.                 />  
  40.                 <Button  
  41.                     android:layout_width="100dp"    
  42.                     android:layout_height="wrap_content"    
  43.                     android:text="OK!"  
  44.                 />  
  45.             </LinearLayout>  
  46.         </org.panel.Panel>  
  47.            
  48.         <org.panel.Panel  
  49.             android:id="@+id/rightPanel"    
  50.             android:layout_width="wrap_content"    
  51.             android:layout_height="wrap_content"    
  52.             panel:position="right"  
  53.             panel:animationDuration="10"  
  54.             panel:animationEnable="true"  
  55.             android:layout_gravity="right"  
  56.         >  
  57.             <Button  
  58.                 android:layout_width="wrap_content"    
  59.                 android:layout_height="wrap_content"    
  60.             />  
  61.             <LinearLayout  
  62.                 android:orientation="vertical"  
  63.                 android:layout_width="wrap_content"  
  64.                 android:layout_height="wrap_content"  
  65.             >  
  66.                 <ImageView  
  67.                     android:layout_width="wrap_content"    
  68.                     android:layout_height="wrap_content"    
  69.                     android:src="@drawable/beijing4_b"  
  70.                 />  
  71.             </LinearLayout>  
  72.         </org.panel.Panel>  
  73.            
  74.         <LinearLayout  
  75.             android:layout_width="fill_parent"    
  76.             android:layout_height="wrap_content"    
  77.             android:orientation="vertical"    
  78.             >  
  79.             <TextView  
  80.                 android:layout_width="fill_parent"    
  81.                 android:layout_height="wrap_content"    
  82.                 android:textSize="16dip"  
  83.                 android:textColor="#ddd"  
  84.                 android:text="other area!!!!!!!!"  
  85.             />  
  86.             <Button  
  87.                     android:id="@+id/button"  
  88.                     android:layout_width="100dp"    
  89.                     android:layout_height="wrap_content"    
  90.                     android:text="Yes!"  
  91.                 />  
  92.         </LinearLayout>  
  93.            
  94.            
  95. </LinearLayout>  

 

 

原创粉丝点击