悬剑请抬头 發表於 2020-2-3 16:53:00

有关 Android 应用开发中的弹窗式通知

<p>2020-02-03</p>
<p>关键字:ToastManager、应用消息通知</p>
<hr>
<p>&nbsp;</p>
<p>Android 应用往往少不了要与用户交互的场景。</p>
<p>&nbsp;</p>
<p>所谓与用户交互,就是指用户需要主动或者被动接受来自应用的消息、状态提示的场景。</p>
<p>&nbsp;</p>
<p>这种消息、状态的展示形式往往多种多样。但常见的也是比较合适的是弹窗式交互。</p>
<p>&nbsp;</p>
<p>弹窗式交互是在应用内展示的。即在应用运行过程中以1、Toast 式弹窗通知;2、对话框式弹窗通知;两种形式来与用户交互。</p>
<p>&nbsp;</p>
<p>其中,第 1 种交互笔者称之为“弱交互式通知”,它弹出来以后过一段时间即会自行消隐。用户只需要看,完全不用去处理,甚至可以连看都不看。</p>
<p style="text-align: center"><img src="https://img2018.cnblogs.com/i-beta/1146198/202002/1146198-20200203114759456-134737110.png"></p>
<p>&nbsp;</p>
<p>而第 2 种笔者则称之为“强交互式通知”,它会弹出一个对话框,用户只能手动点击对话框上的相应按钮才能关掉对话框。</p>
<p style="text-align: center"><img src="https://img2018.cnblogs.com/i-beta/1146198/202002/1146198-20200203114855896-573468608.png"></p>
<p>&nbsp;</p>
<p>这两种交互弹窗的实现可就太容易了。第一个就是 Toast,而第二个则是 Dialog。堪称是小学生都能做出来。</p>
<p>&nbsp;</p>
<p>但今天这篇博文,不聊实现方式。来聊聊在一款应用中应如何对待各种各样的弹窗式消息通知。</p>
<p>&nbsp;</p>
<p>根据笔者的经验,在整个应用中统一管理弹窗式通知是最合理的。如何统一管理呢?</p>
<p>&nbsp;</p>
<p>即严禁私自创建 Toast 或 Dialog 来展示,这样可能会导致同时弹出多个弹窗的情况从而引发通知混乱。</p>
<p>&nbsp;</p>
<p>取而代之的是所有需要弹出的通知都交由同一个通知管理类来弹出。</p>
<p>&nbsp;</p>
<p>有了这个统一的入口,我们就可以很方便地管控通知了。是即时弹出、是过滤、是排队弹出或是其它各种需求,都可以在这个统一的通知管理类中很方便的实现。</p>
<p>&nbsp;</p>
<p>笔者今天就在这里记录一下自己撰写的这么一个通知管理类 ToastManager。当然,笔者的这个类仅仅是根据自己的实际需求来实现的,并没有做到绝对的完善与完美,在此记录的主要目的是为了给自己备一下忘。</p>
<p>&nbsp;</p>
<p>笔者的这个 ToastManager 目前有三种弹窗:</p>
<p style="margin-left: 30px">1、弱交互式弹窗;</p>
<p style="margin-left: 30px">2、强交互式弹窗;</p>
<p style="margin-left: 30px">3、强交互式选择弹窗;</p>
<p style="margin-left: 60px"><span style="font-size: 12px">强交互式弹窗的变种版,对话框上具有“确定”与“否定”两个按钮,可以通过回调方法来通知创建者用户的选择结果。</span></p>
<p>&nbsp;</p>
<p>笔者这个 ToastManager 在本质上就是简单地对 Toast 与 AlertDialog 作一下封装而已。甚至连排队机制都还没有实现,如果你有兴趣,可以尝试着自己去实现。</p>
<p>&nbsp;</p>
<p>对了,还有一个很重要的。因为这个通知管理类理论上允许在任意位置调用。而 Toast 和 Dialog 是不允许在子线程中弹出的,但这种情况笔者仅仅是做了打印提示处理。正常来讲应该是将所有的通知弹出请求都转换成在主线程来弹的,但很遗憾,笔者没有去实现,实在是因为懒~</p>
<p>&nbsp;</p>
<p>话不多说,以下是 ToastManager 的源码:</p>
<div class="cnblogs_code"><img id="code_img_closed_d4ab9cb7-aad4-46ce-b3af-9c490468e3b1" class="code_img_closed lazyload" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img id="code_img_opened_d4ab9cb7-aad4-46ce-b3af-9c490468e3b1" class="code_img_opened lazyload" style="display: none" alt="" data-src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif">
<div id="cnblogs_code_open_d4ab9cb7-aad4-46ce-b3af-9c490468e3b1" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)">package</span><span style="color: rgba(0, 0, 0, 1)"> com.jarwen.scanner.util;

</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.app.AlertDialog;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.content.Context;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.graphics.drawable.ColorDrawable;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.graphics.drawable.Drawable;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.os.Build;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.view.Gravity;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.view.View;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.widget.Button;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.widget.GridLayout;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.widget.LinearLayout;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.widget.TextView;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.widget.Toast;

</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> com.jarwen.scanner.R;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> com.jarwen.scanner.ScannerApplication;

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ToastManager {

    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">boolean</span> IS_WEAK_TOAST = <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> Context context;

    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> Toast toast;
    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> txtColor;
    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> txtSize;
    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> Drawable bgDrawable;

    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> AlertDialog dialog;
    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> OnMakeChoiceResult onMakeChoiceResult;
    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> OnStrongToastListener onStrongToastListener;

    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> ToastManager(Context context){
      </span><span style="color: rgba(0, 0, 255, 1)">this</span>.context =<span style="color: rgba(0, 0, 0, 1)"> context;

      toast </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Toast(context);
      toast.setDuration(Toast.LENGTH_SHORT);
      toast.setGravity(Gravity.CENTER, </span>0, UnitManager.px2dp(80<span style="color: rgba(0, 0, 0, 1)">));

      txtSize </span>= 13<span style="color: rgba(0, 0, 0, 1)">;
      txtColor </span>=<span style="color: rgba(0, 0, 0, 1)"> context.getResources().getColor(R.color.gray_dark_1);
      bgDrawable </span>=<span style="color: rgba(0, 0, 0, 1)"> context.getResources().getDrawable(R.drawable.round_corner_gray_r5);
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> toast(String msg) {
      toast(IS_WEAK_TOAST, msg);
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> toast(<span style="color: rgba(0, 0, 255, 1)">boolean</span><span style="color: rgba(0, 0, 0, 1)"> isWeakToast, String msg){
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(Thread.currentThread().getId() != 1<span style="color: rgba(0, 0, 0, 1)">){
            Logger.e(</span>"Cannot toast on sub-thread."<span style="color: rgba(0, 0, 0, 1)">);
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
      }

      dismissDialog();

      </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(isWeakToast) {
            weakToast(msg);
      }</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
            strongToast(msg);
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> makeChoice(String content, OnMakeChoiceResult callback){
      Logger.v(</span>"makeChoice()"<span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(Thread.currentThread().getId() != 1<span style="color: rgba(0, 0, 0, 1)">){
            Logger.e(</span>"Cannot toast on sub-thread."<span style="color: rgba(0, 0, 0, 1)">);
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
      }

      dismissDialog();

      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(onMakeChoiceResult != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
            Logger.e(</span>"Cannot popup the make choice dialog cause current already shown a 'mc' dialog."<span style="color: rgba(0, 0, 0, 1)">);
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
      }

      </span><span style="color: rgba(0, 0, 255, 1)">int</span> windowWidth = (<span style="color: rgba(0, 0, 255, 1)">int</span>) (ScannerApplication.getInstance().getHardware().getAppWidth() * 0.618f<span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">int</span> windowHeight = UnitManager.px2dp(123<span style="color: rgba(0, 0, 0, 1)">);
      Logger.d(</span>"dimension:" + windowWidth + "*" +<span style="color: rgba(0, 0, 0, 1)"> windowHeight);

      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 1. make layout.</span>
      GridLayout layout = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> GridLayout(context);
      layout.setColumnCount(</span>2<span style="color: rgba(0, 0, 0, 1)">);
      layout.setRowCount(</span>2<span style="color: rgba(0, 0, 0, 1)">);
      layout.setBackground(context.getResources().getDrawable(R.drawable.round_corner_makechoice_dialog_bg));

      TextView tvContent </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> TextView(context);
      tvContent.setText(content);
      tvContent.setTextSize(</span>15<span style="color: rgba(0, 0, 0, 1)">);
      tvContent.setTextColor(context.getResources().getColor(R.color.gray_text_333));
      tvContent.setGravity(Gravity.CENTER);
      tvContent.setBackground(context.getResources().getDrawable(R.drawable.round_corner_makechoice_dialog_content_bg));
      GridLayout.LayoutParams glp </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> GridLayout.LayoutParams(GridLayout.spec(0), GridLayout.spec(0, 2<span style="color: rgba(0, 0, 0, 1)">));
      glp.width </span>= -1<span style="color: rgba(0, 0, 0, 1)">;
      glp.height </span>= (<span style="color: rgba(0, 0, 255, 1)">int</span>) (windowHeight * 0.6f<span style="color: rgba(0, 0, 0, 1)">);
      tvContent.setLayoutParams(glp);

      TextView tvCancel </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> TextView(context);
      tvCancel.setTextColor(context.getResources().getColor(R.color.gray_text_888));
      tvCancel.setTextSize(</span>15<span style="color: rgba(0, 0, 0, 1)">);
      tvCancel.setText(context.getText(R.string.no));
      tvCancel.setBackground(context.getResources().getDrawable(R.drawable.round_corner_makechoice_dialog_cancel_bg));
      tvCancel.setGravity(Gravity.CENTER);
      glp </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> GridLayout.LayoutParams(GridLayout.spec(1), GridLayout.spec(0, 1.0f<span style="color: rgba(0, 0, 0, 1)">));
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(Build.VERSION.SDK_INT &lt;= 22<span style="color: rgba(0, 0, 0, 1)">){
            glp.width </span>= (<span style="color: rgba(0, 0, 255, 1)">int</span>) ((<span style="color: rgba(0, 0, 255, 1)">float</span>) windowWidth / 2.0f<span style="color: rgba(0, 0, 0, 1)">);
      }
      glp.height </span>= (<span style="color: rgba(0, 0, 255, 1)">int</span>) (windowHeight * 0.4f<span style="color: rgba(0, 0, 0, 1)">);
      glp.topMargin </span>= UnitManager.px2dp(1<span style="color: rgba(0, 0, 0, 1)">);
      tvCancel.setLayoutParams(glp);
      tvCancel.setOnClickListener(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> View.OnClickListener() {
            @Override
            </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onClick(View v) {
                Logger.d(</span>"cancel the make choice dialog"<span style="color: rgba(0, 0, 0, 1)">);
                </span><span style="color: rgba(0, 0, 255, 1)">if</span>(onMakeChoiceResult != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
                  onMakeChoiceResult.onMakeChoice(</span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">);
                  onMakeChoiceResult </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
                }

                dismissDialog();
                notifyStrongToastListener(</span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">);
            }
      });

      TextView tvOk </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> TextView(context);
      tvOk.setTextColor(context.getResources().getColor(R.color.toast_makechoice_txt_ok));
      tvOk.setTextSize(</span>15<span style="color: rgba(0, 0, 0, 1)">);
      tvOk.setText(context.getText(R.string.yes));
      tvOk.setGravity(Gravity.CENTER);
      tvOk.setBackground(context.getResources().getDrawable(R.drawable.round_corner_makechoice_dialog_ok_bg));
      glp </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> GridLayout.LayoutParams(GridLayout.spec(1), GridLayout.spec(1, 1.0f<span style="color: rgba(0, 0, 0, 1)">));
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(Build.VERSION.SDK_INT &lt;= 22<span style="color: rgba(0, 0, 0, 1)">){
            glp.width </span>= (<span style="color: rgba(0, 0, 255, 1)">int</span>) ((<span style="color: rgba(0, 0, 255, 1)">float</span>) windowWidth / 2.0f) - UnitManager.px2dp(1<span style="color: rgba(0, 0, 0, 1)">);
      }
      glp.height </span>= (<span style="color: rgba(0, 0, 255, 1)">int</span>) (windowHeight * 0.4f<span style="color: rgba(0, 0, 0, 1)">);
      glp.topMargin </span>= UnitManager.px2dp(1<span style="color: rgba(0, 0, 0, 1)">);
      glp.leftMargin </span>=<span style="color: rgba(0, 0, 0, 1)"> glp.topMargin;
      tvOk.setLayoutParams(glp);
      tvOk.setOnClickListener(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> View.OnClickListener() {
            @Override
            </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onClick(View v) {
                Logger.d(</span>"ok the make choice dialog"<span style="color: rgba(0, 0, 0, 1)">);
                </span><span style="color: rgba(0, 0, 255, 1)">if</span>(onMakeChoiceResult != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
                  onMakeChoiceResult.onMakeChoice(</span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
                  onMakeChoiceResult </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
                }

                dismissDialog();
                notifyStrongToastListener(</span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">);
            }
      });

      layout.addView(tvContent);
      layout.addView(tvCancel);
      layout.addView(tvOk);

      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 2. decorate dialog and show it.</span>
      <span style="color: rgba(0, 0, 255, 1)">if</span>(dialog != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
            dialog.dismiss();
      }
      dialog </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> AlertDialog.Builder(context).create();
      dialog.setCancelable(</span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">);
      dialog.setCanceledOnTouchOutside(</span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">);
      dialog.show();
      dialog.setContentView(layout); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Must behind on 'dialog.show()'.</span>

      <span style="color: rgba(0, 0, 255, 1)">if</span>(dialog.getWindow() != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
            dialog.getWindow().setLayout(windowWidth, windowHeight);
            dialog.getWindow().setBackgroundDrawable(</span><span style="color: rgba(0, 0, 255, 1)">new</span> ColorDrawable(0<span style="color: rgba(0, 0, 0, 1)">));
      }

      onMakeChoiceResult </span>=<span style="color: rgba(0, 0, 0, 1)"> callback;
      notifyStrongToastListener(</span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
    }


</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++</span>


    <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> weakToast(String msg){
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(Build.VERSION.SDK_INT &gt; 25<span style="color: rgba(0, 0, 0, 1)">){
            toast </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
            Toast toast </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Toast(context);
            toast.setDuration(Toast.LENGTH_SHORT);
            toast.setGravity(Gravity.CENTER, </span>0, UnitManager.px2dp(80<span style="color: rgba(0, 0, 0, 1)">));
            toast.setView(getTextView(msg));
            toast.show();
      }</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
            </span><span style="color: rgba(0, 0, 255, 1)">if</span>(toast.getView() != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">){
                ((TextView)toast.getView()).setText(msg);
            }</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
                toast.setView(getTextView(msg));
            }
            toast.show();
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> strongToast(String msg){
      dismissDialog();

      dialog </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> AlertDialog.Builder(context).create();
      dialog.setCanceledOnTouchOutside(</span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">);
      dialog.setCancelable(</span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">);

      dialog.show();
      dialog.setContentView(getDialogView(msg));

      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(dialog.getWindow() != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
            Logger.d(</span>"poping strong toast,screen:" +<span style="color: rgba(0, 0, 0, 1)">
                  ScannerApplication.getInstance().getHardware().getAppWidth() </span>+ "*" +<span style="color: rgba(0, 0, 0, 1)">
                  ScannerApplication.getInstance().getHardware().getAppHeight());
            dialog.getWindow().setLayout((</span><span style="color: rgba(0, 0, 255, 1)">int</span>) (ScannerApplication.getInstance().getHardware().getAppWidth() * 0.618f), -2<span style="color: rgba(0, 0, 0, 1)">);
      }

      notifyStrongToastListener(</span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
    }

    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> dismissDialog(){
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(dialog != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
            dialog.dismiss();
            dialog </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> TextView getTextView(String txt){
      TextView tv </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> TextView(context);
      </span><span style="color: rgba(0, 0, 255, 1)">int</span> padding =<span style="color: rgba(0, 0, 0, 1)"> UnitManager.pix10();
      tv.setPadding(padding, padding, padding, padding);
      tv.setBackground(bgDrawable);
      tv.setGravity(Gravity.CENTER);
      tv.setTextColor(txtColor);
      tv.setTextSize(txtSize);
      tv.setText(txt);

      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> tv;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> View getDialogView(String txt){
      </span><span style="color: rgba(0, 0, 255, 1)">final</span> LinearLayout dialogLayout = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> LinearLayout(context);
      dialogLayout.setGravity(Gravity.CENTER);
      dialogLayout.setBackground(context.getResources().getDrawable(R.drawable.round_corner_white_r5));
      dialogLayout.setOrientation(LinearLayout.VERTICAL);
      dialogLayout.setLayoutParams(</span><span style="color: rgba(0, 0, 255, 1)">new</span> LinearLayout.LayoutParams(-1, -1<span style="color: rgba(0, 0, 0, 1)">));

      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 1. Information view.</span>
      TextView tv = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> TextView(context);
      tv.setPadding(UnitManager.pix10(), UnitManager.pix10(), UnitManager.pix10(), UnitManager.pix10());
      LinearLayout.LayoutParams llp </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
      llp.topMargin </span>= UnitManager.px2dp(20<span style="color: rgba(0, 0, 0, 1)">);
      llp.bottomMargin </span>= UnitManager.px2dp(20<span style="color: rgba(0, 0, 0, 1)">);
      tv.setLayoutParams(llp);
      tv.setGravity(Gravity.CENTER);
      tv.setTextColor(context.getResources().getColor(R.color.gray_textview_original));
      tv.setTextSize(</span>12<span style="color: rgba(0, 0, 0, 1)">);
      tv.setText(txt);

      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 2. Divider line.</span>
      View divider = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> View(context);
      divider.setBackgroundColor(context.getResources().getColor(R.color.gray_background));
      llp </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> LinearLayout.LayoutParams(-1, UnitManager.px2dp(2<span style="color: rgba(0, 0, 0, 1)">));
      divider.setLayoutParams(llp);

      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 3. Button.</span>
      Button btn = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Button(context);
      btn.setText(R.string.ok);
      btn.setTextColor(context.getResources().getColor(R.color.basically_color));
      btn.setTextSize(</span>16<span style="color: rgba(0, 0, 0, 1)">);
      btn.setBackground(context.getResources().getDrawable(R.drawable.round_corner_white_r5));
      btn.setLayoutParams(</span><span style="color: rgba(0, 0, 255, 1)">new</span> LinearLayout.LayoutParams(-1, UnitManager.px2dp(40<span style="color: rgba(0, 0, 0, 1)">)));
      btn.setGravity(Gravity.CENTER);
      btn.setOnClickListener(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> View.OnClickListener() {
            @Override
            </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onClick(View v) {
                dismissDialog();
                notifyStrongToastListener(</span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">);
            }
      });

      dialogLayout.addView(tv);
      dialogLayout.addView(divider);
      dialogLayout.addView(btn);

      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> dialogLayout;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> showWaitingDialog(String info){
      dismissDialog();

      dialog </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> AlertDialog.Builder(context).create();
      dialog.setCancelable(</span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">);
      dialog.setCanceledOnTouchOutside(</span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">);
      dialog.show();
      dialog.setContentView(getTextView(info));

      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(dialog.getWindow() != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
            dialog.getWindow().setLayout((</span><span style="color: rgba(0, 0, 255, 1)">int</span>) (ScannerApplication.getInstance().getHardware().getAppWidth() * 0.382f), -2<span style="color: rgba(0, 0, 0, 1)">);
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> dismissWaitingDialog(){
      dismissDialog();
    }

    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span> notifyStrongToastListener(<span style="color: rgba(0, 0, 255, 1)">boolean</span><span style="color: rgba(0, 0, 0, 1)"> isShown){
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(onStrongToastListener != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
            onStrongToastListener.onStrongToastEvent(isShown);
            </span><span style="color: rgba(0, 0, 255, 1)">if</span>(!<span style="color: rgba(0, 0, 0, 1)">isShown) {
                onStrongToastListener </span>= <span style="color: rgba(0, 0, 255, 1)">null</span>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">一次性通知。</span>
<span style="color: rgba(0, 0, 0, 1)">            }
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setOnStrongToastListener(OnStrongToastListener listener){
      onStrongToastListener </span>=<span style="color: rgba(0, 0, 0, 1)"> listener;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> OnMakeChoiceResult{
      </span><span style="color: rgba(0, 0, 255, 1)">void</span> onMakeChoice(<span style="color: rgba(0, 0, 255, 1)">boolean</span><span style="color: rgba(0, 0, 0, 1)"> yes);
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> OnStrongToastListener {
      </span><span style="color: rgba(0, 0, 255, 1)">void</span> onStrongToastEvent(<span style="color: rgba(0, 0, 255, 1)">boolean</span><span style="color: rgba(0, 0, 0, 1)"> isShown);
    }
}</span></pre>
</div>
<span class="cnblogs_code_collapse">ToastManager源码</span></div>
<p>&nbsp;</p>
<p>它的使用方式也很简单,因为 Android 应用开发中不建议把 Context 静态保存(实际上对于 ToastManager 来说完全可以),而笔者不喜欢看到 Android Studio 的警告提示,就将 ToastManager 做成普通类的形式。同时,因为弹出 Dialog 需要 Activity 的 Context,因此,建议各位同学在 Activity 的初始化时创建 ToastManager 的实例。将实例以参数的形式传递给需要使用的地方即可。当然,其实最合理的方式是做成静态类的方式,这就需要同学自行去琢磨实现了。</p>
<p>&nbsp;</p>
<hr>
<p>&nbsp;</p>

</div>
<div id="MySignature" role="contentinfo">
    +++<br><br>
来源:https://www.cnblogs.com/chorm590/p/11637795.html
頁: [1]
查看完整版本: 有关 Android 应用开发中的弹窗式通知