1 /* 2 * Copyright (C) 2011 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.launcher3; 18 19 import android.content.Context; 20 import android.graphics.Rect; 21 import android.util.AttributeSet; 22 import android.view.Gravity; 23 import android.view.LayoutInflater; 24 import android.view.MotionEvent; 25 import android.view.View; 26 import android.view.ViewDebug; 27 import android.view.ViewGroup; 28 import android.widget.FrameLayout; 29 30 /** 31 * View class that represents the bottom row of the home screen. 32 */ 33 public class Hotseat extends CellLayout implements Insettable { 34 35 // Ratio of empty space, qsb should take up to appear visually centered. 36 public static final float QSB_CENTER_FACTOR = .325f; 37 38 @ViewDebug.ExportedProperty(category = "launcher") 39 private boolean mHasVerticalHotseat; 40 private Workspace<?> mWorkspace; 41 private boolean mSendTouchToWorkspace; 42 43 private final View mQsb; 44 Hotseat(Context context)45 public Hotseat(Context context) { 46 this(context, null); 47 } 48 Hotseat(Context context, AttributeSet attrs)49 public Hotseat(Context context, AttributeSet attrs) { 50 this(context, attrs, 0); 51 } 52 Hotseat(Context context, AttributeSet attrs, int defStyle)53 public Hotseat(Context context, AttributeSet attrs, int defStyle) { 54 super(context, attrs, defStyle); 55 56 mQsb = LayoutInflater.from(context).inflate(R.layout.search_container_hotseat, this, false); 57 addView(mQsb); 58 } 59 60 /** 61 * Returns orientation specific cell X given invariant order in the hotseat 62 */ getCellXFromOrder(int rank)63 public int getCellXFromOrder(int rank) { 64 return mHasVerticalHotseat ? 0 : rank; 65 } 66 67 /** 68 * Returns orientation specific cell Y given invariant order in the hotseat 69 */ getCellYFromOrder(int rank)70 public int getCellYFromOrder(int rank) { 71 return mHasVerticalHotseat ? (getCountY() - (rank + 1)) : 0; 72 } 73 resetLayout(boolean hasVerticalHotseat)74 public void resetLayout(boolean hasVerticalHotseat) { 75 removeAllViewsInLayout(); 76 mHasVerticalHotseat = hasVerticalHotseat; 77 DeviceProfile dp = mActivity.getDeviceProfile(); 78 resetCellSize(dp); 79 if (hasVerticalHotseat) { 80 setGridSize(1, dp.numShownHotseatIcons); 81 } else { 82 setGridSize(dp.numShownHotseatIcons, 1); 83 } 84 } 85 86 @Override setInsets(Rect insets)87 public void setInsets(Rect insets) { 88 FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); 89 DeviceProfile grid = mActivity.getDeviceProfile(); 90 91 if (grid.isVerticalBarLayout()) { 92 mQsb.setVisibility(View.GONE); 93 lp.height = ViewGroup.LayoutParams.MATCH_PARENT; 94 if (grid.isSeascape()) { 95 lp.gravity = Gravity.LEFT; 96 lp.width = grid.hotseatBarSizePx + insets.left; 97 } else { 98 lp.gravity = Gravity.RIGHT; 99 lp.width = grid.hotseatBarSizePx + insets.right; 100 } 101 } else { 102 mQsb.setVisibility(View.VISIBLE); 103 lp.gravity = Gravity.BOTTOM; 104 lp.width = ViewGroup.LayoutParams.MATCH_PARENT; 105 lp.height = grid.hotseatBarSizePx; 106 } 107 108 Rect padding = grid.getHotseatLayoutPadding(getContext()); 109 setPadding(padding.left, padding.top, padding.right, padding.bottom); 110 setLayoutParams(lp); 111 InsettableFrameLayout.dispatchInsets(this, insets); 112 } 113 setWorkspace(Workspace<?> w)114 public void setWorkspace(Workspace<?> w) { 115 mWorkspace = w; 116 } 117 118 @Override onInterceptTouchEvent(MotionEvent ev)119 public boolean onInterceptTouchEvent(MotionEvent ev) { 120 // We allow horizontal workspace scrolling from within the Hotseat. We do this by delegating 121 // touch intercept the Workspace, and if it intercepts, delegating touch to the Workspace 122 // for the remainder of the this input stream. 123 int yThreshold = getMeasuredHeight() - getPaddingBottom(); 124 if (mWorkspace != null && ev.getY() <= yThreshold) { 125 mSendTouchToWorkspace = mWorkspace.onInterceptTouchEvent(ev); 126 return mSendTouchToWorkspace; 127 } 128 return false; 129 } 130 131 @Override onTouchEvent(MotionEvent event)132 public boolean onTouchEvent(MotionEvent event) { 133 // See comment in #onInterceptTouchEvent 134 if (mSendTouchToWorkspace) { 135 final int action = event.getAction(); 136 switch (action & MotionEvent.ACTION_MASK) { 137 case MotionEvent.ACTION_UP: 138 case MotionEvent.ACTION_CANCEL: 139 mSendTouchToWorkspace = false; 140 } 141 return mWorkspace.onTouchEvent(event); 142 } 143 // Always let touch follow through to Workspace. 144 return false; 145 } 146 147 @Override onMeasure(int widthMeasureSpec, int heightMeasureSpec)148 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 149 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 150 151 DeviceProfile dp = mActivity.getDeviceProfile(); 152 mQsb.measure(MeasureSpec.makeMeasureSpec(dp.hotseatQsbWidth, MeasureSpec.EXACTLY), 153 MeasureSpec.makeMeasureSpec(dp.hotseatQsbHeight, MeasureSpec.EXACTLY)); 154 } 155 156 @Override onLayout(boolean changed, int l, int t, int r, int b)157 protected void onLayout(boolean changed, int l, int t, int r, int b) { 158 super.onLayout(changed, l, t, r, b); 159 160 int qsbMeasuredWidth = mQsb.getMeasuredWidth(); 161 int left; 162 DeviceProfile dp = mActivity.getDeviceProfile(); 163 if (dp.isQsbInline) { 164 int qsbSpace = dp.hotseatBorderSpace; 165 left = Utilities.isRtl(getResources()) ? r - getPaddingRight() + qsbSpace 166 : l + getPaddingLeft() - qsbMeasuredWidth - qsbSpace; 167 } else { 168 left = (r - l - qsbMeasuredWidth) / 2; 169 } 170 int right = left + qsbMeasuredWidth; 171 172 int bottom = b - t - dp.getQsbOffsetY(); 173 int top = bottom - dp.hotseatQsbHeight; 174 mQsb.layout(left, top, right, bottom); 175 } 176 177 /** 178 * Sets the alpha value of just our ShortcutAndWidgetContainer. 179 */ setIconsAlpha(float alpha)180 public void setIconsAlpha(float alpha) { 181 getShortcutsAndWidgets().setAlpha(alpha); 182 } 183 184 /** 185 * Sets the alpha value of just our QSB. 186 */ setQsbAlpha(float alpha)187 public void setQsbAlpha(float alpha) { 188 mQsb.setAlpha(alpha); 189 } 190 getIconsAlpha()191 public float getIconsAlpha() { 192 return getShortcutsAndWidgets().getAlpha(); 193 } 194 195 /** 196 * Returns the QSB inside hotseat 197 */ getQsb()198 public View getQsb() { 199 return mQsb; 200 } 201 202 } 203