歡迎光臨
每天分享高質量文章

Android 中的紅點提示怎麼統一實現

作者:生活簡單些

鏈接:https://www.jianshu.com/p/9a8fa0a3bc4c

 

App中的紅點廣泛用於提醒功能,雖然用在選單上、Tab上、串列,但本質它就是一個紅色的View,不就是放哪裡就顯示在哪裡嘛,有什麼難的?對!這是UI設計師和產品經理的一致觀點,但是作為開發你可別信了他們的鬼話!

這邊文章講紅點,絕不是講如何設計紅點的UI,而是講在代碼層面如何實現,如何快速集成到業務中。如果你聽了UI設計師和產品的鬼話你可能就真的哪裡需要顯示紅點然後就在哪裡放紅點view了,然後通過外部代碼控制它的隱藏和顯示,你會很累,要定義很多key-value來儲存記錄各種紅點顯示的條件,零零碎碎很分散,這根本不是統一的解決方案,這是典型的想到哪裡做到哪裡。

我的想法是創建一個紅點View,你可以將此紅點View放置在任何需要的View的右上方,然後初始化告知它顯示的條件,即:接收哪幾類通知提醒,比如告知它顯示的條件是App有版本提醒就結束了,條件滿足自動就會顯示,條件不滿足自動隱藏。

關於此紅點View的接入方式,非常簡單如下:

 

// 紅點提醒如果需要區分賬戶則需要設置賬戶,
// 比如:App升級提示無需區分賬戶,個人訊息提醒需要區分賬戶
mRedDotView.setAccount(accountId);

// 設置當前紅點監聽的appLinks,只有收到了設置的AppLink才會觸發當前紅點的顯示和隱藏
mRedDotView.setAppLinks("my-scheme://NewMsgAlert");

 

關於AppLink之前一篇文章提到過,本質就是借助scheme定義的url解析規則,不同的AppLink對應不用的響應策略。

 

下麵我們分析下紅點顯示的特性:

 

  • 相似而不相同性:都是紅點,只是不同位置的紅點關註的提示內容不一樣,所以更有必要定義統一規則來控制其顯示和隱藏,因此我們使用AppLink來統一解析和管理,不同的紅點View需要設置它所關註的AppLink,如上面接入方式所示,只要每個紅點View在初始化時候指定想要關註的AppLinks即可,如果需要賬戶隔離則別忘記設置account:

  • 持久性:如果不點擊、不查看,它會一直顯示,哪怕App被殺掉再打開。因此,紅點觸發的條件是儲存下來的,常見辦法是通過SharedPreference或Database,我採用了Database方式,因為可以便捷的通過SQL檢索以及資料統一管理,當紅點View加載後會在onAttachedToWindow()里根據註冊的AppLinks查詢是否有未讀的AppLinks:

public class PushMessageDbHelper extends SQLiteOpenHelper {

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE IF NOT EXISTS push_message (" +
                "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
                "title TEXT," +
                "sub_title TEXT," +
                "pic_url TEXT," +
                "app_link TEXT," +
                "account TEXT," +
                "update_dt TEXT," +
                "read INTEGER)");
    }

    // ... others
}

資料庫表結構定義,這是一個融合了AppLink、推送標題、子標題、推送通知圖片、賬戶ID、是否已讀等信息的表定義。

@Override
protected void onAttachedToWindow() {
    super.onAttachedToWindow();
    checkVisible();
    // ...other code
}

當view加載成功後查詢之前有沒有未讀的AppLinks,如果有則設置紅點顯示。

  • 即時性:紅點是否要顯示既可以是view初始化過程中查詢資料庫得知的,也可以是即時通知的,比如推送使得紅點顯示:

public class RedDotView extends AppCompatImageView {
    private PushContentReceiver mContentReceiver = new PushContentReceiver() {

        @Override
        public String getAccount(@NonNull Context context) {
            return mAccount;
        }

        @Override
        public List getAppLinks() {
            return mAppLinks;
        }

        @Override
        public boolean onReceive(@NonNull Context context, @NonNull AppLink appLink) {
            Log.d("DotView""onReceive appLink: " + appLink);

            if (mAppLinks == null || mAppLinks.size() == 0) {
                return false;
            }

            boolean haveUnReadMsg = false;
            for (String item : mAppLinks) {
                if (PushMessageService.getInstance(getContext()).haveUnread(item, getAccount(context))) {
                    haveUnReadMsg = true;
                    break;
                }
            }

            setVisibility(haveUnReadMsg ? VISIBLE : GONE);
            return false;
        }
    };

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        PushContentReceiver.register(getContext(), mContentReceiver, false);
        checkVisible();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        PushContentReceiver.unregister(getContext(), mContentReceiver);
    }

    // ...others code
}

由上可見在View的onAttachedToWindow()里註冊了一個監聽AppLink的receiver。

需要註意的是這裡的AppLink在定義的時候需要註明它是需要儲存的,即overide shouldSave() 並傳回true告知此AppLink收到後要儲存在DB里,因為即便App殺掉再次打開還是需要顯示紅點的,如下案例:

public class NewMsgAlert extends AppLink {

    @Override
    public boolean isPrivate() {
        return true;
    }

    @Override
    public boolean shouldSave() {
        return true;
    }
}

總之,思路並不複雜,主要是充分發揮scheme設計的AppLink帶來的好處,關於此View的實現也很簡單,可以參考這裡。
https://github.com/daydream123/applink/blob/master/library/src/main/java/com/feizhang/applink/RedDotView.java

已同步到看一看
赞(0)

分享創造快樂