標籤:android 菜單 可複用控制項 仿qq菜單
在上一篇《Android開發技巧——使用Dialog實現仿QQ的ActionSheet菜單》中,講了這種菜單的實現過程,接下來將把它改成一個可複用的控制項陳列庫。
本文原創,轉載請註明出處:
http://blog.csdn.net/maosidiaoxian/article/details/46324941
對於要實現的可複用的控制項陳列庫,我需要它具備以下兩點:
- 可添加遠程依賴(不考慮Eclipse中的使用)
- 可靈活配置
分離庫的實現代碼
對於第一點,需要做的就是在Android Studio中建立一個library的module,然後把相關的實現代碼,資源分離出來拖過去,並且把library中標,一些字串等沒有用到的資源刪掉,保持AndroidManifest.xml的乾淨(僅保留會用到的許可權,聲明等)。在這裡,我們library的AndroidManifest最終只剩下了:
<manifest package="com.githang.android.actionsheet"> <application/></manifest>
注意,application節點裡 的allowBackup屬性要去掉,不然會讓一些不知道怎麼用tools中的幾個屬性來解決衝突的人,面對AndroidManifest.xml的合并衝突不知所措。label和icon屬性在這裡也不需要,所以也去掉了。
然後把一開始建立的app module的包名加上.demo尾碼,把com.githang.andorid.actionsheet僅作為我們的library的包名(這個是純屬個人習慣,你也可以不這麼做。我是覺得在包名上把library和demo區分來比較好,而我又不想給library加多一個.library的包。
分離完之後的項目是這樣的:
https://github.com/msdx/ActionSheet/commit/934b73bc3e2d1504c9b13e87649ce388c59f4613
分離之後,就可以把我們的庫打包成aar,並上傳到jcenter,讓別人能以添加遠程依賴的方式來使用了。如何發布到jcenter,可以見我這篇部落格:《使用Gradle發布Android開源項目到JCenter》。
但是現在,我們僅完成的最基本的工作,因為,你不能要求每個人對一個庫的要求都和你完全一樣,可能有些人的需求中,需要改一下UI上的一些屬性什麼的。所以接下來,我們需要讓我們的庫能夠靈活配置。
可自由配置的屬性
我們的大部分屬性是定義在xml中的。要改動這些屬性,方法主要有兩種:
1. 在Java代碼中提供一些View的UI上的介面,讓第三方通過調用它來設定。
2. 布局檔案中使用屬性的引用,而不是直接使用它的值。
如果你寫的是自訂控制項(通過繼承View),那麼你可能還需要自訂一些屬性,讓別人在使用的時候可以在xml中添加。由於這裡我們寫的不是這類控制項,不需要用到它,在這裡就不贅述了。
繼續說上面的兩種方法。Android中,採用xml定義布局,就是想讓布局代碼與邏輯代碼相分離,所以第一種方式我是盡量少用的(在需要動態設定,或者是在Java代碼中設定更簡單時使用,)。下面先說一下第二種的方式的實現過程。
我們在xml中定義到的控制項有三個,一是ListView,二是Button,三是ListView的Item。所以首先,在values檔案夾裡建立一個attrs.xml的屬性檔案,在裡面分別定義三個屬性,format是reference。如下:
<?xml version="1.0" encoding="utf-8"?><resources> <attr name="ActionSheetList" format="reference"/> <attr name="ActionSheetCancel" format="reference"/> <attr name="ActionSheetItem" format="reference"/></resources>
接著,把之前寫的布局檔案改為使用?attr的方式聲明屬性。
menu_item.xml
<?xml version="1.0" encoding="utf-8"?><TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1" style="?attr/ActionSheetItem" />
dialog_action_sheet.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ListView android:id="@+id/menu_items" android:layout_width="match_parent" android:layout_height="wrap_content" style="?attr/ActionSheetList" android:listSelector="@android:color/transparent"/> <Button android:id="@+id/menu_cancel" style="?attr/ActionSheetCancel"/></LinearLayout>
然後在我們的style中聲明這幾個屬性的style:
<style name="ActionSheetList"> <item name="android:divider">#c9dddddd</item> <item name="android:dividerHeight">1px</item> </style> <style name="ActionSheetItem"> <item name="android:layout_width">match_parent</item> <item name="android:layout_height">45dp</item> <item name="android:textSize">18sp</item> <item name="android:gravity">center</item> <item name="android:textColor">@color/menu_text</item> </style> <style name="ActionSheetCancel" parent="ActionSheetItem"> <item name="android:layout_marginTop">8dp</item> <item name="android:layout_marginBottom">8dp</item> <item name="android:background">@drawable/menu_item_single</item> </style>
注意,這裡的style的名稱並不要求與attr中聲明的名稱一致,這裡我只是懶得想其他名字,真的。
這樣做了之後,其他人在使用的時候,會需要多一個步驟:在他的styler中的AppTheme(具體視androidmanifest中指定的theme而定)節點中,需要添加以下幾項:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="ActionSheetList">@style/ActionSheetList</item> <item name="ActionSheetItem">@style/ActionSheetItem</item> <item name="ActionSheetCancel">@style/ActionSheetCancel</item> </style>
如果他想自己修改屬性的值,只需要寫對應的style,然後把上面的item裡的值改為他寫的style即可。
對於菜單的改動,我們就改到這裡。
接下來是對ActionSheetDialog的重構,讓它提供可以進行以下設定的API:
首先是菜單的背景,上文已經說過它一共有四個背景。所以定義一個菜單背景的類:
/** * 菜單背景 */ public static class MenuBackground { public int top; public int middle; public int bottom; public int single; public MenuBackground() {} public MenuBackground(int top, int middle, int bottom, int single) { this.top = top; this.middle = middle; this.bottom = bottom; this.single = single; } }
然後定義一個菜單背景的對象,給它初始值,並定義一個設定背景的方法:
private MenuBackground mMenuBg = new MenuBackground(R.drawable.menu_item_top, R.drawable.menu_item_middle, R.drawable.menu_item_bottom, R.drawable.menu_item_single); public void setMenuBackground(int top, int middle, int bottom, int single) { mMenuBg.top = top; mMenuBg.middle = middle; mMenuBg.bottom = bottom; mMenuBg.single = single; }
最後剩下動畫的配置的。定義分別設定顯示及隱藏動畫的兩個方法,注意,對隱藏動畫的方法中,要設定動畫結束的回調,在這裡隱藏我們的菜單。
動畫設定的代碼重構如下:
private void initAnim(Context context) { setShowAnimation(AnimationUtils.loadAnimation(context, R.anim.translate_up)); setDismissAnimation(AnimationUtils.loadAnimation(context, R.anim.translate_down)); } /** * @param animation Showing animation. * @since 0.2 */ public void setShowAnimation(Animation animation) { mShowAnim = animation; } /** * @param animation Dismissing animation. * @since 0.2 */ public void setDismissAnimation(Animation animation) { mDismissAnim = animation; mDismissAnim.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { dismissMe(); } @Override public void onAnimationRepeat(Animation animation) { } }); }
現在我們的庫已經重構完了,它暴露了適當的API,以讓其他人可以自訂一些屬性。它也對布局檔案的配置提供了方法,即通過style來進行配置。
最後就是升版本號碼,改README,發布新版本了,打TAG了。
項目最後如下:
https://github.com/msdx/ActionSheet/tree/0.2
Android開發技巧——實現可複用的ActionSheet菜單