PreviewFrameLayout.java revision ffcca7403c9a364403357d3c76a3ff256c63c786
1ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin/* 2ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin * Copyright (C) 2009 The Android Open Source Project 3ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin * 4ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin * you may not use this file except in compliance with the License. 6ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin * You may obtain a copy of the License at 7ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin * 8ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin * http://www.apache.org/licenses/LICENSE-2.0 9ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin * 10ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin * Unless required by applicable law or agreed to in writing, software 11ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin * distributed under the License is distributed on an "AS IS" BASIS, 12ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin * See the License for the specific language governing permissions and 14ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin * limitations under the License. 15ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin */ 16ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin 17ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Linpackage com.android.camera; 18ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin 19ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Linimport android.content.Context; 20ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Linimport android.util.AttributeSet; 21ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Linimport android.view.View; 22ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Linimport android.view.ViewGroup; 23ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Linimport android.widget.ImageView; 24ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Linimport android.widget.FrameLayout; 25ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin 26ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Linpublic class PreviewFrameLayout extends ViewGroup { 27ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin private double mAspectRatio = 4.0 / 3.0; 28ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin private ImageView mGripper; 29ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin private FrameLayout mFrame; 30ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin 31ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin public PreviewFrameLayout(Context context, AttributeSet attrs) { 32ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin super(context, attrs); 33ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin } 34ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin 35ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin @Override 36ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin protected void onFinishInflate() { 37ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin mGripper = (ImageView) findViewById(R.id.btn_gripper); 38ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin mFrame = (FrameLayout) findViewById(R.id.frame); 39ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin if (mFrame == null) { 40ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin throw new IllegalStateException( 41ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin "must provide child with id as \"frame\""); 42ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin } 43ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin } 44ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin 45ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin public void setAspectRatio(double ratio) { 46ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin if (ratio <= 0.0) throw new IllegalArgumentException(); 47ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin 48ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin if (mAspectRatio != ratio) { 49ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin mAspectRatio = ratio; 50ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin requestLayout(); 51ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin } 52ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin } 53ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin 54ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin @Override 55ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 56ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin super.onMeasure(widthMeasureSpec, heightMeasureSpec); 57ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin 58ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin int gripperWidth = 0; 59ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin int gripperHeight = 0; 60ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin 61ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin if (mGripper != null) { 62ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin measureChild(mGripper, widthMeasureSpec, heightMeasureSpec); 63ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin gripperWidth = mGripper.getMeasuredWidth(); 64ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin gripperHeight = mGripper.getMeasuredHeight(); 65ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin } 66ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin 67ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin int frameWidth = getMeasuredWidth() - gripperWidth; 68ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin int frameHeight = getMeasuredHeight(); 69ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin 70ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin FrameLayout f = mFrame; 71ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin 72ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin int horizontalPadding = f.getPaddingLeft() + f.getPaddingRight(); 73ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin int verticalPadding = f.getPaddingBottom() + f.getPaddingTop(); 74ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin 75ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin int previewWidth = frameWidth - horizontalPadding; 76ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin int previewHeight = frameHeight - verticalPadding; 77ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin 78ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin // resize frame and preview for aspect ratio 79ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin if (previewWidth > previewHeight * mAspectRatio) { 80ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin previewWidth = (int) (previewHeight * mAspectRatio + .5); 81ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin } else { 82ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin previewHeight = (int) (previewWidth / mAspectRatio + .5); 83ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin } 84ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin frameWidth = previewWidth + horizontalPadding; 85ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin frameHeight = previewHeight + verticalPadding; 86ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin 87ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin measureChild(mFrame, 88ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin MeasureSpec.makeMeasureSpec(MeasureSpec.EXACTLY, frameWidth), 89ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin MeasureSpec.makeMeasureSpec(MeasureSpec.EXACTLY, frameHeight)); 90ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin } 91ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin 92ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin @Override 93ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin protected void onLayout(boolean changed, int l, int t, int r, int b) { 94ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin // Try to layout the "frame" in the center of the area, and put 95ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin // "gripper" just to the left of it. If there is no enough space for 96ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin // the gripper, the "frame" will be moved a little right so that 97ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin // they won't overlap with each other. 98ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin 99ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin int frameWidth = mFrame.getMeasuredWidth(); 100ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin int frameHeight = mFrame.getMeasuredHeight(); 101ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin 102ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin int leftSpace = ((r - l) - frameWidth) / 2; 103ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin int topSpace = ((b - t) - frameHeight) / 2; 104ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin 105ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin int gripperWidth = 0; 106ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin int gripperHeight = 0; 107ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin if (mGripper != null) { 108ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin gripperWidth = mGripper.getMeasuredWidth(); 109ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin gripperHeight = mGripper.getMeasuredHeight(); 110ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin myLayoutChild(mGripper, 111ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin Math.max(l, l + (leftSpace - gripperWidth)), 112ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin t + ((b - t) - gripperHeight) / 2, 113ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin gripperWidth, gripperHeight); 114ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin } 115ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin myLayoutChild(mFrame, Math.max(l + leftSpace, l + gripperWidth), 116ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin t + topSpace, frameWidth, frameHeight); 117ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin } 118ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin 119ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin private static void myLayoutChild(View child, int l, int t, int w, int h) { 120ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin child.layout(l, t, l + w, t + h); 121ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin } 122ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin} 123ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin 124