1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the License
10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11  * or implied. See the License for the specific language governing permissions and limitations under
12  * the License.
13  */
14 package android.windowanimationjank;
15 
16 import java.util.Random;
17 
18 import android.app.Activity;
19 import android.os.Bundle;
20 import android.view.ViewTreeObserver.OnPreDrawListener;
21 import android.widget.Chronometer;
22 import android.widget.RadioButton;
23 import android.widget.Switch;
24 import android.widget.TextView;
25 import android.widget.ToggleButton;
26 
27 /*
28  * Activity with arbitrary number of random UI elements, refresh itself constantly.
29  */
30 public class ElementLayoutActivity extends Activity implements OnPreDrawListener {
31     public final static String NUM_ELEMENTS_KEY = "num_elements";
32 
33     private final static int DEFAULT_NUM_ELEMENTS = 100;
34     private final static int BACKGROUND_COLOR = 0xfffff000;
35     private final static int INDICATOR_COLOR = 0xffff0000;
36 
37     private FlowLayout mLayout;
38     // Use the constant seed in order to get predefined order of elements.
39     private Random mRandom = new Random(0);
40     // Blinker indicator for visual feedback that Activity is currently updating.
41     private TextView mIndicator;
42     private static float mIndicatorState;
43 
44     @Override
onCreate(final Bundle savedInstanceState)45     protected void onCreate(final Bundle savedInstanceState) {
46         super.onCreate(savedInstanceState);
47         setContentView(R.layout.flowlayout);
48 
49         mLayout = (FlowLayout)findViewById(R.id.root_flow_layout);
50         mLayout.setBackgroundColor(BACKGROUND_COLOR);
51 
52         mIndicator = new TextView(this);
53         mLayout.addView(mIndicator);
54         mIndicator.setText("***\n***");
55         mIndicator.setBackgroundColor(BACKGROUND_COLOR);
56         mIndicatorState = 0.0f;
57 
58         // Need constantly invalidate view in order to get max redraw rate.
59         mLayout.getViewTreeObserver().addOnPreDrawListener(this);
60 
61         // Read requested number of elements in layout.
62         int numElements = getIntent().getIntExtra(NUM_ELEMENTS_KEY, DEFAULT_NUM_ELEMENTS);
63 
64         for (int i = 0; i < numElements; ++i) {
65             switch (mRandom.nextInt(5)) {
66             case 0:
67                 createRadioButton();
68                 break;
69             case 1:
70                 createToggleButton();
71                 break;
72             case 2:
73                 createSwitch();
74                 break;
75             case 3:
76                 createTextView();
77                 break;
78             case 4:
79                 createChronometer();
80                 break;
81             }
82         }
83 
84         setContentView(mLayout);
85     }
86 
createTextView()87     private void createTextView() {
88         TextView textView = new TextView(this);
89         int lineCnt = mRandom.nextInt(4);
90         StringBuffer buffer = new StringBuffer();
91         for (int i = 0; i < lineCnt; ++i) {
92             if (i != 0) {
93                 buffer.append("\n");
94             }
95             buffer.append("Line:" + mRandom.nextInt());
96         }
97         textView.setText(buffer);
98         mLayout.addView(textView);
99     }
100 
createRadioButton()101     private void createRadioButton() {
102         RadioButton button = new RadioButton(this);
103         button.setText("RadioButton:" + mRandom.nextInt());
104         mLayout.addView(button);
105     }
106 
createToggleButton()107     private void createToggleButton() {
108         ToggleButton button = new ToggleButton(this);
109         button.setChecked(mRandom.nextBoolean());
110         mLayout.addView(button);
111     }
112 
createSwitch()113     private void createSwitch() {
114         Switch button = new Switch(this);
115         button.setChecked(mRandom.nextBoolean());
116         mLayout.addView(button);
117     }
118 
createChronometer()119     private void createChronometer() {
120         Chronometer chronometer = new Chronometer(this);
121         chronometer.setBase(mRandom.nextLong());
122         mLayout.addView(chronometer);
123         chronometer.start();
124     }
125 
126     @Override
onResume()127     protected void onResume() {
128         super.onResume();
129     }
130 
131     @Override
onPause()132     protected void onPause() {
133         super.onPause();
134     }
135 
136     @Override
onPreDraw()137     public boolean onPreDraw() {
138         // Interpolate indicator color
139         int background = 0xff000000;
140         for (int i = 0; i < 3; ++i) {
141             int shift = 8 * i;
142             int colorB = (BACKGROUND_COLOR >> shift) & 0xff;
143             int colorI = (INDICATOR_COLOR >> shift) & 0xff;
144             int color = (int)((float)colorB * (1.0f - mIndicatorState) +
145                     (float)colorI * mIndicatorState);
146             if (color > 255) {
147                 color = 255;
148             }
149             background |= (color << shift);
150         }
151 
152         mIndicator.setBackgroundColor(background);
153         mIndicatorState += (3 / 60.0f);  // around 3 times per second
154         mIndicatorState = mIndicatorState - (int)mIndicatorState;
155 
156         mLayout.postInvalidate();
157         return true;
158     }
159 }