zoukankan      html  css  js  c++  java
  • 抽屉Panel的研究

    大家对抽屉控件的第一反应就是系统提供的 如下:

     

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

    * 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>  

    * 运行截图:

     - 开

    - 合

  • 相关阅读:
    【2018.05.05 C与C++基础】C++中的自动废料收集:概念与问题引入
    【2018.04.27 C与C++基础】关于switch-case及if-else的效率问题
    【2018.04.19 ROS机器人操作系统】机器人控制:运动规划、路径规划及轨迹规划简介之一
    March 11th, 2018 Week 11th Sunday
    March 10th, 2018 Week 10th Saturday
    March 09th, 2018 Week 10th Friday
    March 08th, 2018 Week 10th Thursday
    March 07th, 2018 Week 10th Wednesday
    ubantu之Git使用
    AMS分析 -- 启动过程
  • 原文地址:https://www.cnblogs.com/xingmeng/p/2534869.html
Copyright © 2011-2022 走看看