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