1e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu/* 2e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu * Copyright (C) 2014 The Android Open Source Project 3e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu * 4e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu * Licensed under the Apache License, Version 2.0 (the "License"); 5e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu * you may not use this file except in compliance with the License. 6e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu * You may obtain a copy of the License at 7e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu * 8e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu * http://www.apache.org/licenses/LICENSE-2.0 9e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu * 10e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu * Unless required by applicable law or agreed to in writing, software 11e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu * distributed under the License is distributed on an "AS IS" BASIS, 12e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu * See the License for the specific language governing permissions and 14e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu * limitations under the License. 15e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu */ 16e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu 17e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liupackage com.android.camera.widget; 18e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu 19e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liuimport android.content.Context; 20e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liuimport android.graphics.Canvas; 21e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liuimport android.util.AttributeSet; 22e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liuimport android.view.View; 23e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liuimport android.widget.TextView; 24e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu 25e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu/** 26e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu * This class defines a generic cling that provides on-screen instructions. A convenient 27e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu * method is provided here to automatically adjust the position of the cling to 28e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu * always be consistent with the reference view. The use of the convenient method 29e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu * is optional. 30e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu */ 31e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liupublic class Cling extends TextView { 32e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu 33e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu private View mReferenceView = null; 34e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu private final int[] mLocation = new int[2]; 35e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu private final OnLayoutChangeListener mLayoutChangeListener = 36e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu new OnLayoutChangeListener() { 37e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu @Override 38e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu public void onLayoutChange(View v, int left, int top, int right, int bottom, 39e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu int oldLeft, int oldTop, int oldRight, int oldBottom) { 40e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu mDelayDrawingUntilNextLayout = false; 41e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu // Reference view has changed layout. 42e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu adjustPosition(); 43e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu } 44e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu }; 45e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu private boolean mDelayDrawingUntilNextLayout = false; 46e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu 47e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu public Cling(Context context, AttributeSet attrs) { 48e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu super(context, attrs); 49e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu } 50e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu 51e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu public Cling(Context context) { 52e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu super(context); 53e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu } 54e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu 55e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu /** 56e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu * Layout on top of a reference view. 57e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu */ 58e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu public void setReferenceView(View v) { 59e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu if (v == null) { 60e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu if (mReferenceView != null) { 61e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu // Clear up existing listeners 62e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu mReferenceView.removeOnLayoutChangeListener(mLayoutChangeListener); 63e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu mReferenceView = null; 64e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu } 65e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu return; 66e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu } 67e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu mReferenceView = v; 68e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu mReferenceView.addOnLayoutChangeListener(mLayoutChangeListener); 69e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu if (mReferenceView.getVisibility() == GONE) { 70e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu mDelayDrawingUntilNextLayout = true; 71e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu } else { 72e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu adjustPosition(); 73e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu } 74e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu } 75e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu 76e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu /** 77e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu * Adjust the translation of the cling to stay on top of the reference view. 78e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu */ 793c56192fac54644a301251aae8d1e33c8d60c3e5Spike Sprague public void adjustPosition() { 80e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu if (mReferenceView == null) { 81e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu return; 82e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu } 83e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu mReferenceView.getLocationInWindow(mLocation); 84e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu int refCenterX = mLocation[0] + mReferenceView.getWidth() / 2; 85e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu int refTopY = mLocation[1]; 86e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu // Align center with the reference view and move on top 87e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu int left = refCenterX - getWidth() / 2; 88e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu int top = refTopY - getHeight(); 89e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu 90e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu getLocationInWindow(mLocation); 91e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu int currentLeft = mLocation[0] - (int) getTranslationX(); 92e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu int currentTop = mLocation[1] - (int) getTranslationY(); 93e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu 94e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu setTranslationX(left - currentLeft); 95e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu setTranslationY(top - currentTop); 96e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu } 97e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu 98e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu @Override 99e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu public void draw(Canvas canvas) { 100e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu if (mDelayDrawingUntilNextLayout) { 101e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu return; 102e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu } 103e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu super.draw(canvas); 104e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu } 105e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu} 106