BottomBar.java revision e3b0e946924e45f6788db69aaa8f48a2d81031f0
10744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen/* 20744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * Copyright (C) 2013 The Android Open Source Project 30744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * 40744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * Licensed under the Apache License, Version 2.0 (the "License"); 50744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * you may not use this file except in compliance with the License. 60744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * You may obtain a copy of the License at 70744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * 80744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * http://www.apache.org/licenses/LICENSE-2.0 90744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * 100744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * Unless required by applicable law or agreed to in writing, software 110744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * distributed under the License is distributed on an "AS IS" BASIS, 120744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * See the License for the specific language governing permissions and 140744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * limitations under the License. 150744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen */ 160744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 170744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenpackage com.android.camera.ui; 180744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 190744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.content.Context; 200744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.content.res.Configuration; 210744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.util.AttributeSet; 220744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.view.Gravity; 230f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Spragueimport android.view.LayoutInflater; 240744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.view.View; 250744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.widget.FrameLayout; 260744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.widget.GridLayout; 270744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.widget.LinearLayout; 28e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Spragueimport android.view.MotionEvent; 290744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 300744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen/** 310744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * BottomBar swaps its width and height on rotation. In addition, it also changes 320744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * gravity and layout orientation based on the new orientation. Specifically, in 330744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * landscape it aligns to the right side of its parent and lays out its children 340744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * vertically, whereas in portrait, it stays at the bottom of the parent and has 350744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * a horizontal layout orientation. 360744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * 370744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * In addition to adjusting itself, this class also makes sure its children are 380744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * always spaced evenly in the new orientation. 390744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen */ 400744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenpublic class BottomBar extends FrameLayout { 410744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen private final int mPaddingStart; 420744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen private final int mPaddingEnd; 430744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 440744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen public BottomBar(Context context, AttributeSet attrs) { 450744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen super(context, attrs); 460744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen if (context.getResources().getConfiguration().orientation 470744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen == Configuration.ORIENTATION_LANDSCAPE) { 480744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen mPaddingStart = getPaddingTop(); 490744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen mPaddingEnd = getPaddingBottom(); 500744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } else { 510744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen // Portrait mode 520744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen mPaddingStart = getPaddingLeft(); 530744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen mPaddingEnd = getPaddingRight(); 540744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 550744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 560744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 570744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen /** 580f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague * Sets the bottom bar buttons given a layout id 590f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague */ 600f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague public void setButtonLayout(int buttonLayoutId) { 61eb3134f6ecc42f7d98625ca2c0ddfb06c9f07c43Spike Sprague removeAllViews(); 620f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( 630f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague Context.LAYOUT_INFLATER_SERVICE); 640f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague inflater.inflate(buttonLayoutId, this, true); 650f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague } 660f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague 670f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague /** 680744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * Adjust layout orientation, width, height and gravity based on new orientation. 690744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen */ 700744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen private void adjustSelf(Configuration configuration) { 710744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); 720744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen int shortEdge; 730744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen if (lp.width != FrameLayout.LayoutParams.MATCH_PARENT) { 740744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen shortEdge = lp.width; 750744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } else { 760744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen shortEdge = lp.height; 770744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 780744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen if (configuration.orientation == Configuration.ORIENTATION_PORTRAIT) { 790744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen lp.width = FrameLayout.LayoutParams.MATCH_PARENT; 800744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen lp.height = shortEdge; 810744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen lp.gravity = Gravity.BOTTOM; 820744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen setLayoutParams(lp); 830744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } else { 840744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen lp.height = FrameLayout.LayoutParams.MATCH_PARENT; 850744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen lp.width = shortEdge; 860744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen lp.gravity = Gravity.RIGHT; 870744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen setLayoutParams(lp); 880744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 890744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 900744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 910744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen @Override 920744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen protected void onConfigurationChanged(Configuration config) { 930744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen super.onConfigurationChanged(config); 940744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen adjustSelf(config); 950744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 960744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 970744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen /** 980744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * Custom layout call that aims to space all children evenly in the given rect. 990744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen */ 1000744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen @Override 1010744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen public void onLayout(boolean changed, int left, int top, int right, int bottom) { 1020744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen final int childCount = getChildCount(); 1030744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen if (childCount == 0) { 1040744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen return; 1050744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 1060744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen // Convert parent coordinates into child coordinates 1070744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen right -= left; 1080744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen bottom -= top; 1090744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen left = 0; 1100744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen top = 0; 1110744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 1120744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen // Evenly space all children 1130744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen if (bottom < right) { 1140744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen // Portrait mode 1150744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen int centerY = (top + bottom) / 2; 1160744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen int perChildHorizontalSpace = (right - left - mPaddingStart - mPaddingEnd) / childCount; 1170744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen for (int i = 0; i < childCount; i++) { 1180744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen int centerX = mPaddingStart + perChildHorizontalSpace * i 1190744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen + perChildHorizontalSpace / 2; 1200744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen View child = getChildAt(i); 1210744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen int childWidth = child.getMeasuredWidth(); 1220744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen int childHeight = child.getMeasuredHeight(); 1230744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen child.layout(centerX - childWidth / 2, centerY - childHeight / 2, 1240744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen centerX + childWidth / 2, centerY + childHeight / 2); 1250744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 1260744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } else { 1270744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen // Landscape 1280744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen int centerX = (left + right) / 2; 1290744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen int perChildVerticalSpace = (bottom - top - mPaddingStart - mPaddingEnd) / childCount; 1300744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen // Layout children from bottom up so that they remain nearly the same position 1310744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen // as when they were in portrait 1320744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen for (int i = 0; i < childCount; i++) { 1330744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen int centerY = mPaddingStart + perChildVerticalSpace * (childCount - 1 - i) 1340744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen + perChildVerticalSpace / 2; 1350744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen View child = getChildAt(i); 1360744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen int childWidth = child.getMeasuredWidth(); 1370744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen int childHeight = child.getMeasuredHeight(); 1380744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen child.layout(centerX - childWidth / 2, centerY - childHeight / 2, 1390744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen centerX + childWidth / 2, centerY + childHeight / 2); 1400744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 1410744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 1420744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 1430744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 144e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague // prevent touches on bottom bar (not its children) 145e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague // from triggering a touch event on preview area 146e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague @Override 147e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague public boolean onTouchEvent(MotionEvent event) { 148e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague return true; 149e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague } 1500744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen} 151