Fix clipping coordinates on RTL

In RTL in landscape, the container for QS and footer was clipping
incorrectly, as it should use its coordinates (not its parent's) for
clipping its children.

Test: manual
Test: atest QSPanelTest, test that views are visible to user
Fixes: 235422445
Change-Id: Idf29a3f17128591eaa3405058ae16d5b09a51f43
This commit is contained in:
Fabian Kozynski
2022-06-09 14:48:24 -04:00
parent 2d3b1c2719
commit 84ffe9f508
2 changed files with 105 additions and 24 deletions

View File

@@ -151,15 +151,17 @@ public class QSPanel extends LinearLayout implements Tunable {
mHorizontalContentContainer.setClipChildren(true);
mHorizontalContentContainer.setClipToPadding(false);
// Don't clip on the top, that way, secondary pages tiles can animate up
// Clipping coordinates should be relative to this view, not absolute (parent coordinates)
mHorizontalContentContainer.addOnLayoutChangeListener(
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
if (left != oldLeft || right != oldRight || bottom != oldBottom) {
mClippingRect.left = left;
mClippingRect.right = right;
mClippingRect.bottom = bottom;
if ((right - left) != (oldRight - oldLeft)
|| ((bottom - top) != (oldBottom - oldTop))) {
mClippingRect.right = right - left;
mClippingRect.bottom = bottom - top;
mHorizontalContentContainer.setClipBounds(mClippingRect);
}
});
mClippingRect.left = 0;
mClippingRect.top = -1000;
mHorizontalContentContainer.setClipBounds(mClippingRect);
}

View File

@@ -13,18 +13,24 @@
*/
package com.android.systemui.qs
import android.graphics.Rect
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.testing.TestableLooper.RunWithLooper
import android.testing.ViewUtils
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.accessibility.AccessibilityNodeInfo
import android.widget.FrameLayout
import android.widget.LinearLayout
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.qs.tileimpl.QSIconViewImpl
import com.android.systemui.qs.tileimpl.QSTileViewImpl
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -36,37 +42,40 @@ import org.mockito.MockitoAnnotations
@RunWithLooper
@SmallTest
class QSPanelTest : SysuiTestCase() {
private lateinit var mTestableLooper: TestableLooper
private lateinit var mQsPanel: QSPanel
private lateinit var testableLooper: TestableLooper
private lateinit var qsPanel: QSPanel
private lateinit var mParentView: ViewGroup
private lateinit var mFooter: View
private lateinit var footer: View
@Before
@Throws(Exception::class)
fun setup() {
MockitoAnnotations.initMocks(this)
mTestableLooper = TestableLooper.get(this)
testableLooper = TestableLooper.get(this)
mTestableLooper.runWithLooper {
mQsPanel = QSPanel(mContext, null)
mQsPanel.initialize()
testableLooper.runWithLooper {
qsPanel = QSPanel(context, null)
qsPanel.mUsingMediaPlayer = true
qsPanel.initialize()
// QSPanel inflates a footer inside of it, mocking it here
mFooter = LinearLayout(mContext).apply { id = R.id.qs_footer }
mQsPanel.addView(mFooter)
mQsPanel.onFinishInflate()
footer = LinearLayout(context).apply { id = R.id.qs_footer }
qsPanel.addView(footer, MATCH_PARENT, 100)
qsPanel.onFinishInflate()
// Provides a parent with non-zero size for QSPanel
mParentView = FrameLayout(mContext).apply {
addView(mQsPanel)
}
ViewUtils.attachView(qsPanel)
}
}
@After
fun tearDown() {
ViewUtils.detachView(qsPanel)
}
@Test
fun testHasCollapseAccessibilityAction() {
val info = AccessibilityNodeInfo(mQsPanel)
mQsPanel.onInitializeAccessibilityNodeInfo(info)
val info = AccessibilityNodeInfo(qsPanel)
qsPanel.onInitializeAccessibilityNodeInfo(info)
assertThat(info.actions and AccessibilityNodeInfo.ACTION_COLLAPSE).isNotEqualTo(0)
assertThat(info.actions and AccessibilityNodeInfo.ACTION_EXPAND).isEqualTo(0)
@@ -75,9 +84,79 @@ class QSPanelTest : SysuiTestCase() {
@Test
fun testCollapseActionCallsRunnable() {
val mockRunnable = mock(Runnable::class.java)
mQsPanel.setCollapseExpandAction(mockRunnable)
qsPanel.setCollapseExpandAction(mockRunnable)
mQsPanel.performAccessibilityAction(AccessibilityNodeInfo.ACTION_COLLAPSE, null)
qsPanel.performAccessibilityAction(AccessibilityNodeInfo.ACTION_COLLAPSE, null)
verify(mockRunnable).run()
}
@Test
fun testTilesFooterVisibleRTLLandscapeMedia() {
qsPanel.layoutDirection = View.LAYOUT_DIRECTION_RTL
// We need at least a tile so the layout has a height
qsPanel.tileLayout?.addTile(
QSPanelControllerBase.TileRecord(
mock(QSTile::class.java),
QSTileViewImpl(context, QSIconViewImpl(context))
)
)
val mediaView = FrameLayout(context)
mediaView.addView(View(context), MATCH_PARENT, 800)
qsPanel.setUsingHorizontalLayout(/* horizontal */ true, mediaView, /* force */ true)
qsPanel.measure(
/* width */ View.MeasureSpec.makeMeasureSpec(3000, View.MeasureSpec.EXACTLY),
/* height */ View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY)
)
qsPanel.layout(0, 0, qsPanel.measuredWidth, qsPanel.measuredHeight)
val tiles = qsPanel.tileLayout as View
// Tiles are effectively to the right of media
assertThat(mediaView isLeftOf tiles)
assertThat(tiles.isVisibleToUser).isTrue()
assertThat(mediaView isLeftOf footer)
assertThat(footer.isVisibleToUser).isTrue()
}
@Test
fun testTilesFooterVisibleLandscapeMedia() {
qsPanel.layoutDirection = View.LAYOUT_DIRECTION_LTR
// We need at least a tile so the layout has a height
qsPanel.tileLayout?.addTile(
QSPanelControllerBase.TileRecord(
mock(QSTile::class.java),
QSTileViewImpl(context, QSIconViewImpl(context))
)
)
val mediaView = FrameLayout(context)
mediaView.addView(View(context), MATCH_PARENT, 800)
qsPanel.setUsingHorizontalLayout(/* horizontal */ true, mediaView, /* force */ true)
qsPanel.measure(
/* width */ View.MeasureSpec.makeMeasureSpec(3000, View.MeasureSpec.EXACTLY),
/* height */ View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY)
)
qsPanel.layout(0, 0, qsPanel.measuredWidth, qsPanel.measuredHeight)
val tiles = qsPanel.tileLayout as View
// Tiles are effectively to the left of media
assertThat(tiles isLeftOf mediaView)
assertThat(tiles.isVisibleToUser).isTrue()
assertThat(footer isLeftOf mediaView)
assertThat(footer.isVisibleToUser).isTrue()
}
private infix fun View.isLeftOf(other: View): Boolean {
val rect = Rect()
getBoundsOnScreen(rect)
val thisRight = rect.right
other.getBoundsOnScreen(rect)
return thisRight <= rect.left
}
}