Merge "Create PrecomputedTextView for Notifications" into udc-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
d5187d6c35
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.statusbar.notification.row
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.widget.RemoteViews
|
||||
import com.android.internal.widget.ImageFloatingTextView
|
||||
|
||||
/** Precomputed version of [ImageFloatingTextView] */
|
||||
@RemoteViews.RemoteView
|
||||
class PrecomputedImageFloatingTextView
|
||||
@JvmOverloads
|
||||
constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
|
||||
ImageFloatingTextView(context, attrs, defStyleAttr), TextPrecomputer {
|
||||
|
||||
override fun setTextAsync(text: CharSequence?): Runnable = precompute(this, text)
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.systemui.statusbar.notification.row
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.widget.RemoteViews
|
||||
import android.widget.TextView
|
||||
|
||||
/**
|
||||
* A user interface element that uses the PrecomputedText API to display text in a notification,
|
||||
* with the help of RemoteViews.
|
||||
*/
|
||||
@RemoteViews.RemoteView
|
||||
class PrecomputedTextView
|
||||
@JvmOverloads
|
||||
constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
|
||||
TextView(context, attrs, defStyleAttr), TextPrecomputer {
|
||||
|
||||
override fun setTextAsync(text: CharSequence?): Runnable = precompute(this, text)
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.statusbar.notification.row
|
||||
|
||||
import android.text.PrecomputedText
|
||||
import android.text.Spannable
|
||||
import android.util.Log
|
||||
import android.widget.TextView
|
||||
|
||||
internal interface TextPrecomputer {
|
||||
/**
|
||||
* Creates PrecomputedText from given text and returns a runnable which sets precomputed text to
|
||||
* the textview on main thread.
|
||||
*
|
||||
* @param text text to be converted to PrecomputedText
|
||||
* @return Runnable that sets precomputed text on the main thread
|
||||
*/
|
||||
fun precompute(
|
||||
textView: TextView,
|
||||
text: CharSequence?,
|
||||
logException: Boolean = true
|
||||
): Runnable {
|
||||
val precomputedText: Spannable? =
|
||||
text?.let { PrecomputedText.create(it, textView.textMetricsParams) }
|
||||
|
||||
return Runnable {
|
||||
try {
|
||||
textView.text = precomputedText
|
||||
} catch (exception: IllegalArgumentException) {
|
||||
if (logException) {
|
||||
Log.wtf(
|
||||
/* tag = */ TAG,
|
||||
/* msg = */ "PrecomputedText setText failed for TextView:$textView",
|
||||
/* tr = */ exception
|
||||
)
|
||||
}
|
||||
textView.text = text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val TAG = "TextPrecomputer"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.statusbar.notification.row
|
||||
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.testing.TestableLooper.RunWithLooper
|
||||
import android.text.PrecomputedText
|
||||
import android.text.TextPaint
|
||||
import android.widget.TextView
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@RunWithLooper
|
||||
class TextPrecomputerTest : SysuiTestCase() {
|
||||
|
||||
private lateinit var textPrecomputer: TextPrecomputer
|
||||
|
||||
private lateinit var textView: TextView
|
||||
|
||||
@Before
|
||||
fun before() {
|
||||
textPrecomputer = object : TextPrecomputer {}
|
||||
textView = TextView(mContext)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun precompute_returnRunnable() {
|
||||
// WHEN
|
||||
val precomputeResult = textPrecomputer.precompute(textView, TEXT)
|
||||
|
||||
// THEN
|
||||
assertThat(precomputeResult).isInstanceOf(Runnable::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun precomputeRunnable_anyText_setPrecomputedText() {
|
||||
// WHEN
|
||||
textPrecomputer.precompute(textView, TEXT).run()
|
||||
|
||||
// THEN
|
||||
assertThat(textView.text).isInstanceOf(PrecomputedText::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun precomputeRunnable_differentPrecomputedTextConfig_notSetPrecomputedText() {
|
||||
// GIVEN
|
||||
val precomputedTextRunnable =
|
||||
textPrecomputer.precompute(textView, TEXT, logException = false)
|
||||
|
||||
// WHEN
|
||||
textView.textMetricsParams = PrecomputedText.Params.Builder(PAINT).build()
|
||||
precomputedTextRunnable.run()
|
||||
|
||||
// THEN
|
||||
assertThat(textView.text).isInstanceOf(String::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun precomputeRunnable_nullText_setNull() {
|
||||
// GIVEN
|
||||
textView.text = TEXT
|
||||
val precomputedTextRunnable = textPrecomputer.precompute(textView, null)
|
||||
|
||||
// WHEN
|
||||
precomputedTextRunnable.run()
|
||||
|
||||
// THEN
|
||||
assertThat(textView.text).isEqualTo("")
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val PAINT = TextPaint()
|
||||
private const val TEXT = "Example Notification Test"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user