将视图添加到具有时间延迟的活动?

Posted

技术标签:

【中文标题】将视图添加到具有时间延迟的活动?【英文标题】:Adding views to activity with time delay? 【发布时间】:2020-11-25 22:54:58 【问题描述】:

我正在尝试修改现有示例应用程序,当用户触摸屏幕时,该应用程序会将视图添加到主活动。这些视图是围绕屏幕浮动的位图图像。触摸屏幕上的任意位置会在该位置添加这些图像之一。

它通过为每次触摸创建一个新视图(位图图像​​)来做到这一点。

它按原样工作正常,但我正在尝试添加一个功能,它以编程方式添加这些视图而无需任何用户输入。

在下面的代码中,我添加了 onResume() 来尝试此功能。 (在 onCreate() 中添加相同的代码也不起作用。)

不幸的是,它没有像我希望的那样添加它们——它不是在用户启动应用程序后每 500 毫秒添加一个,而是暂停 5 秒,然后一次添加所有十个。

显然我是 android dev 的新手,所以我不知道从哪里开始。

我需要做些什么来实现延迟,使其每半秒添加一个新视图?为什么默认情况下会这样做?

谢谢!

    
    
class ImageScreen : Activity()

   
    public override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)

        setContentView(R.layout.imagescreen)

        mFrame = findViewById<View>(R.id.frame) as FrameLayout
        mBitmap = BitmapFactory.decodeResource(resources, R.drawable.myBitmapImage)
    
        mFrame!!.setOnTouchListener  _, event ->
            createImage(event.x, event.y)
            true
        

    
    
    override fun onResume() 
        super.onResume()

        for (i in 0..10) 

            createImage(xpos.random(), ypos.random())
            sleep(500)

        
    
    
    private fun createImage(x: Float, y: Float)
        mFrame!!.addView(myImage(applicationContext, x, y))
    
    
    
    inner class myImage internal constructor(context: Context, x: Float, y: Float) : View(context) 
 
        private fun createScaledBitmap(r: Random) 
            mScaledBitmap = Bitmap.createScaledBitmap(mBitmap!!, mScaledBitmapWidth, mScaledBitmapWidth, false) 
        

        fun start() 
            val executor = Executors.newScheduledThreadPool(1)

            mMoverFuture = executor.scheduleWithFixedDelay(
                if (changePosIfStillOnScreen()) 
                    postInvalidate()
                 else stop(false)
            , 0, REFRESH_RATE.toLong(), TimeUnit.MILLISECONDS)
        

        private fun stop() 
                    mFrame!!.removeView(this@myImage)
        

        @Synchronized
        override fun onDraw(canvas: Canvas) 
            canvas.save()
            canvas.drawBitmap(mScaledBitmap!!, mXPos, mYPos, mPainter)
            canvas.restore()
        
    


// Additional code, such as functions and variable declarations that are not pertinent to this question, have been removed for simplicity

【问题讨论】:

【参考方案1】:

注意:下面的sn-p是从java角度看的,可能需要修改成kotlin

    Handler handler = new Handler(getMainLooper());
    Runnable runnable = new Runnable() 
        @Override
        public void run() 
            if (counter < 5) 
                createImage(0, 0); //your positions
                handler.postDelayed(this, 500);
                counter++;
            
        
    ;
    handler.postDelayed(runnable, 500);

注意:counter 是一个 int 变量来确定...计数。

推理: 您在任何 UI 类(活动、片段、视图)中执行的所有代码都默认为 UI 线程。如果您在该线程中执行任何 Thread.sleep() 操作,则整个 UI 将暂时冻结,这在某些情况下可能导致 ANR 崩溃 ANR。Handler 可以在这里为您提供帮助。它需要一个Looper 引用来实例化。当您调用post(Runnable) 或可选的postDelayed(Runnable, long millis) 时,它将采用Runnable 并在UI 线程上执行它(延迟或其他方式)。但是,对于每次使用,您都需要再次调用 post,即在 Runnable 中递归调用 post我希望这会有所帮助!! p>

【讨论】:

谢谢!那工作得很好。但是我仍然不完全清楚为什么所有十个视图最初同时出现。我知道 sleep() 冻结了线程,但是假设我对冻结的线程没问题(在那段时间我不需要任何用户输入),为什么在添加其他视图之间不简单地冻结线程十次?是否存在假设设计者希望一次添加所有元素的 UI 线程的某些属性? 就我对视图层次结构的了解而言,想要膨胀视图与实际膨胀的视图之间有一点延迟,因为所有视图调用都在后端排队。这可能是因为睡眠-唤醒周期太快,视图无法在屏幕上具体化。 val executor = Executors.newScheduledThreadPool(1) mMoverFuture = executor.scheduleWithFixedDelay( if (changePosIfStillOnScreen()) postInvalidate() else stop(false) , 0, REFRESH_RATE.toLong(), TimeUnit.MILLISECONDS) 这可能是加载图像的部分,在您设置图像和显示图像之间引入了轻微的延迟。【参考方案2】:

它会暂停 5 秒,然后一次添加所有 10 个,这是因为您在代码中使用了sleep(500),它会冻结主线程(UI 线程)。

使用handler实现延时动作,Ref:https://developer.android.com/reference/android/os/Handler

【讨论】:

以上是关于将视图添加到具有时间延迟的活动?的主要内容,如果未能解决你的问题,请参考以下文章

将活动指示器添加到警报视图

如何将可扩展列表视图的选定子视图数据从片段发送到父活动?

将项目添加到另一个活动中的列表视图(仅添加 1 个条目)

以编程方式将 XIB 视图添加到具有边界的视图控制器 - 不居中

活动指示器未显示在视图前面

将多个项目添加到列表视图,每个项目从按钮单击的另一个意图接收