1/* 2 * Copyright (C) 2008 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 android.util; 18 19import com.google.android.collect.Lists; 20 21import android.app.Activity; 22import android.content.Context; 23import android.os.Bundle; 24import android.view.View; 25import android.view.ViewGroup; 26import android.view.Window; 27import android.widget.Button; 28import android.widget.LinearLayout; 29import android.widget.ScrollView; 30import android.widget.TextView; 31 32import java.util.List; 33 34/** 35 * Utility base class for creating scroll view scenarios, allowing you to add 36 * a series of different kinds of views arranged vertically, taking up a 37 * specified amount of the screen height. 38 */ 39public abstract class ScrollViewScenario extends Activity { 40 41 /** 42 * Holds content of scroll view 43 */ 44 private LinearLayout mLinearLayout; 45 46 /** 47 * The actual scroll view 48 */ 49 private ScrollView mScrollView; 50 51 52 /** 53 * What we need of each view that the user wants: the view, and the ratio 54 * to the screen height for its desired height. 55 */ 56 private interface ViewFactory { 57 View create(final Context context); 58 59 float getHeightRatio(); 60 } 61 62 /** 63 * Partially implement ViewFactory given a height ratio. 64 */ 65 private static abstract class ViewFactoryBase implements ViewFactory { 66 67 private float mHeightRatio; 68 69 @SuppressWarnings({"UnusedDeclaration"}) 70 private ViewFactoryBase() {throw new UnsupportedOperationException("don't call this!");} 71 72 protected ViewFactoryBase(float heightRatio) { 73 mHeightRatio = heightRatio; 74 } 75 76 public float getHeightRatio() { 77 return mHeightRatio; 78 } 79 } 80 81 /** 82 * Builder for selecting the views to be vertically arranged in the scroll 83 * view. 84 */ 85 @SuppressWarnings({"JavaDoc"}) 86 public static class Params { 87 88 List<ViewFactory> mViewFactories = Lists.newArrayList(); 89 90 /** 91 * Add a text view. 92 * @param text The text of the text view. 93 * @param heightRatio The view's height will be this * the screen height. 94 */ 95 public Params addTextView(final String text, float heightRatio) { 96 mViewFactories.add(new ViewFactoryBase(heightRatio) { 97 public View create(final Context context) { 98 final TextView tv = new TextView(context); 99 tv.setText(text); 100 return tv; 101 } 102 }); 103 return this; 104 } 105 106 /** 107 * Add multiple text views. 108 * @param numViews the number of views to add. 109 * @param textPrefix The text to prepend to each text view. 110 * @param heightRatio The view's height will be this * the screen height. 111 */ 112 public Params addTextViews(int numViews, String textPrefix, float heightRatio) { 113 for (int i = 0; i < numViews; i++) { 114 addTextView(textPrefix + i, heightRatio); 115 } 116 return this; 117 } 118 119 /** 120 * Add a button. 121 * @param text The text of the button. 122 * @param heightRatio The view's height will be this * the screen height. 123 */ 124 public Params addButton(final String text, float heightRatio) { 125 mViewFactories.add(new ViewFactoryBase(heightRatio) { 126 public View create(final Context context) { 127 final Button button = new Button(context); 128 button.setText(text); 129 return button; 130 } 131 }); 132 return this; 133 } 134 135 /** 136 * Add multiple buttons. 137 * @param numButtons the number of views to add. 138 * @param textPrefix The text to prepend to each button. 139 * @param heightRatio The view's height will be this * the screen height. 140 */ 141 public Params addButtons(int numButtons, String textPrefix, float heightRatio) { 142 for (int i = 0; i < numButtons; i++) { 143 addButton(textPrefix + i, heightRatio); 144 } 145 return this; 146 } 147 148 /** 149 * Add an {@link InternalSelectionView}. 150 * @param numRows The number of rows in the internal selection view. 151 * @param heightRatio The view's height will be this * the screen height. 152 */ 153 public Params addInternalSelectionView(final int numRows, float heightRatio) { 154 mViewFactories.add(new ViewFactoryBase(heightRatio) { 155 public View create(final Context context) { 156 return new InternalSelectionView(context, numRows, "isv"); 157 } 158 }); 159 return this; 160 } 161 162 /** 163 * Add a sublayout of buttons as a single child of the scroll view. 164 * @param numButtons The number of buttons in the sub layout 165 * @param heightRatio The layout's height will be this * the screen height. 166 */ 167 public Params addVerticalLLOfButtons(final String prefix, final int numButtons, float heightRatio) { 168 mViewFactories.add(new ViewFactoryBase(heightRatio) { 169 170 public View create(Context context) { 171 final LinearLayout ll = new LinearLayout(context); 172 ll.setOrientation(LinearLayout.VERTICAL); 173 174 // fill width, equally weighted on height 175 final LinearLayout.LayoutParams lp = 176 new LinearLayout.LayoutParams( 177 ViewGroup.LayoutParams.MATCH_PARENT, 0, 1f); 178 for (int i = 0; i < numButtons; i++) { 179 final Button button = new Button(context); 180 button.setText(prefix + i); 181 ll.addView(button, lp); 182 } 183 184 return ll; 185 } 186 }); 187 return this; 188 } 189 } 190 191 /** 192 * Override this and initialized the views in the scroll view. 193 * @param params Used to configure the contents of the scroll view. 194 */ 195 protected abstract void init(Params params); 196 197 public LinearLayout getLinearLayout() { 198 return mLinearLayout; 199 } 200 201 public ScrollView getScrollView() { 202 return mScrollView; 203 } 204 205 /** 206 * Get the child contained within the vertical linear layout of the 207 * scroll view. 208 * @param index The index within the linear layout. 209 * @return the child within the vertical linear layout of the scroll view 210 * at the specified index. 211 */ 212 @SuppressWarnings({"unchecked"}) 213 public <T extends View> T getContentChildAt(int index) { 214 return (T) mLinearLayout.getChildAt(index); 215 } 216 217 /** 218 * Hook for changing how scroll view's are created. 219 */ 220 @SuppressWarnings({"JavaDoc"}) 221 protected ScrollView createScrollView() { 222 return new ScrollView(this); 223 } 224 225 @Override 226 protected void onCreate(Bundle savedInstanceState) { 227 super.onCreate(savedInstanceState); 228 229 // for test stability, turn off title bar 230 requestWindowFeature(Window.FEATURE_NO_TITLE); 231 int screenHeight = getWindowManager().getDefaultDisplay().getHeight() 232 - 25; 233 mLinearLayout = new LinearLayout(this); 234 mLinearLayout.setOrientation(LinearLayout.VERTICAL); 235 236 // initialize params 237 final Params params = new Params(); 238 init(params); 239 240 // create views specified by params 241 for (ViewFactory viewFactory : params.mViewFactories) { 242 final LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( 243 ViewGroup.LayoutParams.MATCH_PARENT, 244 (int) (viewFactory.getHeightRatio() * screenHeight)); 245 mLinearLayout.addView(viewFactory.create(this), lp); 246 } 247 248 mScrollView = createScrollView(); 249 mScrollView.addView(mLinearLayout, new ViewGroup.LayoutParams( 250 ViewGroup.LayoutParams.MATCH_PARENT, 251 ViewGroup.LayoutParams.MATCH_PARENT)); 252 253 // no animation to speed up tests 254 mScrollView.setSmoothScrollingEnabled(false); 255 256 setContentView(mScrollView); 257 } 258} 259