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.util.AttributeSet;
22 import android.view.View;
23 import android.widget.TextView;
24 
25 /**
26  * This class defines a generic cling that provides on-screen instructions. A convenient
27  * method is provided here to automatically adjust the position of the cling to
28  * always be consistent with the reference view. The use of the convenient method
29  * is optional.
30  */
31 public class Cling extends TextView {
32 
33     private View mReferenceView = null;
34     private final int[] mLocation = new int[2];
35     private final OnLayoutChangeListener mLayoutChangeListener =
36             new OnLayoutChangeListener() {
37                 @Override
38                 public void onLayoutChange(View v, int left, int top, int right, int bottom,
39                         int oldLeft, int oldTop, int oldRight, int oldBottom) {
40                     mDelayDrawingUntilNextLayout = false;
41                     // Reference view has changed layout.
42                     adjustPosition();
43                 }
44             };
45     private boolean mDelayDrawingUntilNextLayout = false;
46 
Cling(Context context, AttributeSet attrs)47     public Cling(Context context, AttributeSet attrs) {
48         super(context, attrs);
49     }
50 
Cling(Context context)51     public Cling(Context context) {
52         super(context);
53     }
54 
55     /**
56      * Layout on top of a reference view.
57      */
setReferenceView(View v)58     public void setReferenceView(View v) {
59         if (v == null) {
60             if (mReferenceView != null) {
61                 // Clear up existing listeners
62                 mReferenceView.removeOnLayoutChangeListener(mLayoutChangeListener);
63                 mReferenceView = null;
64             }
65             return;
66         }
67         mReferenceView = v;
68         mReferenceView.addOnLayoutChangeListener(mLayoutChangeListener);
69         if (mReferenceView.getVisibility() == GONE) {
70             mDelayDrawingUntilNextLayout = true;
71         } else {
72             adjustPosition();
73         }
74     }
75 
76     /**
77      * Adjust the translation of the cling to stay on top of the reference view.
78      */
adjustPosition()79     public void adjustPosition() {
80         if (mReferenceView == null) {
81             return;
82         }
83         mReferenceView.getLocationInWindow(mLocation);
84         int refCenterX = mLocation[0] + mReferenceView.getWidth() / 2;
85         int refTopY = mLocation[1];
86         // Align center with the reference view and move on top
87         int left = refCenterX - getWidth() / 2;
88         int top = refTopY - getHeight();
89 
90         getLocationInWindow(mLocation);
91         int currentLeft = mLocation[0] - (int) getTranslationX();
92         int currentTop = mLocation[1] - (int) getTranslationY();
93 
94         setTranslationX(left - currentLeft);
95         setTranslationY(top - currentTop);
96     }
97 
98     @Override
draw(Canvas canvas)99     public void draw(Canvas canvas) {
100         if (mDelayDrawingUntilNextLayout) {
101             return;
102         }
103         super.draw(canvas);
104     }
105 }
106