1 /* 2 * Copyright (C) 2013 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.ui; 18 19 import android.content.Context; 20 import android.graphics.Canvas; 21 import android.graphics.Typeface; 22 import android.graphics.drawable.Drawable; 23 import android.util.AttributeSet; 24 import android.view.MotionEvent; 25 import android.widget.FrameLayout; 26 import android.widget.TextView; 27 28 import com.android.camera.util.ApiHelper; 29 import com.android.camera2.R; 30 31 /** 32 * This is a package private class, as it is not intended to be visible or used 33 * outside of this package. 34 * 35 * ModeSelectorItem is a FrameLayout that contains an ImageView to display the 36 * icon for the corresponding mode, a TextView that explains what the mode is, 37 * and a GradientDrawable at the end of the TextView. 38 * 39 * The purpose of this class is to encapsulate different drawing logic into 40 * its own class. There are two drawing mode, <code>FLY_IN</code> 41 * and <code>FLY_OUT</code>. They define how we draw the view when 42 * we display the view partially. 43 */ 44 class ModeSelectorItem extends FrameLayout { 45 private TextView mText; 46 private ModeIconView mIcon; 47 private int mVisibleWidth = 0; 48 private final int mMinVisibleWidth; 49 private VisibleWidthChangedListener mListener = null; 50 51 private int mWidth; 52 private int mModeId; 53 54 /** 55 * A listener that gets notified when the visible width of the current item 56 * is changed. 57 */ 58 public interface VisibleWidthChangedListener { 59 public void onVisibleWidthChanged(int width); 60 } 61 62 public ModeSelectorItem(Context context, AttributeSet attrs) { 63 super(context, attrs); 64 setWillNotDraw(false); 65 setClickable(true); 66 mMinVisibleWidth = getResources() 67 .getDimensionPixelSize(R.dimen.mode_selector_icon_block_width); 68 } 69 70 @Override 71 public void onFinishInflate() { 72 mIcon = (ModeIconView) findViewById(R.id.selector_icon); 73 mText = (TextView) findViewById(R.id.selector_text); 74 Typeface typeface; 75 if (ApiHelper.HAS_ROBOTO_MEDIUM_FONT) { 76 typeface = Typeface.create("sans-serif-medium", Typeface.NORMAL); 77 } else { 78 // Load roboto_light typeface from assets. 79 typeface = Typeface.createFromAsset(getResources().getAssets(), 80 "Roboto-Medium.ttf"); 81 } 82 mText.setTypeface(typeface); 83 } 84 85 public void setDefaultBackgroundColor(int color) { 86 setBackgroundColor(color); 87 } 88 89 /** 90 * Sets a listener that receives a callback when the visible width of this 91 * selector item changes. 92 */ 93 public void setVisibleWidthChangedListener(VisibleWidthChangedListener listener) { 94 mListener = listener; 95 } 96 97 @Override 98 public void setSelected(boolean selected) { 99 mIcon.setSelected(selected); 100 } 101 102 @Override 103 public boolean dispatchTouchEvent(MotionEvent ev) { 104 // Do not dispatch any touch event, so that all the events that are received 105 // in onTouchEvent() are only through forwarding. 106 return false; 107 } 108 109 @Override 110 public boolean onTouchEvent(MotionEvent ev) { 111 super.onTouchEvent(ev); 112 return false; 113 } 114 115 /** 116 * When swiping in, we truncate the end of the item if the visible width 117 * is not enough to show the whole item. When swiping out, we truncate the 118 * front of the text (i.e. offset the text). 119 * 120 * @param swipeIn whether swiping direction is swiping in (i.e. from left 121 * to right) 122 */ 123 public void onSwipeModeChanged(boolean swipeIn) { 124 mText.setTranslationX(0); 125 } 126 127 public void setText(CharSequence text) { 128 mText.setText(text); 129 } 130 131 @Override 132 public void onLayout(boolean changed, int left, int top, int right, int bottom) { 133 super.onLayout(changed, left, top, right, bottom); 134 mWidth = right - left; 135 if (changed && mVisibleWidth > 0) { 136 // Reset mode list to full screen 137 setVisibleWidth(mWidth); 138 } 139 } 140 141 /** 142 * Sets image resource as the icon for the mode. By default, all drawables instances 143 * loaded from the same resource share a common state; if you modify the state 144 * of one instance, all the other instances will receive the same modification. 145 * In order to modify properties of this icon drawable without affecting other 146 * drawables, here we use a mutable drawable which is guaranteed to not share 147 * states with other drawables. 148 * 149 * @param resource resource id of the asset to be used as icon 150 */ 151 public void setImageResource(int resource) { 152 Drawable drawableIcon = getResources().getDrawable(resource); 153 if (drawableIcon != null) { 154 drawableIcon = drawableIcon.mutate(); 155 } 156 mIcon.setIconDrawable(drawableIcon); 157 } 158 159 /** 160 * Sets the visible width preferred for the item. The item can then decide how 161 * to draw itself based on the visible width and whether it's being swiped in 162 * or out. This function will be called on every frame during animation. It should 163 * only do minimal work required to get the animation working. 164 * 165 * @param newWidth new visible width 166 */ 167 public void setVisibleWidth(int newWidth) { 168 int fullyShownIconWidth = getMaxVisibleWidth(); 169 newWidth = Math.max(newWidth, 0); 170 // Visible width should not be greater than view width 171 newWidth = Math.min(newWidth, fullyShownIconWidth); 172 173 if (mVisibleWidth != newWidth) { 174 mVisibleWidth = newWidth; 175 if (mListener != null) { 176 mListener.onVisibleWidthChanged(newWidth); 177 } 178 } 179 invalidate(); 180 } 181 182 /** 183 * Getter for visible width. This function will get called during animation as 184 * well. 185 * 186 * @return The visible width of this item 187 */ 188 public int getVisibleWidth() { 189 return mVisibleWidth; 190 } 191 192 /** 193 * Draw the view based on the drawing mode. Clip the canvas if necessary. 194 * 195 * @param canvas The Canvas to which the View is rendered. 196 */ 197 @Override 198 public void draw(Canvas canvas) { 199 float transX = 0f; 200 // If the given width is less than the icon width, we need to translate icon 201 if (mVisibleWidth < mMinVisibleWidth + mIcon.getLeft()) { 202 transX = mMinVisibleWidth + mIcon.getLeft() - mVisibleWidth; 203 } 204 canvas.save(); 205 canvas.translate(-transX, 0); 206 super.draw(canvas); 207 canvas.restore(); 208 } 209 210 /** 211 * Sets the color that will be used in the drawable for highlight state. 212 * 213 * @param highlightColor color for the highlight state 214 */ 215 public void setHighlightColor(int highlightColor) { 216 mIcon.setHighlightColor(highlightColor); 217 } 218 219 /** 220 * @return highlightColor color for the highlight state 221 */ 222 public int getHighlightColor() { 223 return mIcon.getHighlightColor(); 224 } 225 226 /** 227 * Gets the maximum visible width of the mode icon. The mode item will be 228 * full shown when the mode icon has max visible width. 229 */ 230 public int getMaxVisibleWidth() { 231 return mIcon.getLeft() + mMinVisibleWidth; 232 } 233 234 /** 235 * Gets the position of the icon center relative to the window. 236 * 237 * @param loc integer array of size 2, to hold the position x and y 238 */ 239 public void getIconCenterLocationInWindow(int[] loc) { 240 mIcon.getLocationInWindow(loc); 241 loc[0] += mMinVisibleWidth / 2; 242 loc[1] += mMinVisibleWidth / 2; 243 } 244 245 /** 246 * Sets the mode id of the current item. 247 * 248 * @param modeId id of the mode represented by current item. 249 */ 250 public void setModeId(int modeId) { 251 mModeId = modeId; 252 } 253 254 /** 255 * Gets the mode id of the current item. 256 */ 257 public int getModeId() { 258 return mModeId; 259 } 260 261 /** 262 * @return The {@link ModeIconView} attached to this item. 263 */ 264 public ModeIconView getIcon() { 265 return mIcon; 266 } 267 268 /** 269 * Sets the alpha on the mode text. 270 */ 271 public void setTextAlpha(float alpha) { 272 mText.setAlpha(alpha); 273 } 274 } 275