AI2 Component  (Version nb184)
ScaledFrameLayout.java
Go to the documentation of this file.
1 // -*- mode: java; c-basic-offset: 2; -*-
2 // Copyright 2009-2015 Google, All Rights reserved
3 // Copyright 2011-2015 MIT, All rights reserved
4 // Released under the Apache License, Version 2.0
5 // http://www.apache.org/licenses/LICENSE-2.0
6 
7 package com.google.appinventor.components.runtime;
8 
9 import android.content.Context;
10 import android.graphics.Canvas;
11 import android.graphics.Rect;
12 import android.os.Build.VERSION;
13 import android.os.Build.VERSION_CODES;
14 import android.util.AttributeSet;
15 import android.view.Gravity;
16 import android.view.MotionEvent;
17 import android.view.View;
18 import android.view.ViewGroup;
19 import android.view.ViewParent;
20 
23 
30 public class ScaledFrameLayout extends ViewGroup {
31 
32  private static final int MATRIX_SAVE_FLAG = 0x01;
33 
35  private int mLeftWidth;
36 
38  private int mRightWidth;
39 
41  private final Rect mTmpContainerRect = new Rect();
42  private final Rect mTmpChildRect = new Rect();
43 
44  private float mScale = 1.0f;
45 
46  public ScaledFrameLayout(Context context) {
47  super(context);
48  }
49 
50  public ScaledFrameLayout(Context context, AttributeSet attrs) {
51  this(context, attrs, 0);
52  }
53 
54  public ScaledFrameLayout(Context context, AttributeSet attrs, int defStyle) {
55  super(context, attrs, defStyle);
56  setClipChildren(false);
57  }
58 
59  @Override
60  protected void dispatchDraw(Canvas canvas) {
61  canvas.save();
62  canvas.scale(mScale, mScale);
63  super.dispatchDraw(canvas);
64  canvas.restore();
65  }
66 
67  @Override
68  public ViewParent invalidateChildInParent(final int[] location,
69  final Rect dirty) {
70  // This function is overridden so that children properly invalidate
71  // when scaling is in place.
72  final int[] scaledLocation = { (int) (location[0] * mScale),
73  (int) (location[1] * mScale) };
74 
75  final Rect scaledDirty = new Rect((int) (dirty.left * mScale),
76  (int) (dirty.top * mScale), (int) (dirty.right * mScale),
77  (int) (dirty.bottom * mScale));
78 
79  this.invalidate(scaledDirty);
80 
81  return super.invalidateChildInParent(scaledLocation, scaledDirty);
82  }
83 
84  @Override
85  public boolean dispatchTouchEvent(MotionEvent ev) {
86  // Modify the touch events so that children receive scaled touch events
87  ev.setLocation(ev.getX() * (1f / mScale), ev.getY() * (1f / mScale));
88  super.dispatchTouchEvent(ev);
89  return true;
90  }
91 
92  public void setScale(float scale) {
93  mScale = scale;
94  updatePadding(getWidth(), getHeight());
95  }
96 
97  private void updatePadding(int width, int height) {
98  // To maintain constant size, the padding is adjusted such that
99  // scale * (size - padding) = size
100  int paddingRight = (int)((width * (mScale - 1f)) / mScale);
101  int paddingBottom = (int)((height * (mScale - 1f)) / mScale);
102  setPadding(0, 0, paddingRight, paddingBottom);
103  }
104 
105  @Override
106  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
107  updatePadding(w,h);
108  }
109 
113  @Override
114  public boolean shouldDelayChildPressedState() {
115  return false;
116  }
117 
122  @Override
123  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
124  int count = getChildCount();
125 
126  mLeftWidth = 0;
127  mRightWidth = 0;
128 
129  int maxHeight = 0;
130  int maxWidth = 0;
131  int childState = 0;
132 
133  for (int i = 0; i < count; i++) {
134  final View child = getChildAt(i);
135  if (child.getVisibility() != GONE) {
136  measureChild(child, widthMeasureSpec, heightMeasureSpec);
137 
138  mLeftWidth += Math.max(maxWidth, child.getMeasuredWidth());
139 
140  maxHeight = Math.max(maxHeight, child.getMeasuredHeight());
142  childState = HoneycombUtil.combineMeasuredStates(this, childState,
144  }
145  }
146  }
147 
148  maxWidth += mLeftWidth + mRightWidth;
149 
150  maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
151  maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
152 
154  setMeasuredDimension(
155  HoneycombUtil.resolveSizeAndState(this, maxWidth, widthMeasureSpec, childState),
156  HoneycombUtil.resolveSizeAndState(this, maxHeight, heightMeasureSpec,
158  } else {
159  setMeasuredDimension(
160  resolveSize(maxWidth, widthMeasureSpec),
161  resolveSize(maxHeight, heightMeasureSpec));
162  }
163  }
164 
168  @Override
169  protected void onLayout(boolean changed, int left, int top, int right,
170  int bottom) {
171  final int count = getChildCount();
172 
173  int leftPos = getPaddingLeft();
174 
175  final int parentTop = getPaddingTop();
176  final int parentBottom = bottom - top - getPaddingBottom();
177 
178  for (int i = 0; i < count; i++) {
179  final View child = getChildAt(i);
180  if (child.getVisibility() != GONE) {
181  final int width = child.getMeasuredWidth();
182  final int height = child.getMeasuredHeight();
183 
184  mTmpContainerRect.left = leftPos;
185  mTmpContainerRect.right = leftPos;
186  leftPos = mTmpContainerRect.right;
187  mTmpContainerRect.top = parentTop;
188  mTmpContainerRect.bottom = parentBottom;
189 
190  Gravity.apply(Gravity.TOP | Gravity.LEFT, width, height,
191  mTmpContainerRect, mTmpChildRect);
192 
193  child.layout(mTmpChildRect.left, mTmpChildRect.top,
194  mTmpChildRect.right, mTmpChildRect.bottom);
195  }
196  }
197  }
198 }
com.google.appinventor.components.runtime.ScaledFrameLayout.ScaledFrameLayout
ScaledFrameLayout(Context context, AttributeSet attrs)
Definition: ScaledFrameLayout.java:50
com.google.appinventor.components.runtime.util.HoneycombUtil.getMeasuredState
static int getMeasuredState(View view)
Definition: HoneycombUtil.java:29
com.google.appinventor.components.runtime.util
-*- mode: java; c-basic-offset: 2; -*-
Definition: AccountChooser.java:7
com.google.appinventor.components.runtime.util.HoneycombUtil.VIEWGROUP_MEASURED_HEIGHT_STATE_SHIFT
static final int VIEWGROUP_MEASURED_HEIGHT_STATE_SHIFT
Definition: HoneycombUtil.java:20
com.google.appinventor.components
com.google.appinventor.components.runtime.ScaledFrameLayout.dispatchTouchEvent
boolean dispatchTouchEvent(MotionEvent ev)
Definition: ScaledFrameLayout.java:85
com.google.appinventor.components.runtime.ScaledFrameLayout.ScaledFrameLayout
ScaledFrameLayout(Context context, AttributeSet attrs, int defStyle)
Definition: ScaledFrameLayout.java:54
com.google.appinventor.components.runtime.ScaledFrameLayout.shouldDelayChildPressedState
boolean shouldDelayChildPressedState()
Definition: ScaledFrameLayout.java:114
com.google.appinventor.components.runtime.ScaledFrameLayout.onSizeChanged
void onSizeChanged(int w, int h, int oldw, int oldh)
Definition: ScaledFrameLayout.java:106
com.google.appinventor.components.runtime.ScaledFrameLayout.setScale
void setScale(float scale)
Definition: ScaledFrameLayout.java:92
com.google.appinventor.components.runtime.ScaledFrameLayout.invalidateChildInParent
ViewParent invalidateChildInParent(final int[] location, final Rect dirty)
Definition: ScaledFrameLayout.java:68
com.google.appinventor.components.runtime.util.SdkLevel.LEVEL_HONEYCOMB
static final int LEVEL_HONEYCOMB
Definition: SdkLevel.java:28
com.google.appinventor.components.runtime.util.SdkLevel
Definition: SdkLevel.java:19
com.google.appinventor.components.runtime.util.HoneycombUtil.resolveSizeAndState
static int resolveSizeAndState(ViewGroup view, int maxWidth, int widthMeasureSpec, int childState)
Definition: HoneycombUtil.java:33
com.google.appinventor.components.runtime.ScaledFrameLayout
Definition: ScaledFrameLayout.java:30
com.google.appinventor.components.runtime.util.HoneycombUtil.combineMeasuredStates
static int combineMeasuredStates(ViewGroup view, int curState, int newState)
Definition: HoneycombUtil.java:25
com.google.appinventor.components.runtime.ScaledFrameLayout.ScaledFrameLayout
ScaledFrameLayout(Context context)
Definition: ScaledFrameLayout.java:46
com.google.appinventor.components.runtime.ScaledFrameLayout.dispatchDraw
void dispatchDraw(Canvas canvas)
Definition: ScaledFrameLayout.java:60
com.google.appinventor.components.runtime.ScaledFrameLayout.onLayout
void onLayout(boolean changed, int left, int top, int right, int bottom)
Definition: ScaledFrameLayout.java:169
com.google.appinventor.components.runtime.util.SdkLevel.getLevel
static int getLevel()
Definition: SdkLevel.java:45
com.google.appinventor.components.runtime
Copyright 2009-2011 Google, All Rights reserved.
Definition: AccelerometerSensor.java:8
com.google.appinventor.components.runtime.Canvas
Definition: Canvas.java:132
com.google
com
com.google.appinventor.components.runtime.ScaledFrameLayout.onMeasure
void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
Definition: ScaledFrameLayout.java:123
com.google.appinventor
com.google.appinventor.components.runtime.util.HoneycombUtil
Definition: HoneycombUtil.java:18