1 /*
2  * Copyright (C) 2014 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 
17 package com.android.camera.widget;
18 
19 import android.content.Context;
20 import android.graphics.Canvas;
21 import android.graphics.Paint;
22 import android.graphics.Path;
23 import android.util.AttributeSet;
24 import android.view.View;
25 import android.widget.FrameLayout;
26 
27 import com.android.camera2.R;
28 
29 /**
30  * This is a cling widget for settings button. In addition to drawing a cling button
31  * background and overlaying text, it draws a small triangle that points at the
32  * settings button that this cling is for.
33  */
34 public class SettingsCling extends FrameLayout {
35     private final int mClingTriangleHeight;
36     private final int mClingTriangleWidth;
37     private final Path mTrianglePath = new Path();
38     private final Paint mClingPaint = new Paint();
39 
SettingsCling(Context context, AttributeSet attrs)40     public SettingsCling(Context context, AttributeSet attrs) {
41         super(context, attrs);
42         setWillNotDraw(false);
43         mClingTriangleHeight = getResources().getDimensionPixelSize(
44                 R.dimen.settings_cling_triangle_height);
45         mClingTriangleWidth = getResources().getDimensionPixelSize(
46                 R.dimen.settings_cling_triangle_width);
47         mClingPaint.setColor(getResources().getColor(R.color.settings_cling_color));
48         mClingPaint.setStyle(Paint.Style.FILL);
49     }
50 
51     /**
52      * Updates the current position of the cling based on a reference view. If there
53      * is enough space to lay out the cling on top of the reference view, then have
54      * the cling on top. Otherwise, position the cling underneath the reference view.
55      *
56      * @param referenceView a view that cling uses as a position reference
57      */
updatePosition(View referenceView)58     public void updatePosition(View referenceView) {
59         if (referenceView == null) {
60             return;
61         }
62         // Right align cling:
63         float referenceRight = referenceView.getX() + referenceView.getMeasuredWidth();
64         setTranslationX(referenceRight - getMeasuredWidth());
65 
66         float referenceTop = referenceView.getY();
67         if (referenceTop < getMeasuredHeight()) {
68             // Layout cling under reference view.
69             setTranslationY(referenceTop + referenceView.getMeasuredHeight());
70             float triangleStartX = getMeasuredWidth() - referenceView.getMeasuredWidth() / 2;
71             float triangleStartY = 0;
72             mTrianglePath.reset();
73             mTrianglePath.moveTo(triangleStartX, triangleStartY);
74             mTrianglePath.lineTo(triangleStartX - mClingTriangleWidth / 2,
75                     triangleStartY + mClingTriangleHeight);
76             mTrianglePath.lineTo(triangleStartX + mClingTriangleWidth / 2,
77                     triangleStartY + mClingTriangleHeight);
78             mTrianglePath.lineTo(triangleStartX, triangleStartY);
79         } else {
80             // Layout cling on top of reference view.
81             setTranslationY(referenceTop - getMeasuredHeight());
82             float triangleStartX = getMeasuredWidth() - referenceView.getMeasuredWidth() / 2;
83             float triangleStartY = getMeasuredHeight();
84             mTrianglePath.reset();
85             mTrianglePath.moveTo(triangleStartX, triangleStartY);
86             mTrianglePath.lineTo(triangleStartX - mClingTriangleWidth / 2,
87                     triangleStartY - mClingTriangleHeight);
88             mTrianglePath.lineTo(triangleStartX + mClingTriangleWidth / 2,
89                     triangleStartY - mClingTriangleHeight);
90             mTrianglePath.lineTo(triangleStartX, triangleStartY);
91         }
92         invalidate();
93     }
94 
95     @Override
onDraw(Canvas canvas)96     public void onDraw(Canvas canvas) {
97         super.onDraw(canvas);
98         // Draw triangle.
99         canvas.drawPath(mTrianglePath, mClingPaint);
100     }
101 }
102