Home | History | Annotate | Download | only in widget
      1 /*
      2  * Copyright 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package androidx.percentlayout.widget;
     17 
     18 import static android.support.test.espresso.Espresso.onView;
     19 import static android.support.test.espresso.matcher.ViewMatchers.withId;
     20 
     21 import android.os.Build;
     22 import android.support.test.filters.SmallTest;
     23 import android.view.View;
     24 
     25 import androidx.core.view.ViewCompat;
     26 import androidx.percentlayout.test.R;
     27 
     28 import org.junit.Before;
     29 import org.junit.Test;
     30 
     31 /**
     32  * The arrangement of child views in the layout class in the default LTR (left-to-right) direction
     33  * is as follows:
     34  *
     35  *  +---------------------------------------------+
     36  *  |                                             |
     37  *  |    TTTTTTTTTTTTTTTTTTTTT                    |
     38  *  |                                             |
     39  *  | S                                           |
     40  *  | S           CCCCCCCCCCCCCCCCCC              |
     41  *  | S           CCCCCCCCCCCCCCCCCC              |
     42  *  | S           CCCCCCCCCCCCCCCCCC           E  |
     43  *  | S           CCCCCCCCCCCCCCCCCC           E  |
     44  *  | S           CCCCCCCCCCCCCCCCCC           E  |
     45  *  |             CCCCCCCCCCCCCCCCCC           E  |
     46  *  |             CCCCCCCCCCCCCCCCCC           E  |
     47  *  |                                          E  |
     48  *  |                                             |
     49  *  |                    BBBBBBBBBBBBBBBBBBBBB    |
     50  *  |                                             |
     51  *  +---------------------------------------------+
     52  *
     53  * The arrangement of child views in the layout class in the RTL (right-to-left) direction
     54  * is as follows:
     55  *
     56  *  +---------------------------------------------+
     57  *  |                                             |
     58  *  |                    TTTTTTTTTTTTTTTTTTTTT    |
     59  *  |                                             |
     60  *  |                                          S  |
     61  *  |             CCCCCCCCCCCCCCCCCC           S  |
     62  *  |             CCCCCCCCCCCCCCCCCC           S  |
     63  *  | E           CCCCCCCCCCCCCCCCCC           S  |
     64  *  | E           CCCCCCCCCCCCCCCCCC           S  |
     65  *  | E           CCCCCCCCCCCCCCCCCC           S  |
     66  *  | E           CCCCCCCCCCCCCCCCCC              |
     67  *  | E           CCCCCCCCCCCCCCCCCC              |
     68  *  | E                                           |
     69  *  |                                             |
     70  *  |    BBBBBBBBBBBBBBBBBBBBB                    |
     71  *  |                                             |
     72  *  +---------------------------------------------+
     73  *
     74  * Child views are exercising the following percent-based constraints supported by
     75  * <code>PercentRelativeLayout</code>:
     76  *
     77  * <ul>
     78  *     <li>Top child (marked with T) - width, aspect ratio, top margin, start margin.</li>
     79  *     <li>Start child (marked with S) - height, aspect ratio, top margin, start margin.</li>
     80  *     <li>Bottom child (marked with B) - width, aspect ratio, bottom margin, end margin.</li>
     81  *     <li>Right child (marked with E) - height, aspect ratio, bottom margin, end margin.</li>
     82  *     <li>Center child (marked with C) - margin (all sides) from the other four children.</li>
     83  * </ul>
     84  *
     85  * Under LTR direction (pre-v17 devices and v17+ with default direction of en-US locale) we are
     86  * testing the same assertions as <code>PercentRelativeTest</code>. Under RTL direction (on v17+
     87  * devices with Espresso-powered direction switch) we are testing the reverse assertions along the
     88  * X axis for all child views.
     89  *
     90  * Note that due to a bug in the core {@link RelativeLayout} (base class of
     91  * {@link PercentRelativeLayout}) in how it treats end margin of child views on v17 devices, we are
     92  * skipping all tests in this class for v17 devices. This is in line with the overall contract
     93  * of percent-based layouts provided by the support library - we do not work around / fix bugs in
     94  * the core classes, but rather just provide a translation layer between percentage-based values
     95  * and pixel-based ones.
     96  */
     97 @SmallTest
     98 public class PercentRelativeRtlTest extends BaseInstrumentationTestCase<TestRelativeRtlActivity> {
     99     private PercentRelativeLayout mPercentRelativeLayout;
    100     private int mContainerWidth;
    101     private int mContainerHeight;
    102 
    103     public PercentRelativeRtlTest() {
    104         super(TestRelativeRtlActivity.class);
    105     }
    106 
    107     @Before
    108     public void setUp() throws Exception {
    109         final TestRelativeRtlActivity activity = mActivityTestRule.getActivity();
    110         mPercentRelativeLayout = (PercentRelativeLayout) activity.findViewById(R.id.container);
    111         mContainerWidth = mPercentRelativeLayout.getWidth();
    112         mContainerHeight = mPercentRelativeLayout.getHeight();
    113     }
    114 
    115     private void switchToRtl() {
    116         // Force the container to RTL mode
    117         onView(withId(R.id.container)).perform(
    118                 LayoutDirectionActions.setLayoutDirection(ViewCompat.LAYOUT_DIRECTION_RTL));
    119 
    120         // Force a full measure + layout pass on the container
    121         mPercentRelativeLayout.measure(
    122                 View.MeasureSpec.makeMeasureSpec(mContainerWidth, View.MeasureSpec.EXACTLY),
    123                 View.MeasureSpec.makeMeasureSpec(mContainerHeight, View.MeasureSpec.EXACTLY));
    124         mPercentRelativeLayout.layout(mPercentRelativeLayout.getLeft(),
    125                 mPercentRelativeLayout.getTop(), mPercentRelativeLayout.getRight(),
    126                 mPercentRelativeLayout.getBottom());
    127     }
    128 
    129     @Test
    130     public void testTopChild() {
    131         if (Build.VERSION.SDK_INT == 17) {
    132             return;
    133         }
    134         final View childToTest = mPercentRelativeLayout.findViewById(R.id.child_top);
    135 
    136         if (Build.VERSION.SDK_INT >= 17) {
    137             switchToRtl();
    138 
    139             final int childRight = childToTest.getRight();
    140             assertFuzzyEquals("Child start margin as 20% of the container",
    141                     0.2f * mContainerWidth, mContainerWidth - childRight);
    142         } else {
    143             final int childLeft = childToTest.getLeft();
    144             assertFuzzyEquals("Child start margin as 20% of the container",
    145                     0.2f * mContainerWidth, childLeft);
    146         }
    147 
    148         final int childTop = childToTest.getTop();
    149         assertFuzzyEquals("Child top margin as 5% of the container",
    150                 0.05f * mContainerHeight, childTop);
    151 
    152         final int childWidth = childToTest.getWidth();
    153         final int childHeight = childToTest.getHeight();
    154 
    155         assertFuzzyEquals("Child width as 50% of the container",
    156                 0.5f * mContainerWidth, childWidth);
    157         assertFuzzyEquals("Child aspect ratio of 2000%",
    158                 0.05f * childWidth, childHeight);
    159     }
    160 
    161     @Test
    162     public void testStartChild() {
    163         if (Build.VERSION.SDK_INT == 17) {
    164             return;
    165         }
    166         final View childToTest = mPercentRelativeLayout.findViewById(R.id.child_start);
    167 
    168         if (Build.VERSION.SDK_INT >= 17) {
    169             switchToRtl();
    170 
    171             final int childRight = childToTest.getRight();
    172             assertFuzzyEquals("Child start margin as 5% of the container",
    173                     0.05f * mContainerWidth, mContainerWidth - childRight);
    174         } else {
    175             final int childLeft = childToTest.getLeft();
    176             assertFuzzyEquals("Child start margin as 5% of the container",
    177                     0.05f * mContainerWidth, childLeft);
    178         }
    179 
    180         final int childWidth = childToTest.getWidth();
    181         final int childHeight = childToTest.getHeight();
    182 
    183         assertFuzzyEquals("Child height as 50% of the container",
    184                 0.5f * mContainerHeight, childHeight);
    185         assertFuzzyEquals("Child aspect ratio of 5%",
    186                 0.05f * childHeight, childWidth);
    187 
    188         final int childTop = childToTest.getTop();
    189 
    190         assertFuzzyEquals("Child top margin as 20% of the container",
    191                 0.2f * mContainerHeight, childTop);
    192     }
    193 
    194     @Test
    195     public void testBottomChild() {
    196         if (Build.VERSION.SDK_INT == 17) {
    197             return;
    198         }
    199         final View childToTest = mPercentRelativeLayout.findViewById(R.id.child_bottom);
    200 
    201         if (Build.VERSION.SDK_INT >= 17) {
    202             switchToRtl();
    203 
    204             final int childLeft = childToTest.getLeft();
    205             assertFuzzyEquals("Child end margin as 20% of the container",
    206                     0.2f * mContainerWidth, childLeft);
    207         } else {
    208             final int childRight = childToTest.getRight();
    209             assertFuzzyEquals("Child end margin as 20% of the container",
    210                     0.2f * mContainerWidth, mContainerWidth - childRight);
    211         }
    212 
    213 
    214         final int childWidth = childToTest.getWidth();
    215         final int childHeight = childToTest.getHeight();
    216 
    217         assertFuzzyEquals("Child width as 40% of the container",
    218                 0.4f * mContainerWidth, childWidth);
    219         assertFuzzyEquals("Child aspect ratio of 2000%",
    220                 0.05f * childWidth, childHeight);
    221 
    222         final int childBottom = childToTest.getBottom();
    223 
    224         assertFuzzyEquals("Child bottom margin as 5% of the container",
    225                 0.05f * mContainerHeight, mContainerHeight - childBottom);
    226     }
    227 
    228     @Test
    229     public void testEndChild() {
    230         if (Build.VERSION.SDK_INT == 17) {
    231             return;
    232         }
    233         final View childToTest = mPercentRelativeLayout.findViewById(R.id.child_end);
    234 
    235         if (Build.VERSION.SDK_INT >= 17) {
    236             switchToRtl();
    237 
    238             final int childLeft = childToTest.getLeft();
    239             assertFuzzyEquals("Child end margin as 5% of the container",
    240                     0.05f * mContainerWidth, childLeft);
    241         } else {
    242             final int childRight = childToTest.getRight();
    243             assertFuzzyEquals("Child end margin as 5% of the container",
    244                     0.05f * mContainerWidth, mContainerWidth - childRight);
    245         }
    246 
    247         final int childWidth = childToTest.getWidth();
    248         final int childHeight = childToTest.getHeight();
    249 
    250         assertFuzzyEquals("Child height as 50% of the container",
    251                 0.4f * mContainerHeight, childHeight);
    252         assertFuzzyEquals("Child aspect ratio of 5%",
    253                 0.05f * childHeight, childWidth);
    254 
    255         final int childBottom = childToTest.getBottom();
    256 
    257         assertFuzzyEquals("Child bottom margin as 20% of the container",
    258                 0.2f * mContainerHeight, mContainerHeight - childBottom);
    259     }
    260 
    261     @Test
    262     public void testCenterChild() {
    263         if (Build.VERSION.SDK_INT == 17) {
    264             return;
    265         }
    266         final View childToTest = mPercentRelativeLayout.findViewById(R.id.child_center);
    267 
    268         boolean supportsRtl = Build.VERSION.SDK_INT >= 17;
    269         if (supportsRtl) {
    270             switchToRtl();
    271         }
    272 
    273         final int childLeft = childToTest.getLeft();
    274         final int childTop = childToTest.getTop();
    275         final int childRight = childToTest.getRight();
    276         final int childBottom = childToTest.getBottom();
    277 
    278         final View leftChild = supportsRtl
    279                 ? mPercentRelativeLayout.findViewById(R.id.child_end)
    280                 : mPercentRelativeLayout.findViewById(R.id.child_start);
    281         assertFuzzyEquals("Child left margin as 10% of the container",
    282                 leftChild.getRight() + 0.1f * mContainerWidth, childLeft);
    283 
    284         final View topChild = mPercentRelativeLayout.findViewById(R.id.child_top);
    285         assertFuzzyEquals("Child top margin as 10% of the container",
    286                 topChild.getBottom() + 0.1f * mContainerHeight, childTop);
    287 
    288         final View rightChild = supportsRtl
    289                 ? mPercentRelativeLayout.findViewById(R.id.child_start)
    290                 : mPercentRelativeLayout.findViewById(R.id.child_end);
    291         assertFuzzyEquals("Child right margin as 10% of the container",
    292                 rightChild.getLeft() - 0.1f * mContainerWidth, childRight);
    293 
    294         final View bottomChild = mPercentRelativeLayout.findViewById(R.id.child_bottom);
    295         assertFuzzyEquals("Child bottom margin as 10% of the container",
    296                 bottomChild.getTop() - 0.1f * mContainerHeight, childBottom);
    297     }
    298 }
    299