활동 배경 흐림

11689 단어 AndroidKotlin
※ 이 기사는 요약potatotips45의 발표되었습니다.

입문


응용 프로그램을 개발할 때 때때로 Activity로 팝업 UI를 실현할 수 있다고 생각합니다.그때 희미한 배경을 바라는 부탁을 받은 적이 있나.iOS에서는 UIVIsual EffectView만 사용하지만 안드로이드에서는 약간의 노력이 필요하다.본고는 활동 배경을 모호하게 할 때 실시하는 방침과 힘든 점을 소개한다.

실시 방침


활동에서 배경이 모호해지려면 대략 3단계가 필요하다.
  • 촬영 배경 포착
  • 캡처 이미지에 대한 모호 처리
  • 모호하게 처리된 캡처 이미지를 활성 배경으로 설정
  • 1, 2에 대해서는 Background Blur in Android 참조하십시오."Getting Bitmap Ready""Blur it!"에 설명된 해당 매개변수의 값입니다.이렇게 한다고 생각할 수도 있지만 설치 후 힘든 부분이 있기 때문에 다음 장은 나중에 소개해 드리겠습니다.

    수고점 ①: 팝업 활동으로 배경 포착 불가


    팝업 활동을 사용하여 스냅되지 않은 배경 활동을 스냅합니다.반복적인 실험을 통해 나는 배경의 Activity로 포착을 촬영한 후에 그것을 튀어나온 Activity에 건네주었다.그러나 Bitmap의 용량이 너무 커서 Intent를 통해 전달할 수 없습니다.이번에는 이미지를 로컬 저장소에 한 번 저장하고 Intent로 그 Uri를 전달합니다.
    // Activityのキャプチャを撮る
    val view: View = window.findViewById(android.R.id.content)
    try {
        val bitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
        val c = Canvas(bitmap)
        view.draw(c)
    } catch (e: IllegalArgumentException) {
        e.printStackTrace()
    }
    
    // Bitmapをローカルストレージに保存してUriを取得
    val cacheDir = weakActivity.get()?.cacheDir ?: return null
    val file = File(cacheDir, CACHE_FILE_NAME)
    try {
        val outputStream = FileOutputStream(file)
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
        outputStream.flush()
        outputStream.close()
        Uri.fromFile(file)
    } catch (e: IOException) {
        e.printStackTrace()
    }
    
    이렇게 하면 기쁘고 축하할 만한 배경 포착을 얻을 수 있다.이번에는 하지 않았지만 포착을 받을 때 비트맵 자체의 용량을 압축하는 것도 괜찮다.

    수고점 ②: 이미지 저장, 모호 처리


    이미지 저장·모호 처리가 상당히 무거워 기종에 따라 각각 0.5초 정도 걸리는 경우도 있다.주 스레드가 이 작업을 수행하면 다른 작업에 영향을 미치므로 AsyncTask를 사용하여 모두 처리하기로 결정했습니다.이미지 처리는 Context를 사용하기 때문에 AsyncTask의 초기화 프로그램에서 Activity를 전달하기로 했습니다.다음 코드는 AsynkTask에서 모호하게 처리된 예입니다.
    // 非同期でUriから画像を取得してぼかし処理を掛ける
    private class AsyncBlurredCaptureLoader(activity: BlurredModalActivity) : AsyncTask<Uri, Unit, Drawable>() {
        private val activity = WeakReference(activity)
        override fun doInBackground(vararg params: Uri?): Drawable? {
            val uri = params[0] ?: return null
            val capture = loadCapture(uri) ?: return null
    
            val renderScript = activity.get()?.let { RenderScript.create(it) } ?: return null
            val blurredCapture = RSBlurProcessor(renderScript).blur(capture, 25f, 3) ?: return null
            val resources = activity.get()?.resources ?: return null
            return BitmapDrawable(resources, blurredCapture)
        }
    
        override fun onPostExecute(result: Drawable?) {
            super.onPostExecute(result)
            activity.get()?.onLoadBlurredCapture(result)
        }
    
        private fun loadCapture(uri: Uri): Bitmap? {
            try {
                val inputStream = activity.get()?.contentResolver?.openInputStream(uri) ?: return null
                return BitmapFactory.decodeStream(inputStream)
            } catch (e: IOException) {
                e.printStackTrace()
                return null
            }
        }
    }
    
    
    여기서 중요한 점은 Weak Reference에서 Activity를 갖는 것입니다.여기에서 일반 등록 정보를 사용하여 활동을 예약하는 경우 활동을 취소할 때 GC가 올바르게 수행되지 않을 수 있습니다.실제로 Android Studio도 경고This field leaks a context object를 보냅니다.

    견본


    이것은 간단한 실현 예이다.

    GitHub에 코드를 공개합니다.
    https://github.com/niba1122/blurred-activity

    마지막


    안드로이드도 튀어나온 배경을 흐리게 할 수 있다.그러나 설치할 때 메모리, 스레드, 생명주기를 고려해야 하기 때문에 설치에 많은 노력이 필요하다.

    좋은 웹페이지 즐겨찾기