AbsSeekBar: Fix growRect computation

Fixes an issue with the growRectTo computation where if the
difference between the current and target size wasn't an even
number, the resulting rect would not actually have the correct
size.

Also, asserts using the thumb bounds, rather than the view
bounds in case the thumb is not perfectly centered within the
view due to rounding errors on odd densities.

Fixes: 173872859
Test: atest AbsSeekBarTest
Change-Id: Ib2b81a91ba8feeb6743a4e4a588d6116d231eb8d
This commit is contained in:
Adrian Roos
2021-01-14 13:39:51 +01:00
parent 361e0a91a6
commit c5ce225fdf
2 changed files with 55 additions and 15 deletions

View File

@@ -39,6 +39,7 @@ import android.view.accessibility.AccessibilityNodeInfo;
import android.view.inspector.InspectableProperty;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
import java.util.ArrayList;
@@ -776,17 +777,23 @@ public abstract class AbsSeekBar extends ProgressBar {
/**
* Grows {@code r} from its center such that each dimension is at least {@code minimumSize}.
*
* The result will still have the same {@link Rect#centerX()} and {@link Rect#centerY()} as the
* input.
*
* @hide
*/
private void growRectTo(Rect r, int minimumSize) {
int dy = (minimumSize - r.height()) / 2;
@VisibleForTesting
public void growRectTo(Rect r, int minimumSize) {
int dy = minimumSize - r.height();
if (dy > 0) {
r.top -= dy;
r.bottom += dy;
r.top -= (dy + 1) / 2;
r.bottom += dy / 2;
}
int dx = (minimumSize - r.width()) / 2;
int dx = minimumSize - r.width();
if (dx > 0) {
r.left -= dx;
r.right += dx;
r.left -= (dx + 1) / 2;
r.right += dx / 2;
}
}

View File

@@ -30,7 +30,6 @@ import android.graphics.Rect;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RectShape;
import android.platform.test.annotations.Presubmit;
import android.view.View;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -48,6 +47,7 @@ import java.util.List;
@Presubmit
public class AbsSeekBarTest {
public static final int PADDING = 10;
private Context mContext;
private AbsSeekBar mBar;
@@ -59,34 +59,42 @@ public class AbsSeekBarTest {
@Test
public void testExclusionForThumb_limitedTo48dp() {
mBar.setPadding(10, 10, 10, 10);
mBar.setPadding(PADDING, PADDING, PADDING, PADDING);
mBar.setThumb(newThumb(dpToPxSize(20)));
mBar.setMin(0);
mBar.setMax(100);
mBar.setProgress(50);
final int thumbOffset = mBar.getThumbOffset();
measureAndLayout(dpToPxSize(200), dpToPxSize(100));
List<Rect> exclusions = mBar.getSystemGestureExclusionRects();
assertEquals("exclusions should be size 1, but was " + exclusions, 1, exclusions.size());
assertEquals("exclusion should be centered on thumb",
center(mBar), center(exclusions.get(0)));
center(offset(mBar.getThumb().getBounds(), PADDING - thumbOffset, PADDING)),
center(exclusions.get(0)));
assertEquals("exclusion should be 48dp high", dpToPxSize(48), exclusions.get(0).height());
assertEquals("exclusion should be 48dp wide", dpToPxSize(48), exclusions.get(0).width());
}
@Test
public void testExclusionForThumb_limitedToHeight() {
mBar.setPadding(10, 10, 10, 10);
mBar.setPadding(PADDING, PADDING, PADDING, PADDING);
mBar.setThumb(newThumb(dpToPxSize(20)));
mBar.setMin(0);
mBar.setMax(100);
mBar.setProgress(50);
final int thumbOffset = mBar.getThumbOffset();
measureAndLayout(dpToPxSize(200), dpToPxSize(32));
List<Rect> exclusions = mBar.getSystemGestureExclusionRects();
assertEquals("exclusions should be size 1, but was " + exclusions, 1, exclusions.size());
assertEquals("exclusion should be centered on thumb",
center(mBar), center(exclusions.get(0)));
center(offset(mBar.getThumb().getBounds(), PADDING - thumbOffset, PADDING)),
center(exclusions.get(0)));
assertEquals("exclusion should be 32dp high", dpToPxSize(32), exclusions.get(0).height());
assertEquals("exclusion should be 32dp wide", dpToPxSize(32), exclusions.get(0).width());
}
@@ -95,7 +103,7 @@ public class AbsSeekBarTest {
public void testExclusionForThumb_passesThroughUserExclusions() {
mBar.setSystemGestureExclusionRects(Arrays.asList(new Rect(1, 2, 3, 4)));
mBar.setPadding(10, 10, 10, 10);
mBar.setPadding(PADDING, PADDING, PADDING, PADDING);
mBar.setThumb(newThumb(dpToPxSize(20)));
mBar.setMin(0);
mBar.setMax(100);
@@ -110,12 +118,37 @@ public class AbsSeekBarTest {
assertThat(mBar.getSystemGestureExclusionRects(), hasSize(2));
}
@Test
public void testGrowRectTo_evenInitialDifference() {
doGrowRectTest(new Rect(0, 0, 0, 0), 10, new Rect(-5, -5, 5, 5));
}
@Test
public void testGrowRectTo_unevenInitialDifference() {
doGrowRectTest(new Rect(0, 0, 1, 1), 10, new Rect(-5, -5, 5, 5));
}
@Test
public void testGrowRectTo_unevenInitialDifference_unevenSize() {
doGrowRectTest(new Rect(0, 0, 0, 0), 9, new Rect(-5, -5, 4, 4));
}
public void doGrowRectTest(Rect in, int minimumSize, Rect expected) {
Rect result = new Rect(in);
mBar.growRectTo(result, minimumSize);
assertEquals("grown rect", expected, result);
assertEquals("grown rect center point", center(expected), center(result));
}
private Point center(Rect rect) {
return new Point(rect.centerX(), rect.centerY());
}
private Point center(View view) {
return center(new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()));
private Rect offset(Rect rect, int dx, int dy) {
Rect result = new Rect(rect);
result.offset(dx, dy);
return result;
}
private ShapeDrawable newThumb(int size) {