|
1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- |
|
2 * This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 package org.mozilla.gecko.widget; |
|
7 |
|
8 import org.mozilla.gecko.GeckoApp; |
|
9 import org.mozilla.gecko.R; |
|
10 import org.mozilla.gecko.util.HardwareUtils; |
|
11 |
|
12 import android.content.res.Resources; |
|
13 import android.graphics.drawable.BitmapDrawable; |
|
14 import android.os.Build; |
|
15 import android.view.Gravity; |
|
16 import android.view.LayoutInflater; |
|
17 import android.view.View; |
|
18 import android.view.ViewGroup; |
|
19 import android.widget.ImageView; |
|
20 import android.widget.LinearLayout; |
|
21 import android.widget.PopupWindow; |
|
22 import android.widget.RelativeLayout; |
|
23 |
|
24 public class ArrowPopup extends PopupWindow { |
|
25 protected final GeckoApp mActivity; |
|
26 |
|
27 private View mAnchor; |
|
28 private ImageView mArrow; |
|
29 |
|
30 private int mArrowWidth; |
|
31 private int mYOffset; |
|
32 |
|
33 protected LinearLayout mContent; |
|
34 protected boolean mInflated; |
|
35 |
|
36 public ArrowPopup(GeckoApp aActivity) { |
|
37 this(aActivity, null); |
|
38 } |
|
39 |
|
40 public ArrowPopup(GeckoApp activity, View anchor) { |
|
41 super(activity); |
|
42 mActivity = activity; |
|
43 mAnchor = anchor; |
|
44 |
|
45 mInflated = false; |
|
46 |
|
47 final Resources res = activity.getResources(); |
|
48 mArrowWidth = res.getDimensionPixelSize(R.dimen.menu_popup_arrow_width); |
|
49 mYOffset = res.getDimensionPixelSize(R.dimen.menu_popup_arrow_offset); |
|
50 |
|
51 setAnimationStyle(R.style.PopupAnimation); |
|
52 } |
|
53 |
|
54 public void setAnchor(View anchor) { |
|
55 mAnchor = anchor; |
|
56 } |
|
57 |
|
58 protected void init() { |
|
59 setBackgroundDrawable(new BitmapDrawable()); |
|
60 setOutsideTouchable(true); |
|
61 |
|
62 setWindowLayoutMode(HardwareUtils.isTablet() ? ViewGroup.LayoutParams.WRAP_CONTENT : ViewGroup.LayoutParams.FILL_PARENT, |
|
63 ViewGroup.LayoutParams.WRAP_CONTENT); |
|
64 |
|
65 LayoutInflater inflater = LayoutInflater.from(mActivity); |
|
66 RelativeLayout layout = (RelativeLayout) inflater.inflate(R.layout.arrow_popup, null); |
|
67 setContentView(layout); |
|
68 |
|
69 mArrow = (ImageView) layout.findViewById(R.id.arrow); |
|
70 mContent = (LinearLayout) layout.findViewById(R.id.content); |
|
71 |
|
72 mInflated = true; |
|
73 } |
|
74 |
|
75 /* |
|
76 * Shows the popup with the arrow pointing to the center of the anchor view. If an anchor hasn't |
|
77 * been set or isn't visible, the popup will just be shown at the top of the gecko app view. |
|
78 */ |
|
79 public void show() { |
|
80 int[] anchorLocation = new int[2]; |
|
81 if (mAnchor != null) |
|
82 mAnchor.getLocationInWindow(anchorLocation); |
|
83 |
|
84 // If there's no anchor or the anchor is out of the window bounds, |
|
85 // just show the popup at the top of the gecko app view. |
|
86 if (mAnchor == null || anchorLocation[1] < 0) { |
|
87 final View view = mActivity.getView(); |
|
88 |
|
89 // Bug in android code causes the window layout parameters to be ignored |
|
90 // when using showAtLocation() in Gingerbread phones. |
|
91 if (Build.VERSION.SDK_INT < 11) { |
|
92 setWidth(view.getWidth()); |
|
93 setHeight(view.getHeight()); |
|
94 } |
|
95 |
|
96 showAtLocation(view, Gravity.TOP, 0, 0); |
|
97 return; |
|
98 } |
|
99 |
|
100 // Remove padding from the width of the anchor when calculating the arrow offset. |
|
101 int anchorWidth = mAnchor.getWidth() - mAnchor.getPaddingLeft() - mAnchor.getPaddingRight(); |
|
102 // This is the difference between the edge of the anchor view and the edge of the arrow view. |
|
103 // We're making an assumption here that the anchor view is wider than the arrow view. |
|
104 int arrowOffset = (anchorWidth - mArrowWidth)/2 + mAnchor.getPaddingLeft(); |
|
105 |
|
106 // The horizontal offset of the popup window, relative to the left side of the anchor view. |
|
107 int offset = 0; |
|
108 |
|
109 RelativeLayout.LayoutParams arrowLayoutParams = (RelativeLayout.LayoutParams) mArrow.getLayoutParams(); |
|
110 |
|
111 if (HardwareUtils.isTablet()) { |
|
112 // On tablets, the popup has a fixed width, so we use a horizontal offset to position it. |
|
113 // The arrow's left margin is set by the arrow_popup.xml layout file. |
|
114 // This assumes that anchor is not too close to the right side of the screen. |
|
115 offset = arrowOffset - arrowLayoutParams.leftMargin; |
|
116 } else { |
|
117 // On phones, the popup takes up the width of the screen, so we set the arrow's left |
|
118 // margin to make it line up with the anchor. |
|
119 int leftMargin = anchorLocation[0] + arrowOffset; |
|
120 arrowLayoutParams.setMargins(leftMargin, 0, 0, 0); |
|
121 } |
|
122 |
|
123 if (isShowing()) { |
|
124 update(mAnchor, offset, -mYOffset, -1, -1); |
|
125 } else { |
|
126 showAsDropDown(mAnchor, offset, -mYOffset); |
|
127 } |
|
128 } |
|
129 } |