blob: 278bb16327e7f1bdf8cb2c2e27452b757c3fd385 [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.camera.widget;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import com.android.camera.ShutterButton;
import com.android.camera.debug.Log;
import com.android.camera.ui.PreviewOverlay;
import com.android.camera.ui.PreviewStatusListener;
import com.android.camera2.R;
/**
* ModeOptionsOverlay is a FrameLayout which positions mode options in
* in the bottom of the preview that is visible above the bottom bar.
*/
public class ModeOptionsOverlay extends FrameLayout
implements PreviewStatusListener.PreviewAreaChangedListener,
PreviewOverlay.OnPreviewTouchedListener,
IndicatorIconController.OnIndicatorVisibilityChangedListener,
ShutterButton.OnShutterButtonListener {
private final static Log.Tag TAG = new Log.Tag("ModeOptionsOverlay");
private static final int BOTTOMBAR_OPTIONS_TIMEOUT_MS = 2000;
private final static int BOTTOM_RIGHT = Gravity.BOTTOM | Gravity.RIGHT;
private final static int TOP_RIGHT = Gravity.TOP | Gravity.RIGHT;
private int mPreviewWidth;
private int mPreviewHeight;
private ModeOptions mModeOptions;
// The mode options toggle can be either a default image, or a
// group of on screen indicators.
private FrameLayout mModeOptionsToggle;
// Default image for mode options toggle.
private ImageView mThreeDots;
// Group of on screen indicators for mode options toggle.
private LinearLayout mIndicators;
public ModeOptionsOverlay(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void onFinishInflate() {
mModeOptions = (ModeOptions) findViewById(R.id.mode_options);
mModeOptions.setClickable(true);
mModeOptions.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
closeModeOptions();
}
});
mModeOptionsToggle = (FrameLayout) findViewById(R.id.mode_options_toggle);
mModeOptionsToggle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mModeOptions.animateVisible();
}
});
mModeOptions.setViewToShowHide(mModeOptionsToggle);
mThreeDots = (ImageView) findViewById(R.id.three_dots);
mIndicators = (LinearLayout) findViewById(R.id.indicator_icons);
showCorrectToggleView(mThreeDots, mIndicators);
}
@Override
public void onPreviewTouched(MotionEvent ev) {
closeModeOptions();
}
@Override
public void onIndicatorVisibilityChanged(View indicator) {
showCorrectToggleView(mThreeDots, mIndicators);
}
@Override
public void onShutterButtonClick() {
closeModeOptions();
}
@Override
public void onShutterButtonFocus(boolean pressed) {
}
/**
* Schedule (or re-schedule) the options menu to be closed after a number
* of milliseconds. If the options menu is already closed, nothing is
* scheduled.
*/
private void closeModeOptions() {
mModeOptions.animateHidden();
}
@Override
public void onConfigurationChanged(Configuration configuration) {
super.onConfigurationChanged(configuration);
checkOrientation(configuration.orientation);
}
@Override
public void onPreviewAreaChanged(RectF previewArea) {
mPreviewWidth = (int) previewArea.width();
mPreviewHeight = (int) previewArea.height();
setLayoutDimensions();
}
/**
* The overlay takes its horizontal dimension from the preview. The vertical
* dimension of the overlay is determined by its parent layout, which has
* knowledge of the bottom bar dimensions.
*/
private void setLayoutDimensions() {
if (mPreviewWidth == 0 || mPreviewHeight == 0) {
return;
}
boolean isPortrait = Configuration.ORIENTATION_PORTRAIT
== getResources().getConfiguration().orientation;
ViewGroup.LayoutParams params = (ViewGroup.LayoutParams) getLayoutParams();
if (isPortrait) {
params.width = mPreviewWidth;
} else {
params.height = mPreviewHeight;
}
setLayoutParams(params);
}
/**
* Set the layout gravity of the child layout to be bottom or top right
* depending on orientation.
*/
private void checkOrientation(int orientation) {
final boolean isPortrait = Configuration.ORIENTATION_PORTRAIT == orientation;
FrameLayout.LayoutParams modeOptionsParams
= (FrameLayout.LayoutParams) mModeOptions.getLayoutParams();
FrameLayout.LayoutParams modeOptionsToggleParams
= (FrameLayout.LayoutParams) mModeOptionsToggle.getLayoutParams();
if (isPortrait) {
modeOptionsParams.height = modeOptionsParams.width;
modeOptionsParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
if (modeOptionsParams.gravity != Gravity.BOTTOM) {
modeOptionsParams.gravity = Gravity.BOTTOM;
}
if (modeOptionsToggleParams.gravity != BOTTOM_RIGHT) {
modeOptionsToggleParams.gravity = BOTTOM_RIGHT;
}
// Remove the rotation on the three dots.
mThreeDots.setImageMatrix(new Matrix());
} else if (!isPortrait) {
modeOptionsParams.width = modeOptionsParams.height;
modeOptionsParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
if (modeOptionsParams.gravity != Gravity.RIGHT) {
modeOptionsParams.gravity = Gravity.RIGHT;
}
if (modeOptionsToggleParams.gravity != TOP_RIGHT) {
modeOptionsToggleParams.gravity = TOP_RIGHT;
}
// Rotate the three dots 90 to match portrait.
Matrix matrix = new Matrix();
matrix.setRotate(90, mThreeDots.getWidth() / 2 , mThreeDots.getHeight() / 2);
mThreeDots.setImageMatrix(matrix);
}
requestLayout();
}
/**
* Show the correct toggle view: the default view if the group has
* no visible children, otherwise the default view.
*/
private void showCorrectToggleView(View defaultView, ViewGroup group) {
if (getVisibleChildCount(group) > 0) {
defaultView.setVisibility(View.GONE);
group.setVisibility(View.VISIBLE);
} else {
group.setVisibility(View.GONE);
defaultView.setVisibility(View.VISIBLE);
}
}
/**
* Get the number of a ViewGroup's visible children.
*/
private int getVisibleChildCount(ViewGroup group) {
int visible = 0;
for (int i = 0; i < group.getChildCount(); i++) {
View child = group.getChildAt(i);
if (child != null && child.getVisibility() == View.VISIBLE) {
visible++;
}
}
return visible;
}
}