開發(fā)中Dialog彈窗優(yōu)先級(jí)控制

如果你的APP有多種彈窗,試想一下,你的APP中有(活動(dòng)彈窗、登錄彈窗、更新彈窗、alert彈窗...)它們出現(xiàn)的時(shí)機(jī)有可能會(huì)重疊,那么彈窗的優(yōu)先級(jí)就有必要做了,活動(dòng)如:


WechatIMG1799.jpeg

1.創(chuàng)建一個(gè)單例manger用來維護(hù)彈窗優(yōu)先級(jí)

public static DialogManger getInstance(Context context) {
    if (mInstance == null) {
        synchronized (DialogManger.class) {
            if (mInstance == null) {
                mInstance = new DialogManger(context.getApplicationContext());
            }
        }
    }
    return mInstance;
  }

2.在manger中用常量定義各種彈框的級(jí)別

 /**
 * 活動(dòng)彈窗的優(yōu)先級(jí)
 */
public final static int AD_PRIORITY = 1;
/**
 * 更新彈窗的優(yōu)先級(jí)
 */
public final static int UPDATE_PRIORITY = 2;
/**
 * alert彈窗的優(yōu)先級(jí)
 */
public final static int ALERT_PRIORITY = 3;
/**
 * 登錄彈窗的優(yōu)先級(jí)
 */
public final static int LOGIN_PRIORITY = 4;
/**
 * other彈窗的優(yōu)先級(jí)
 */
public final static int OTHER_PRIORITY = 5;


@RestrictTo(GROUP_ID)
@IntDef({AD_PRIORITY, UPDATE_PRIORITY, ALERT_PRIORITY, LOGIN_PRIORITY, OTHER_PRIORITY})
@Retention(RetentionPolicy.SOURCE)
public @interface DialogLevel {
}

3.創(chuàng)建一個(gè)stack來存儲(chǔ)每種彈框Tag

我們先創(chuàng)建一個(gè)DialogTag類,序列化,重寫equals方法,用于標(biāo)記每種彈框
public class DialogTag implements Serializable {

int level;
String uuid;

public DialogTag(@DialogManger.DialogLevel int level, String uuid) {
    this.level = level;
    this.uuid = uuid;
}


@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj instanceof DialogTag) {
        DialogTag anotherDialogTag = (DialogTag) obj;

        if (this.level == anotherDialogTag.level
                && this.uuid.equals(anotherDialogTag.uuid)) {
            return true;
        }
    }
    return false;
}


}
 在manger中創(chuàng)建stack存儲(chǔ)DialogTag
 private Stack<DialogTag> mDialogLevels = new Stack<>();

4.提供一個(gè)方法根據(jù)優(yōu)先級(jí)處理彈框是否可顯示

  public boolean canShow(DialogTag tag) {
    if (mDialogLevels.size() > 0) {
        DialogTag topTag = mDialogLevels.peek();
        if (tag.level >= topTag.level) {
            mDialogLevels.push(tag);
            return true;
        } else {
            return false;
        }
    } else {
        mDialogLevels.push(tag);
        return true;
    }
}
 每個(gè)彈框打開前會(huì)調(diào)用次方法,如果stack的size為0時(shí),說明還沒有任何彈窗打開,這時(shí)候第一個(gè)彈窗就push到棧頂,
 如果已經(jīng)有開啟的彈窗,下一個(gè)彈窗進(jìn)來,首先就會(huì)取棧頂?shù)膹棿癟ag與本次要啟動(dòng)彈窗的Tag級(jí)別做比較,
 如果進(jìn)來的彈窗優(yōu)先級(jí)比棧頂?shù)膬?yōu)先級(jí)高,那么這個(gè)彈窗就可以開啟,并且push到棧頂,否則就不能開啟

 因?yàn)閟tack是先進(jìn)后出特點(diǎn),所以每個(gè)Tag進(jìn)來都會(huì)在棧頂,由于每次新進(jìn)來的彈框都會(huì)取棧頂?shù)呐c之比較,所以棧頂優(yōu)先級(jí)肯定高于站內(nèi)其他Tag

5.彈框銷毀時(shí)通知manger中stack移除Tag

我們彈框打開時(shí)會(huì)把Tag  push到stack里,當(dāng)彈框銷毀時(shí)也要從stack中移除,我們可以通過廣播通知manger調(diào)用dismiss來移除Tag

在構(gòu)造方法中注冊(cè)廣播
private DialogManger(Context context) {
    IntentFilter filter = new IntentFilter(ACTION_DIALOG_DISMISS);
    LocalBroadcastManager.getInstance(context).registerReceiver(mDialogDismissReceiver, filter);
}

在收到廣播后,調(diào)用dismiss()
public class DialogDismissReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent != null) {
            DialogTag tag = (DialogTag) intent.getSerializableExtra(DIALOG_TAG);
            dismiss(tag);
        }
    }
}
private void dismiss(DialogTag tag) {
    int i = mDialogLevels.lastIndexOf(tag);
    if (i >= 0) {
        mDialogLevels.removeElementAt(i);
    }
}

彈窗啟動(dòng)前創(chuàng)建一個(gè)DialogTag,調(diào)用manger的canShow()
public static void launch(Activity activity) {
    DialogTag dialogTag = new DialogTag(DialogManger.ALERT_PRIORITY, UUID.randomUUID().toString());
    if (DialogManger.getInstance(activity).canShow(dialogTag)) {
        Intent intent = new Intent(activity, AlertDialogActivity.class);
        intent.putExtra(DialogManger.DIALOG_TAG, dialogTag);
        activity.startActivity(intent);
    }

}
在彈框銷毀時(shí),發(fā)送廣播通知manger         
 @Override
protected void onDestroy() {
    super.onDestroy();
    LocalBroadcastManager.getInstance(this)
            .sendBroadcast(new Intent(DialogManger.ACTION_DIALOG_DISMISS)
                    .putExtra(DialogManger.DIALOG_TAG, mDialogTag));
}

因?yàn)轫?xiàng)目需求 我這里的彈框都是用Activity使用Dialog樣式

接下來我們測(cè)試一下


Dialog樣式的Activity.png

我這創(chuàng)建了幾種Dialog樣式的Activity,作為Dialog

在一個(gè)button的click方法中,每點(diǎn)擊一次會(huì)隨機(jī)生成1-5之間的5個(gè)數(shù)字代表5個(gè)DialogActivity的優(yōu)先級(jí),每次生成的5個(gè)數(shù)字都用TextView顯示在MainActivity上,
方便觀察,
 public void onClick(View view) {
    count = randomCommon(0, 6, 5);//隨機(jī)生成1-5之間的5個(gè)數(shù)字
    assert count != null;
    for (int level : count) {
        sb.append(level);
        if (level != count[count.length - 1]) {
            sb.append(",");
        }
    }
    tv_level.setText(String.valueOf("startDialogActivity level : " + sb.toString()));
    sb.setLength(0);
    startCountdown();
}

創(chuàng)建一個(gè)倒計(jì)時(shí),每間隔1秒啟動(dòng)一個(gè)DialogActivity

private synchronized void startCountdown() {

    mCountDownTimer = new CountDownTimer(7 * 1000, 1000) {
        @Override
        public void onTick(long millisUntilFinished) {
            if (index < count.length) {
                startDialogActivity(count[index]);
                index++;
            } else {
                index = 0;
                endCountdown();
            }

            Log.e(TAG, "onTick:  index :" + index);
        }

        @Override
        public void onFinish() {

        }
    }.start();
}

根據(jù)優(yōu)先級(jí)數(shù)組中的數(shù)字級(jí)別來啟動(dòng)DialogActivity

 private void startDialogActivity(int levels) {
    switch (levels) {
        case DialogManger.AD_PRIORITY:
            ADDialogActivity.launch(MainActivity.this);
            break;
        case DialogManger.UPDATE_PRIORITY:
            UpdateDialogActivity.launch(MainActivity.this);
            break;
        case DialogManger.ALERT_PRIORITY:
            AlertDialogActivity.launch(MainActivity.this);
            break;
        case DialogManger.LOGIN_PRIORITY:
            LoginDialogActivity.launch(MainActivity.this);
            break;
        case DialogManger.OTHER_PRIORITY:
            OtherDialogActivity.launch(MainActivity.this);
            break;
    }

}

看下效果:

test.gif

我們看到優(yōu)先級(jí)數(shù)組顯示為 3、5、1、4、2,那么優(yōu)先級(jí)為3、5的彈框依次彈出,后面的1、4、2,優(yōu)先級(jí)都低于5,沒有彈出。
再看一次

test2.gif

這次只有優(yōu)先級(jí)為1的沒有彈出

好啦,代碼比較簡(jiǎn)單,相信一看就能明白,demo我已傳到GitHub,歡迎star,謝謝!
https://github.com/xiaviv/DialogLevels

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,769評(píng)論 25 709
  • ¥開啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個(gè)線程,因...
    小菜c閱讀 7,295評(píng)論 0 17
  • 哎呀呀 ,馬上就要面臨找工作了,媛媛心里緊張呀. 作為一個(gè)即將畢業(yè)的Android程序媛,開始面臨找工作了,...
    左神話閱讀 5,154評(píng)論 7 59
  • 來自:【http://benbeng.leanote.com/post/On-Demand-Resources-G...
    LV大樹閱讀 1,573評(píng)論 0 2
  • 將秋風(fēng)采集 釀在咸菜壇子里 壓上時(shí)間的瓦礫 汗水裹著鹽粒成防腐劑 等著春天里 和你 就著桃花嘗秋風(fēng)釀手藝 想趁著白...
    喬安的故事閱讀 191評(píng)論 0 0

友情鏈接更多精彩內(nèi)容