QuickAction.java 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /* ownCloud Android client application
  2. * Copyright (C) 2011 Bartek Przybylski
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. */
  18. package eu.alefzero.owncloud.ui;
  19. import android.content.Context;
  20. import android.graphics.Rect;
  21. import android.graphics.drawable.Drawable;
  22. import android.widget.ImageView;
  23. import android.widget.TextView;
  24. import android.widget.LinearLayout;
  25. import android.widget.ScrollView;
  26. import android.view.Gravity;
  27. import android.view.LayoutInflater;
  28. import android.view.View;
  29. import android.view.View.OnClickListener;
  30. import android.view.ViewGroup.LayoutParams;
  31. import android.view.ViewGroup;
  32. import java.util.ArrayList;
  33. import eu.alefzero.owncloud.R;
  34. import eu.alefzero.owncloud.R.id;
  35. import eu.alefzero.owncloud.R.layout;
  36. import eu.alefzero.owncloud.R.style;
  37. /**
  38. * Popup window, shows action list as icon and text like the one in Gallery3D app.
  39. *
  40. * @author Lorensius. W. T
  41. */
  42. public class QuickAction extends CustomPopup {
  43. private final View root;
  44. private final ImageView mArrowUp;
  45. private final ImageView mArrowDown;
  46. private final LayoutInflater inflater;
  47. private final Context context;
  48. protected static final int ANIM_GROW_FROM_LEFT = 1;
  49. protected static final int ANIM_GROW_FROM_RIGHT = 2;
  50. protected static final int ANIM_GROW_FROM_CENTER = 3;
  51. protected static final int ANIM_REFLECT = 4;
  52. protected static final int ANIM_AUTO = 5;
  53. private int animStyle;
  54. private ViewGroup mTrack;
  55. private ScrollView scroller;
  56. private ArrayList<ActionItem> actionList;
  57. /**
  58. * Constructor
  59. *
  60. * @param anchor {@link View} on where the popup window should be displayed
  61. */
  62. public QuickAction(View anchor) {
  63. super(anchor);
  64. actionList = new ArrayList<ActionItem>();
  65. context = anchor.getContext();
  66. inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  67. root = (ViewGroup) inflater.inflate(R.layout.popup, null);
  68. mArrowDown = (ImageView) root.findViewById(R.id.arrow_down);
  69. mArrowUp = (ImageView) root.findViewById(R.id.arrow_up);
  70. setContentView(root);
  71. mTrack = (ViewGroup) root.findViewById(R.id.tracks);
  72. scroller = (ScrollView) root.findViewById(R.id.scroller);
  73. animStyle = ANIM_AUTO;
  74. }
  75. /**
  76. * Set animation style
  77. *
  78. * @param animStyle animation style, default is set to ANIM_AUTO
  79. */
  80. public void setAnimStyle(int animStyle) {
  81. this.animStyle = animStyle;
  82. }
  83. /**
  84. * Add action item
  85. *
  86. * @param action {@link ActionItem} object
  87. */
  88. public void addActionItem(ActionItem action) {
  89. actionList.add(action);
  90. }
  91. /**
  92. * Show popup window. Popup is automatically positioned, on top or bottom of anchor view.
  93. *
  94. */
  95. public void show () {
  96. preShow();
  97. int xPos, yPos;
  98. int[] location = new int[2];
  99. mAnchor.getLocationOnScreen(location);
  100. Rect anchorRect = new Rect(location[0], location[1], location[0] + mAnchor.getWidth(), location[1]
  101. + mAnchor.getHeight());
  102. createActionList();
  103. root.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
  104. root.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
  105. int rootHeight = root.getMeasuredHeight();
  106. int rootWidth = root.getMeasuredWidth();
  107. int screenWidth = mWManager.getDefaultDisplay().getWidth();
  108. int screenHeight = mWManager.getDefaultDisplay().getHeight();
  109. //automatically get X coord of popup (top left)
  110. if ((anchorRect.left + rootWidth) > screenWidth) {
  111. xPos = anchorRect.left - (rootWidth-mAnchor.getWidth());
  112. } else {
  113. if (mAnchor.getWidth() > rootWidth) {
  114. xPos = anchorRect.centerX() - (rootWidth/2);
  115. } else {
  116. xPos = anchorRect.left;
  117. }
  118. }
  119. int dyTop = anchorRect.top;
  120. int dyBottom = screenHeight - anchorRect.bottom;
  121. boolean onTop = (dyTop > dyBottom) ? true : false;
  122. if (onTop) {
  123. if (rootHeight > dyTop) {
  124. yPos = 15;
  125. LayoutParams l = scroller.getLayoutParams();
  126. l.height = dyTop - mAnchor.getHeight();
  127. } else {
  128. yPos = anchorRect.top - rootHeight;
  129. }
  130. } else {
  131. yPos = anchorRect.bottom;
  132. if (rootHeight > dyBottom) {
  133. LayoutParams l = scroller.getLayoutParams();
  134. l.height = dyBottom;
  135. }
  136. }
  137. showArrow(((onTop) ? R.id.arrow_down : R.id.arrow_up), anchorRect.centerX()-xPos);
  138. setAnimationStyle(screenWidth, anchorRect.centerX(), onTop);
  139. mWindow.showAtLocation(mAnchor, Gravity.NO_GRAVITY, xPos, yPos);
  140. }
  141. /**
  142. * Set animation style
  143. *
  144. * @param screenWidth screen width
  145. * @param requestedX distance from left edge
  146. * @param onTop flag to indicate where the popup should be displayed. Set TRUE if displayed on top of anchor view
  147. * and vice versa
  148. */
  149. private void setAnimationStyle(int screenWidth, int requestedX, boolean onTop) {
  150. int arrowPos = requestedX - mArrowUp.getMeasuredWidth()/2;
  151. switch (animStyle) {
  152. case ANIM_GROW_FROM_LEFT:
  153. mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Left : R.style.Animations_PopDownMenu_Left);
  154. break;
  155. case ANIM_GROW_FROM_RIGHT:
  156. mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Right : R.style.Animations_PopDownMenu_Right);
  157. break;
  158. case ANIM_GROW_FROM_CENTER:
  159. mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Center : R.style.Animations_PopDownMenu_Center);
  160. break;
  161. case ANIM_REFLECT:
  162. mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Reflect : R.style.Animations_PopDownMenu_Reflect);
  163. break;
  164. case ANIM_AUTO:
  165. if (arrowPos <= screenWidth/4) {
  166. mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Left : R.style.Animations_PopDownMenu_Left);
  167. } else if (arrowPos > screenWidth/4 && arrowPos < 3 * (screenWidth/4)) {
  168. mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Center : R.style.Animations_PopDownMenu_Center);
  169. } else {
  170. mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Right : R.style.Animations_PopDownMenu_Right);
  171. }
  172. break;
  173. }
  174. }
  175. /**
  176. * Create action list
  177. */
  178. private void createActionList() {
  179. View view;
  180. String title;
  181. Drawable icon;
  182. OnClickListener listener;
  183. for (int i = 0; i < actionList.size(); i++) {
  184. title = actionList.get(i).getTitle();
  185. icon = actionList.get(i).getIcon();
  186. listener = actionList.get(i).getOnClickListerner();
  187. view = getActionItem(title, icon, listener);
  188. view.setFocusable(true);
  189. view.setClickable(true);
  190. mTrack.addView(view);
  191. }
  192. }
  193. /**
  194. * Get action item {@link View}
  195. *
  196. * @param title action item title
  197. * @param icon {@link Drawable} action item icon
  198. * @param listener {@link View.OnClickListener} action item listener
  199. * @return action item {@link View}
  200. */
  201. private View getActionItem(String title, Drawable icon, OnClickListener listener) {
  202. LinearLayout container = (LinearLayout) inflater.inflate(R.layout.action_item, null);
  203. ImageView img = (ImageView) container.findViewById(R.id.icon);
  204. TextView text = (TextView) container.findViewById(R.id.title);
  205. if (icon != null) {
  206. img.setImageDrawable(icon);
  207. }
  208. if (title != null) {
  209. text.setText(title);
  210. }
  211. if (listener != null) {
  212. container.setOnClickListener(listener);
  213. }
  214. return container;
  215. }
  216. /**
  217. * Show arrow
  218. *
  219. * @param whichArrow arrow type resource id
  220. * @param requestedX distance from left screen
  221. */
  222. private void showArrow(int whichArrow, int requestedX) {
  223. final View showArrow = (whichArrow == R.id.arrow_up) ? mArrowUp : mArrowDown;
  224. final View hideArrow = (whichArrow == R.id.arrow_up) ? mArrowDown : mArrowUp;
  225. final int arrowWidth = mArrowUp.getMeasuredWidth();
  226. showArrow.setVisibility(View.VISIBLE);
  227. ViewGroup.MarginLayoutParams param = (ViewGroup.MarginLayoutParams)showArrow.getLayoutParams();
  228. param.leftMargin = requestedX - arrowWidth / 2;
  229. hideArrow.setVisibility(View.INVISIBLE);
  230. }
  231. }