diff --git a/src/com/android/settings/widget/RtlCompatibleViewPager.java b/src/com/android/settings/widget/RtlCompatibleViewPager.java index f74ea2454a7..16fc08ca2ca 100644 --- a/src/com/android/settings/widget/RtlCompatibleViewPager.java +++ b/src/com/android/settings/widget/RtlCompatibleViewPager.java @@ -17,10 +17,12 @@ package com.android.settings.widget; import android.content.Context; +import android.os.Parcelable; import android.support.v4.view.ViewPager; import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; +import android.os.Parcel; import java.util.Locale; @@ -54,6 +56,23 @@ public final class RtlCompatibleViewPager extends ViewPager { super.setCurrentItem(getRtlAwareIndex(item)); } + @Override + public Parcelable onSaveInstanceState() { + Parcelable parcelable = super.onSaveInstanceState(); + + RtlSavedState rtlSavedState = new RtlSavedState(parcelable); + rtlSavedState.position = getCurrentItem(); + return rtlSavedState; + } + + @Override + public void onRestoreInstanceState(Parcelable state) { + RtlSavedState rtlSavedState = (RtlSavedState) state; + super.onRestoreInstanceState(rtlSavedState.getSuperState()); + + setCurrentItem(rtlSavedState.position); + } + /** * Get a "RTL friendly" index. If the locale is LTR, the index is returned as is. * Otherwise it's transformed so view pager can render views using the new index for RTL. For @@ -70,4 +89,38 @@ public final class RtlCompatibleViewPager extends ViewPager { } return index; } + + static class RtlSavedState extends BaseSavedState { + int position; + + public RtlSavedState(Parcelable superState) { + super(superState); + } + + private RtlSavedState(Parcel in) { + super(in); + position = in.readInt(); + } + + @Override + public void writeToParcel(Parcel out, int flags) { + super.writeToParcel(out, flags); + out.writeInt(position); + } + + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + @Override + public RtlSavedState createFromParcel(Parcel in) { + return new RtlSavedState(in); + } + + @Override + public RtlSavedState[] newArray(int size) { + return new RtlSavedState[size]; + } + }; + + } + } diff --git a/tests/robotests/src/com/android/settings/shadow/ShadowTextUtils.java b/tests/robotests/src/com/android/settings/shadow/ShadowTextUtils.java new file mode 100644 index 00000000000..4a98f6a23c4 --- /dev/null +++ b/tests/robotests/src/com/android/settings/shadow/ShadowTextUtils.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2016 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.settings.shadow; + +import android.icu.util.ULocale; +import android.os.SystemProperties; +import android.provider.Settings; +import android.text.TextUtils; +import android.view.View; +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; + +import java.util.Locale; + +/** + * Important: The current robolectric doesn't support API 24, so I copy the code + * from API 24 here to make it compatible. Once robolectric is upgraded to 24, + * We can delete this shadow class. + **/ +@Implements(TextUtils.class) +public class ShadowTextUtils { + + @Implementation + public static int getLayoutDirectionFromLocale(Locale locale) { + return ((locale != null && !locale.equals(Locale.ROOT) + && ULocale.forLocale(locale).isRightToLeft()) + // If forcing into RTL layout mode, return RTL as default + || SystemProperties.getBoolean(Settings.Global.DEVELOPMENT_FORCE_RTL, false)) + ? View.LAYOUT_DIRECTION_RTL + : View.LAYOUT_DIRECTION_LTR; + } + +} diff --git a/tests/robotests/src/com/android/settings/widget/RtlCompatibleViewPagerTest.java b/tests/robotests/src/com/android/settings/widget/RtlCompatibleViewPagerTest.java new file mode 100644 index 00000000000..b56f7141453 --- /dev/null +++ b/tests/robotests/src/com/android/settings/widget/RtlCompatibleViewPagerTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2016 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.settings.widget; + +import android.annotation.Nullable; +import android.app.Activity; +import android.os.Bundle; +import android.os.Parcelable; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewGroup; +import com.android.settings.TestConfig; +import com.android.settings.shadow.ShadowTextUtils; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.assertEquals; + +import java.util.Locale; + +import android.support.v4.view.PagerAdapter; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; +import org.robolectric.Robolectric; + +@RunWith(RobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class RtlCompatibleViewPagerTest { + private ViewPagerTestActivity mTestActivity; + private RtlCompatibleViewPager mTestViewPager; + private Locale mLocaleEn; + private Locale mLocaleHe; + + @Before + public void setUp() { + mTestActivity = Robolectric.setupActivity(ViewPagerTestActivity.class); + mTestViewPager = mTestActivity.getViewPager(); + mLocaleEn = new Locale("en"); + mLocaleHe = new Locale("he"); + } + + @Test + @Config(shadows = {ShadowTextUtils.class}) + public void testRtlCompatible() { + testRtlCompatibleInner(0); + testRtlCompatibleInner(1); + } + + private void testRtlCompatibleInner(int currentItem) { + // Set up the environment + Locale.setDefault(mLocaleEn); + assertEquals(View.LAYOUT_DIRECTION_LTR, + TextUtils.getLayoutDirectionFromLocale(Locale.getDefault())); + mTestViewPager.setCurrentItem(currentItem); + assertEquals(currentItem, mTestViewPager.getCurrentItem()); + + // Simulate to change the language to RTL + Parcelable savedInstance = mTestViewPager.onSaveInstanceState(); + Locale.setDefault(mLocaleHe); + assertEquals(View.LAYOUT_DIRECTION_RTL, + TextUtils.getLayoutDirectionFromLocale(Locale.getDefault())); + mTestViewPager.onRestoreInstanceState(savedInstance); + + assertEquals(currentItem, mTestViewPager.getCurrentItem()); + } + + + /** + * Test activity that contains RTL viewpager + */ + private static class ViewPagerTestActivity extends Activity { + private RtlCompatibleViewPager mViewPager; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mViewPager = new RtlCompatibleViewPager(ViewPagerTestActivity.this); + mViewPager.setAdapter(new ViewPagerAdapter()); + + setContentView(mViewPager); + } + + public RtlCompatibleViewPager getViewPager() { + return mViewPager; + } + } + + /** + * Test viewpager adapter, uses 2 view to test it + */ + private static final class ViewPagerAdapter extends PagerAdapter { + + private static final int ITEM_COUNT = 2; + + public ViewPagerAdapter() { + } + + @Override + public int getCount() { + return ITEM_COUNT; + } + + @Override + public boolean isViewFromObject(View view, Object object) { + return view == object; + } + + @Override + public void destroyItem(ViewGroup collection, int position, Object view) { + collection.removeView((View) view); + } + + @Override + public Object instantiateItem(ViewGroup container, int position) { + return null; + } + + @Override + public CharSequence getPageTitle(int position) { + return null; + } + } +}