Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> ListView分割線

ListView分割線

編輯:關於Android編程

重新定義分割線Drawable的Bounds

首先,需要清楚一個事實:出現以上情況的矛盾點,是官方ListView的分割線屬性不支持左右留白。所以最佳的解決方案,就是使得官方的分割線支持這種功能,這樣既利於擴展,也利於提高性能。

先來簡單看一下,ListView的源碼是如何實現分割線的功能的。

    void drawDivider(Canvas canvas, Rect bounds, int childIndex) {
        // This widget draws the same divider for all children
        final Drawable divider = mDivider;

        divider.setBounds(bounds);
        divider.draw(canvas);
    }

在onDraw方法中,最終會調用到drawDivider方法。由於分割線是一個Drawable對象,上下左右的位置都是由Rect對象控制的,這個對象通過setBounds方法設置。

這個Rect對象的top和bottom屬性我們是不需要關心的,只需要看left和right兩個屬性,默認情況下left=paddingLeft,right=width-paddingLeft-paddingRight,即表示分割線的起點和終點貫穿ListView的左右兩側。

dispatchDraw方法中可以驗證這一點:

 protected void dispatchDraw(Canvas canvas) {
    ...
    if (drawDividers || drawOverscrollHeader || drawOverscrollFooter) {
        final Rect bounds = mTempRect;
        bounds.left = mPaddingLeft;
        bounds.right = mRight - mLeft - mPaddingRight;
        ...
        drawDivider(canvas, bounds, i);
    }
    ...
 }

如果我們能將bounds的left和right屬性的值進行修改,那麼就能實現控制分割線的左右邊距了。

既然需要擴展ListView,最常用的方法就是繼承重寫了。不幸的是由於drawDivider方法的訪問控制故並不能被復寫,但值得慶幸的是ListView的Divider對象具有setter和getter方法。

具體的實現邏輯非常簡單,核心是裝飾模式,我就不去詳細說了。

源碼和范例詳見:https://github.com/MegatronKing/DividerSample

用法非常簡單,給ListView分割線擴充了兩個屬性:dividerPaddingLeft和dividerPaddingRight,顧名思義。這兩個屬性值既可以在xml布局中配置也可以在代碼中設置。

layout示例如下:

<com.megatronking.divider.view.DividerListView    
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:divider="http://schemas.android.com/apk/res-auto"
    android:id="@+id/list"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:divider="#99cccccc"
    android:dividerHeight="0.5dip"
    divider:dividerPaddingLeft="15dip"
    divider:dividerPaddingRight="15dip" />

使用inset標簽定義drawable

在Drawable家族中有一個特殊的存在:InsetDrawable,可以定義上下左右四個邊界的留白,InsetDrawable同樣使用了裝飾模式,和方案4的機制有異曲同工之妙。當被裝飾Drawable的Bound值變化時,重新定義Bound。另外,最強大的是可以直接使用xml定義。

<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:insetLeft="15dip">
    <shape>
        <size android:height="0.5dip" />
        <solid android:color="#99cccccc" />