1 package com.folioreader.model.quickaction;
3 import com.folioreader.R;
5 import android.content.Context;
6 import android.graphics.Rect;
7 import android.graphics.drawable.Drawable;
8 import android.view.Gravity;
9 import android.view.LayoutInflater;
10 import android.view.View;
11 import android.view.View.OnClickListener;
12 import android.view.ViewGroup;
13 import android.view.ViewGroup.LayoutParams;
14 import android.widget.ImageView;
15 import android.widget.PopupWindow.OnDismissListener;
16 import android.widget.RelativeLayout;
17 import android.widget.ScrollView;
18 import android.widget.TextView;
20 import java.util.ArrayList;
21 import java.util.List;
24 * QuickAction dialog, shows action list as icon and text like the one in Gallery3D app. Currently
26 * and horizontal layout.
28 * @author Lorensius W. L. T <lorenz@londatiga.net>
31 * - Kevin Peck <kevinwpeck@gmail.com>
33 public class QuickAction extends PopupWindows implements OnDismissListener {
34 private View mRootView;
35 private ImageView mArrowUp;
36 private ImageView mArrowDown;
37 private LayoutInflater mInflater;
38 private ViewGroup mTrack;
39 private ScrollView mScroller;
40 private OnActionItemClickListener mItemClickListener;
41 private OnDismissListener mDismissListener;
43 private List<ActionItem> mActionItems = new ArrayList<ActionItem>();
45 private boolean mDidAction;
47 private int mChildPos;
48 private int mInsertPos;
49 private int mAnimStyle;
50 private int mOrientation;
51 private int mRootWidth = 0;
53 public static final int HORIZONTAL = 0;
54 public static final int VERTICAL = 1;
56 public static final int ANIM_GROW_FROM_LEFT = 1;
57 public static final int ANIM_GROW_FROM_RIGHT = 2;
58 public static final int ANIM_GROW_FROM_CENTER = 3;
59 public static final int ANIM_REFLECT = 4;
60 public static final int ANIM_AUTO = 5;
63 * Constructor for default vertical layout
65 * @param context Context
67 public QuickAction(Context context) {
68 this(context, VERTICAL);
72 * Constructor allowing orientation override
74 * @param context Context
75 * @param orientation Layout orientation, can be vartical or horizontal
77 public QuickAction(Context context, int orientation) {
80 mOrientation = orientation;
82 mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
84 if (mOrientation == HORIZONTAL) {
85 setRootViewId(R.layout.popup_horizontal);
87 setRootViewId(R.layout.popup_vertical);
90 mAnimStyle = ANIM_AUTO;
95 * Get action item at an index
97 * @param index Index of item (position from callback)
98 * @return Action Item at the position
100 public ActionItem getActionItem(int index) {
101 return mActionItems.get(index);
107 * @param id Layout resource id
109 public void setRootViewId(int id) {
110 mRootView = (ViewGroup) mInflater.inflate(id, null);
111 mTrack = (ViewGroup) mRootView.findViewById(R.id.tracks);
113 mArrowDown = (ImageView) mRootView.findViewById(R.id.arrow_down);
114 mArrowUp = (ImageView) mRootView.findViewById(R.id.arrow_up);
116 mScroller = (ScrollView) mRootView.findViewById(R.id.scroller);
118 //This was previously defined on show()
119 // method, moved here to prevent force close that occured
120 //when tapping fastly on a view to show quickaction dialog.
121 //Thanx to zammbi (github.com/zammbi)
122 mRootView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
123 LayoutParams.WRAP_CONTENT));
125 setContentView(mRootView);
129 * Set animation style
131 * @param mAnimStyle animation style, default is set to ANIM_AUTO
133 public void setAnimStyle(int mAnimStyle) {
134 this.mAnimStyle = mAnimStyle;
138 * Set listener for action item clicked.
140 * @param listener Listener
142 public void setOnActionItemClickListener(OnActionItemClickListener listener) {
143 mItemClickListener = listener;
149 * @param action {@link ActionItem}
151 public void addActionItem(ActionItem action) {
152 mActionItems.add(action);
154 String title = action.getTitle();
155 Drawable icon = action.getIcon();
159 if (mOrientation == HORIZONTAL) {
160 container = mInflater.inflate(R.layout.action_item_horizontal, null);
162 container = mInflater.inflate(R.layout.action_item_vertical, null);
165 ImageView img = (ImageView) container.findViewById(R.id.iv_icon);
166 TextView text = (TextView) container.findViewById(R.id.tv_title);
169 img.setImageDrawable(icon);
171 img.setVisibility(View.GONE);
177 text.setVisibility(View.GONE);
180 final int pos = mChildPos;
181 final int actionId = action.getActionId();
183 container.setOnClickListener(new OnClickListener() {
185 public void onClick(View v) {
186 if (mItemClickListener != null) {
187 mItemClickListener.onItemClick(QuickAction.this, pos, actionId);
190 if (!getActionItem(pos).isSticky()) {
198 container.setFocusable(true);
199 container.setClickable(true);
201 if (mOrientation == HORIZONTAL && mChildPos != 0) {
202 View separator = mInflater.inflate(R.layout.horiz_separator, null);
204 RelativeLayout.LayoutParams params =
205 new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
206 LayoutParams.FILL_PARENT);
208 separator.setLayoutParams(params);
209 separator.setPadding(5, 0, 5, 0);
211 mTrack.addView(separator, mInsertPos);
216 mTrack.addView(container, mInsertPos);
223 * Show quickaction popup. Popup is automatically positioned, on top or bottom of anchor view.
225 public void show(View anchor) {
228 int xPos, yPos, arrowPos;
232 int[] location = new int[2];
234 anchor.getLocationOnScreen(location);
236 Rect anchorRect = new Rect(location[0], location[1], location[0]
237 + anchor.getWidth(), location[1]
238 + anchor.getHeight());
240 mRootView.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
242 int rootHeight = mRootView.getMeasuredHeight();
244 if (mRootWidth == 0) {
245 mRootWidth = mRootView.getMeasuredWidth();
248 int screenWidth = mWindowManager.getDefaultDisplay().getWidth();
249 int screenHeight = mWindowManager.getDefaultDisplay().getHeight();
251 //automatically get X coord of popup (top left)
252 if ((anchorRect.left + mRootWidth) > screenWidth) {
253 xPos = anchorRect.left - (mRootWidth - anchor.getWidth());
254 xPos = (xPos < 0) ? 0 : xPos;
256 arrowPos = anchorRect.centerX() - xPos;
259 if (anchor.getWidth() > mRootWidth) {
260 xPos = anchorRect.centerX() - (mRootWidth / 2);
262 xPos = anchorRect.left;
265 arrowPos = anchorRect.centerX() - xPos;
268 int dyTop = anchorRect.top;
269 int dyBottom = screenHeight - anchorRect.bottom;
271 boolean onTop = (dyTop > dyBottom) ? true : false;
274 if (rootHeight > dyTop) {
276 LayoutParams l = mScroller.getLayoutParams();
277 l.height = dyTop - anchor.getHeight();
279 yPos = anchorRect.top - rootHeight;
282 yPos = anchorRect.bottom;
284 if (rootHeight > dyBottom) {
285 LayoutParams l = mScroller.getLayoutParams();
290 showArrow(((onTop) ? R.id.arrow_down : R.id.arrow_up), arrowPos);
292 setAnimationStyle(screenWidth, anchorRect.centerX(), onTop);
294 mWindow.showAtLocation(anchor, Gravity.NO_GRAVITY, xPos, yPos);
297 public void show(View anchor, int width, int height) {
300 int xPos, yPos, arrowPos;
301 int[] location = new int[2];
303 anchor.getLocationOnScreen(location);
306 new Rect(location[0], location[1], location[0] + width, location[1] + height);
310 mRootView.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
312 int rootHeight = mRootView.getMeasuredHeight();
314 if (mRootWidth == 0) {
315 mRootWidth = mRootView.getMeasuredWidth();
318 int screenWidth = mWindowManager.getDefaultDisplay().getWidth();
319 int screenHeight = mWindowManager.getDefaultDisplay().getHeight();
321 //automatically get X coord of popup (top left)
322 if ((anchorRect.left + mRootWidth) > screenWidth) {
323 xPos = anchorRect.left - (mRootWidth - width);
324 xPos = (xPos < 0) ? 0 : xPos;
326 arrowPos = anchorRect.centerX() - xPos;
329 if (width > mRootWidth) {
330 xPos = anchorRect.centerX() - (mRootWidth / 2);
332 xPos = anchorRect.left;
335 arrowPos = anchorRect.centerX() - xPos;
338 int dyTop = anchorRect.top;
339 int dyBottom = screenHeight - anchorRect.bottom;
341 boolean onTop = (dyTop > dyBottom) ? true : false;
344 if (rootHeight > dyTop) {
346 LayoutParams l = mScroller.getLayoutParams();
347 l.height = dyTop - height;
349 yPos = anchorRect.top - rootHeight;
352 yPos = anchorRect.bottom;
354 if (rootHeight > dyBottom) {
355 LayoutParams l = mScroller.getLayoutParams();
360 showArrow(((onTop) ? R.id.arrow_down : R.id.arrow_up), arrowPos);
362 setAnimationStyle(screenWidth, anchorRect.centerX(), onTop);
364 mWindow.showAtLocation(anchor, Gravity.NO_GRAVITY, xPos, yPos);
368 * Set animation style
370 * @param screenWidth screen width
371 * @param requestedX distance from left edge
372 * @param onTop flag to indicate where the popup should be displayed. Set TRUE if
373 * displayed on top of anchor view
376 private void setAnimationStyle(int screenWidth, int requestedX, boolean onTop) {
377 int arrowPos = requestedX - mArrowUp.getMeasuredWidth() / 2;
379 switch (mAnimStyle) {
380 case ANIM_GROW_FROM_LEFT:
381 mWindow.setAnimationStyle((onTop) ?
382 R.style.Animations_PopUpMenu_Left : R.style.Animations_PopDownMenu_Left);
385 case ANIM_GROW_FROM_RIGHT:
386 mWindow.setAnimationStyle((onTop) ?
387 R.style.Animations_PopUpMenu_Right : R.style.Animations_PopDownMenu_Right);
390 case ANIM_GROW_FROM_CENTER:
391 mWindow.setAnimationStyle((onTop) ?
392 R.style.Animations_PopUpMenu_Center :
393 R.style.Animations_PopDownMenu_Center);
397 mWindow.setAnimationStyle((onTop) ?
398 R.style.Animations_PopUpMenu_Reflect :
399 R.style.Animations_PopDownMenu_Reflect);
403 if (arrowPos <= screenWidth / 4) {
404 mWindow.setAnimationStyle((onTop) ?
405 R.style.Animations_PopUpMenu_Left :
406 R.style.Animations_PopDownMenu_Left);
407 } else if (arrowPos > screenWidth / 4 &&
408 arrowPos < 3 * (screenWidth / 4)) {
409 mWindow.setAnimationStyle((onTop) ?
410 R.style.Animations_PopUpMenu_Center :
411 R.style.Animations_PopDownMenu_Center);
413 mWindow.setAnimationStyle((onTop) ?
414 R.style.Animations_PopUpMenu_Right :
415 R.style.Animations_PopDownMenu_Right);
425 * @param whichArrow arrow type resource id
426 * @param requestedX distance from left screen
428 private void showArrow(int whichArrow, int requestedX) {
429 final View showArrow = (whichArrow == R.id.arrow_up) ? mArrowUp : mArrowDown;
430 final View hideArrow = (whichArrow == R.id.arrow_up) ? mArrowDown : mArrowUp;
432 final int arrowWidth = mArrowUp.getMeasuredWidth();
434 showArrow.setVisibility(View.VISIBLE);
436 ViewGroup.MarginLayoutParams param =
437 (ViewGroup.MarginLayoutParams) showArrow.getLayoutParams();
439 param.leftMargin = requestedX - arrowWidth / 2;
441 hideArrow.setVisibility(View.INVISIBLE);
445 * Set listener for window dismissed. This listener will only be fired if the quicakction dialog
447 * by clicking outside the dialog or clicking on sticky item.
449 public void setOnDismissListener(QuickAction.OnDismissListener listener) {
450 setOnDismissListener(this);
452 mDismissListener = listener;
456 public void onDismiss() {
457 if (!mDidAction && mDismissListener != null) {
458 mDismissListener.onDismiss();
463 * Listener for item click
465 public interface OnActionItemClickListener {
466 public abstract void onItemClick(QuickAction source, int pos, int actionId);
470 * Listener for window dismiss
472 public interface OnDismissListener {
473 public abstract void onDismiss();