blob: 544999a38061048223c4ef2af89e275795230d84 [file] [log] [blame]
Noah Wange64cc262015-12-15 09:05:30 -08001/*
2 * Copyright (C) 2015 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
17package com.android.settings;
18
Noah Wange64cc262015-12-15 09:05:30 -080019import android.content.Context;
20import android.content.res.Configuration;
21import android.os.Bundle;
Noah Wang49fabb92016-01-12 09:00:57 -080022import android.support.v4.view.ViewPager;
Noah Wang36e89f62016-03-03 20:05:14 -080023import android.support.v4.view.ViewPager.OnPageChangeListener;
Noah Wange64cc262015-12-15 09:05:30 -080024import android.view.LayoutInflater;
Noah Wange64cc262015-12-15 09:05:30 -080025import android.view.View;
26import android.view.View.OnClickListener;
27import android.view.ViewGroup;
Noah Wang36e89f62016-03-03 20:05:14 -080028import android.view.accessibility.AccessibilityEvent;
Noah Wange64cc262015-12-15 09:05:30 -080029import android.widget.SeekBar;
30import android.widget.SeekBar.OnSeekBarChangeListener;
31import android.widget.TextView;
Noah Wang37c95e42016-04-09 20:53:14 -070032
Noah Wang085028d2016-01-13 16:55:07 -080033import com.android.settings.widget.DotsPageIndicator;
Noah Wang2030f452016-01-25 20:14:42 -080034import com.android.settings.widget.LabeledSeekBar;
Noah Wange64cc262015-12-15 09:05:30 -080035
Noah Wange64cc262015-12-15 09:05:30 -080036/**
37 * Preference fragment shows a preview and a seek bar to adjust a specific settings.
38 */
39public abstract class PreviewSeekBarPreferenceFragment extends SettingsPreferenceFragment {
40
41 /** List of entries corresponding the settings being set. */
42 protected String[] mEntries;
43
44 /** Index of the entry corresponding to initial value of the settings. */
45 protected int mInitialIndex;
46
47 /** Index of the entry corresponding to current value of the settings. */
48 protected int mCurrentIndex;
49
50 /** Resource id of the layout for this preference fragment. */
51 protected int mActivityLayoutResId;
52
Noah Wang36e89f62016-03-03 20:05:14 -080053 /** Resource id of the layout that defines the contents inside preview screen. */
Noah Wang49fabb92016-01-12 09:00:57 -080054 protected int[] mPreviewSampleResIds;
Noah Wange64cc262015-12-15 09:05:30 -080055
Noah Wang49fabb92016-01-12 09:00:57 -080056 private ViewPager mPreviewPager;
57 private PreviewPagerAdapter mPreviewPagerAdapter;
Noah Wang36e89f62016-03-03 20:05:14 -080058 private DotsPageIndicator mPageIndicator;
Noah Wange64cc262015-12-15 09:05:30 -080059
Noah Wange64cc262015-12-15 09:05:30 -080060 private TextView mLabel;
61 private View mLarger;
62 private View mSmaller;
63
Noah Wang33712a72016-01-25 22:32:00 -080064 private class onPreviewSeekBarChangeListener implements OnSeekBarChangeListener {
65 private boolean mSeekByTouch;
66
67 @Override
68 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
69 setPreviewLayer(progress, true);
70 if (!mSeekByTouch) {
71 commit();
72 }
73 }
74
75 @Override
76 public void onStartTrackingTouch(SeekBar seekBar) {
77 mSeekByTouch = true;
78 }
79
80 @Override
81 public void onStopTrackingTouch(SeekBar seekBar) {
Noah Wang6e7d4102016-04-10 03:57:24 -070082 if (mPreviewPagerAdapter.isAnimating()) {
83 mPreviewPagerAdapter.setAnimationEndAction(new Runnable() {
84 @Override
85 public void run() {
86 commit();
87 }
88 });
89 } else {
90 commit();
91 }
Noah Wang33712a72016-01-25 22:32:00 -080092 mSeekByTouch = false;
93 }
94 }
95
Noah Wange64cc262015-12-15 09:05:30 -080096 @Override
97 public View onCreateView(LayoutInflater inflater, ViewGroup container,
98 Bundle savedInstanceState) {
99 final View root = super.onCreateView(inflater, container, savedInstanceState);
100 final ViewGroup listContainer = (ViewGroup) root.findViewById(android.R.id.list_container);
101 listContainer.removeAllViews();
102
103 final View content = inflater.inflate(mActivityLayoutResId, listContainer, false);
104 listContainer.addView(content);
105
106 mLabel = (TextView) content.findViewById(R.id.current_label);
107
108 // The maximum SeekBar value always needs to be non-zero. If there's
109 // only one available value, we'll handle this by disabling the
110 // seek bar.
111 final int max = Math.max(1, mEntries.length - 1);
112
Noah Wang2030f452016-01-25 20:14:42 -0800113 final LabeledSeekBar seekBar = (LabeledSeekBar) content.findViewById(R.id.seek_bar);
114 seekBar.setLabels(mEntries);
Noah Wange64cc262015-12-15 09:05:30 -0800115 seekBar.setMax(max);
116 seekBar.setProgress(mInitialIndex);
Noah Wang33712a72016-01-25 22:32:00 -0800117 seekBar.setOnSeekBarChangeListener(new onPreviewSeekBarChangeListener());
Noah Wange64cc262015-12-15 09:05:30 -0800118
119 mSmaller = content.findViewById(R.id.smaller);
120 mSmaller.setOnClickListener(new OnClickListener() {
121 @Override
122 public void onClick(View v) {
123 final int progress = seekBar.getProgress();
124 if (progress > 0) {
125 seekBar.setProgress(progress - 1, true);
126 }
127 }
128 });
129
130 mLarger = content.findViewById(R.id.larger);
131 mLarger.setOnClickListener(new OnClickListener() {
132 @Override
133 public void onClick(View v) {
134 final int progress = seekBar.getProgress();
135 if (progress < seekBar.getMax()) {
136 seekBar.setProgress(progress + 1, true);
137 }
138 }
139 });
140
141 if (mEntries.length == 1) {
142 // The larger and smaller buttons will be disabled when we call
143 // setPreviewLayer() later in this method.
144 seekBar.setEnabled(false);
145 }
146
Fan Zhangcafe6972016-07-21 13:28:19 -0700147 final Context context = getContext();
Noah Wange64cc262015-12-15 09:05:30 -0800148 final Configuration origConfig = context.getResources().getConfiguration();
Noah Wang37c95e42016-04-09 20:53:14 -0700149 final boolean isLayoutRtl = origConfig.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
Noah Wang49fabb92016-01-12 09:00:57 -0800150 Configuration[] configurations = new Configuration[mEntries.length];
Noah Wange64cc262015-12-15 09:05:30 -0800151 for (int i = 0; i < mEntries.length; ++i) {
Noah Wang49fabb92016-01-12 09:00:57 -0800152 configurations[i] = createConfig(origConfig, i);
Noah Wange64cc262015-12-15 09:05:30 -0800153 }
154
Noah Wang49fabb92016-01-12 09:00:57 -0800155 mPreviewPager = (ViewPager) content.findViewById(R.id.preview_pager);
Noah Wang35a95612016-04-15 13:49:12 -0700156 mPreviewPagerAdapter = new PreviewPagerAdapter(context, isLayoutRtl,
157 mPreviewSampleResIds, configurations);
158 mPreviewPager.setAdapter(mPreviewPagerAdapter);
159 mPreviewPager.setCurrentItem(isLayoutRtl ? mPreviewSampleResIds.length - 1 : 0);
160 mPreviewPager.addOnPageChangeListener(mPreviewPageChangeListener);
Noah Wang45393212016-04-13 10:18:45 -0700161
Noah Wang35a95612016-04-15 13:49:12 -0700162 mPageIndicator = (DotsPageIndicator) content.findViewById(R.id.page_indicator);
163 if (mPreviewSampleResIds.length > 1) {
164 mPageIndicator.setViewPager(mPreviewPager);
165 mPageIndicator.setVisibility(View.VISIBLE);
166 mPageIndicator.setOnPageChangeListener(mPageIndicatorPageChangeListener);
167 } else {
168 mPageIndicator.setVisibility(View.GONE);
Noah Wang085028d2016-01-13 16:55:07 -0800169 }
170
Noah Wang49fabb92016-01-12 09:00:57 -0800171 setPreviewLayer(mInitialIndex, false);
Noah Wange64cc262015-12-15 09:05:30 -0800172 return root;
173 }
174
Noah Wange64cc262015-12-15 09:05:30 -0800175 /**
176 * Creates new configuration based on the current position of the SeekBar.
177 */
178 protected abstract Configuration createConfig(Configuration origConfig, int index);
179
Noah Wang45393212016-04-13 10:18:45 -0700180 /**
181 * Persists the selected value and sends a configuration change.
182 */
183 protected abstract void commit();
184
Noah Wange64cc262015-12-15 09:05:30 -0800185 private void setPreviewLayer(int index, boolean animate) {
186 mLabel.setText(mEntries[index]);
Noah Wange64cc262015-12-15 09:05:30 -0800187 mSmaller.setEnabled(index > 0);
188 mLarger.setEnabled(index < mEntries.length - 1);
Noah Wang35a95612016-04-15 13:49:12 -0700189 setPagerIndicatorContentDescription(mPreviewPager.getCurrentItem());
190 mPreviewPagerAdapter.setPreviewLayer(index, mCurrentIndex,
191 mPreviewPager.getCurrentItem(), animate);
Noah Wange64cc262015-12-15 09:05:30 -0800192
Noah Wange64cc262015-12-15 09:05:30 -0800193 mCurrentIndex = index;
194 }
195
Noah Wang36e89f62016-03-03 20:05:14 -0800196 private void setPagerIndicatorContentDescription(int position) {
197 mPageIndicator.setContentDescription(
198 getPrefContext().getString(R.string.preview_page_indicator_content_description,
199 position + 1, mPreviewSampleResIds.length));
200 }
201
Noah Wang45393212016-04-13 10:18:45 -0700202 private OnPageChangeListener mPreviewPageChangeListener = new OnPageChangeListener() {
203 @Override
204 public void onPageScrollStateChanged(int state) {
205 // Do nothing.
206 }
207
208 @Override
209 public void onPageScrolled(int position, float positionOffset,
210 int positionOffsetPixels) {
211 // Do nothing.
212 }
213
214 @Override
215 public void onPageSelected(int position) {
216 mPreviewPager.sendAccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT);
217 }
218 };
219
220 private OnPageChangeListener mPageIndicatorPageChangeListener = new OnPageChangeListener() {
221 @Override
222 public void onPageScrollStateChanged(int state) {
223 // Do nothing.
224 }
225
226 @Override
227 public void onPageScrolled(int position, float positionOffset,
228 int positionOffsetPixels) {
229 // Do nothing.
230 }
231
232 @Override
233 public void onPageSelected(int position) {
234 setPagerIndicatorContentDescription(position);
235 }
236 };
Noah Wange64cc262015-12-15 09:05:30 -0800237}