【问题标题】:How to hide a message after few seconds in Android如何在Android中几秒钟后隐藏消息
【发布时间】:2017-09-29 18:33:48
【问题描述】:

我向用户显示消息通知并在几秒钟后隐藏该通知,我正在使用 postDelayed() 来实现此功能,但问题是当我在隐藏第一条消息之前用新消息更新通知时,我需要重置/重新启动计时器。我找不到任何方法来实现它,因为 removeCallbacks() 只删除待处理的任务。

每当我有新消息要显示在按钮单击时,我都会从MyClass 呼叫showNotification() 并提供新消息。现在,如果我在 4 秒内再次单击该按钮(比如说x 秒)(在隐藏旧通知消息之前)。无法取消旧的 postDelayed 或将计时器重新启动到 4 秒,它会在 4-x 秒后隐藏我的新通知。

MyClass.java

...
// On Button Click - everytime a different message

MyNotification obj = new MyNotification();
obj.showNotification(msg);
...

MyNotification.java

public class MyNotification
{
    ...
    ...
    private static TextView textview1;
    private static MyNotification notification;

    @Override
    protected void onFinishInflate()
    {
        super.onFinishInflate();

        notification = (MyNotification) this.findViewById(R.id.notification_bar);
        textview1 = (TextView) this.findViewById(R.id.textview_notification);
    }

    Runnable hideNotification = new Runnable() {
        @Override
        public void run() {
            textview1.setVisibility(GONE);
            notification.setVisibility(GONE);
        }
    };

    public void showNotification(String msg)
    {

        textview1.setText(msg);
        textview1.setVisibility(VISIBLE);
        notification.setVisibility(VISIBLE);

        // Hide Toast notification after few secs
        notification.postDelayed(hideNotification, 4000);
    }

    ...
}

【问题讨论】:

    标签: java android notifications postdelayed


    【解决方案1】:

    只需使用处理程序并根据需要添加或删除回调。我为此写了一个类。我会和你分享。

       /**
         * Created with IntelliJ IDEA.
         * User: App Studio 35
         * Date: 5/17/13
         * Time: 1:53 PM
         * To change this template use File | Settings | File Templates.
         */
    
        public class TimeOutWatcher {
    
        /*//////////////////////////////////////////////////////////
        // MEMBERS
        *///////////////////////////////////////////////////////////
        private ITimeOutWatcher mTimeOutHandler = null;
        private Handler mHandler = null;
        private long mTimeOutMilliseconds;
    
    
        /*//////////////////////////////////////////////////////////
        // Runnable
        *///////////////////////////////////////////////////////////
        private Runnable mTimeoutRunnable = new Runnable() {
            @Override
            public void run() {
                //If stopTimeOutWatch has not been called then trigger TimeOutOccurred
                if(mTimeOutHandler != null){
                    mTimeOutHandler.TimeOutOccurred();
                }
    
                //Remove callback to avoid duplicate triggers
                mHandler.removeCallbacks(mTimeoutRunnable);
            }
        };
    
    
       /*//////////////////////////////////////////////////////////
       // METHODS
       *///////////////////////////////////////////////////////////
        /**
         * Set TimeOutListener to trigger when timeout occurs
         *
         * @param listener of type ITimeOutWatcher
         */
        public void setTimeOutListener(ITimeOutWatcher listener){
            mTimeOutHandler = listener;
        }
        /**
         * Called when needing a timeout to occur based on the passed number of
         * Milliseconds. Performs a postDelay to trigger calling of TimeOutOccurred.
         * Must call stopTimeOutWatch after your waiting process is complete and
         * before this delay trigger happens if you want to avoid
         * getting a TimeOutOccurred
         *
         * @param timeOutMilliseconds
         */
        public void startTimeOutWatch(long timeOutMilliseconds){
            mTimeOutMilliseconds = timeOutMilliseconds;
            mHandler = new Handler(Looper.getMainLooper());
            mHandler.postDelayed(mTimeoutRunnable, timeOutMilliseconds);
        }
        public void resetTimeOutWatch(long timeOutMilliseconds){
            stopTimeOutWatch();
            startTimeOutWatch(timeOutMilliseconds);
        }
        public void resetTimeOutWatch(){
            stopTimeOutWatch();
            startTimeOutWatch(mTimeOutMilliseconds);
        }
        /**
         * Used to cancel TimeOut from happening
         * Call when process that you are waiting on is complete
         * to avoid TimeOutOccurred
         */
        public void stopTimeOutWatch(){
            if(mTimeoutRunnable != null){
                if(mHandler != null){
                    mHandler.removeCallbacks(mTimeoutRunnable);
                }
            }
        }
    
    
        public interface ITimeOutWatcher {
    
            /**
             * Called when TimeOutWatcher exceeds requested TimeOut Period
             */
            void TimeOutOccurred();
    
        }
    }
    

    使用很简单,只需创建一个 TimeOutWatcher 实例并在所需时间开始超时。如果您需要取消它然后调用停止如果你想重置然后调用重置。简单的。希望对您有所帮助。

    【讨论】:

    • 只是想确认一件事.. 1. 它是要在同一个 UI 线程上运行 Runnable 还是要创建一个新线程。因为我的Runnable 方法修改了现有的 UI 元素。
    • 是的,就是新的处理程序中的 Looper.prepareMainLooper() 命令。如果您愿意,您也可以修改它以删除它并在调用它的任何线程上运行。
    【解决方案2】:

    一个简单的解决方案是,如果在通知已显示的情况下单击按钮,则防止出现重复通知。

    这很容易通过在启动 runnable 之前检查视图的可见性来完成:

    public void showNotification(String msg)
        {
    
            if (textview1.getVisibility() != View.VISIBLE) {
                textview1.setText(msg);
                textview1.setVisibility(VISIBLE);
                notification.setVisibility(VISIBLE);
    
                // Hide Toast notification after few secs
                notification.postDelayed(hideNotification, 4000);
            }
        }
    

    【讨论】:

    • 按照您的建议,我将不得不更新代码以仅在新短信已经可见时才设置它。再说一次,我需要一种方法将计时器重置为新的 4 秒并取消旧计时器(第一次创建)
    【解决方案3】:

    当然,您可以取消可运行文件并发布新的:使用View.removeCallbacks(Runnable)

    所以我认为您的代码将更改为:

    public void showNotification(String msg)
    {
    
        textview1.setText(msg);
        textview1.setVisibility(VISIBLE);
        notification.setVisibility(VISIBLE);
    
        // Remove the existing hide instruction
        notification.removeCallbacks(hideNotification);
        // Hide Toast notification after few secs
        notification.postDelayed(hideNotification, 4000);
    }
    

    【讨论】:

    • 我已经尝试过了,但这并没有取消回调(如我的描述中所述),所有以前的hideNotification 不再在Pending 队列中,而是在Running 队列中并且将最终在 4 秒后运行。
    猜你喜欢
    • 2019-01-11
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-07
    • 2017-12-28
    • 1970-01-01
    相关资源
    最近更新 更多