Skip to content
This repository was archived by the owner on Jun 8, 2024. It is now read-only.

Commit d61734c

Browse files
committed
CheatSheet: Add tooltips for image buttons
Signed-off-by: Fung <fython@163.com>
1 parent c1e8243 commit d61734c

7 files changed

Lines changed: 156 additions & 3 deletions

File tree

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
package info.papdt.express.helper.support;
2+
3+
import android.content.Context;
4+
import android.content.res.Configuration;
5+
import android.graphics.Rect;
6+
import android.text.TextUtils;
7+
import android.view.Gravity;
8+
import android.view.View;
9+
import android.widget.TextView;
10+
import android.widget.Toast;
11+
import info.papdt.express.helper.R;
12+
13+
/**
14+
* Helper class for showing cheat sheets (tooltips) for icon-only UI elements on long-press. This is
15+
* already default platform behavior for icon-only {@link android.app.ActionBar} items and tabs.
16+
* This class provides this behavior for any other such UI element.
17+
*
18+
* <p>Based on the original action bar implementation in <a href="https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/com/android/internal/view/menu/ActionMenuItemView.java">
19+
* ActionMenuItemView.java</a>.
20+
*/
21+
public class CheatSheet {
22+
/**
23+
* The estimated height of a toast, in dips (density-independent pixels). This is used to
24+
* determine whether or not the toast should appear above or below the UI element.
25+
*/
26+
private static final int ESTIMATED_TOAST_HEIGHT_DIPS = 48;
27+
28+
/**
29+
* Sets up a cheat sheet (tooltip) for the given view by setting its {@link
30+
* android.view.View.OnLongClickListener}. When the view is long-pressed, a {@link Toast} with
31+
* the view's {@link android.view.View#getContentDescription() content description} will be
32+
* shown either above (default) or below the view (if there isn't room above it).
33+
*
34+
* @param view The view to add a cheat sheet for.
35+
*/
36+
public static void setup(View view) {
37+
view.setOnLongClickListener(new View.OnLongClickListener() {
38+
@Override
39+
public boolean onLongClick(View view) {
40+
return showCheatSheet(view, view.getContentDescription());
41+
}
42+
});
43+
}
44+
45+
/**
46+
* Sets up a cheat sheet (tooltip) for the given view by setting its {@link
47+
* android.view.View.OnLongClickListener}. When the view is long-pressed, a {@link Toast} with
48+
* the given text will be shown either above (default) or below the view (if there isn't room
49+
* above it).
50+
*
51+
* @param view The view to add a cheat sheet for.
52+
* @param textResId The string resource containing the text to show on long-press.
53+
*/
54+
public static void setup(View view, final int textResId) {
55+
view.setOnLongClickListener(new View.OnLongClickListener() {
56+
@Override
57+
public boolean onLongClick(View view) {
58+
return showCheatSheet(view, view.getContext().getString(textResId));
59+
}
60+
});
61+
}
62+
63+
/**
64+
* Sets up a cheat sheet (tooltip) for the given view by setting its {@link
65+
* android.view.View.OnLongClickListener}. When the view is long-pressed, a {@link Toast} with
66+
* the given text will be shown either above (default) or below the view (if there isn't room
67+
* above it).
68+
*
69+
* @param view The view to add a cheat sheet for.
70+
* @param text The text to show on long-press.
71+
*/
72+
public static void setup(View view, final CharSequence text) {
73+
view.setOnLongClickListener(new View.OnLongClickListener() {
74+
@Override
75+
public boolean onLongClick(View view) {
76+
return showCheatSheet(view, text);
77+
}
78+
});
79+
}
80+
81+
/**
82+
* Removes the cheat sheet for the given view by removing the view's {@link
83+
* android.view.View.OnLongClickListener}.
84+
*
85+
* @param view The view whose cheat sheet should be removed.
86+
*/
87+
public static void remove(final View view) {
88+
view.setOnLongClickListener(null);
89+
}
90+
91+
/**
92+
* Internal helper method to show the cheat sheet toast.
93+
*/
94+
private static boolean showCheatSheet(View view, CharSequence text) {
95+
if (TextUtils.isEmpty(text)) {
96+
return false;
97+
}
98+
99+
final int[] screenPos = new int[2]; // origin is device display
100+
final Rect displayFrame = new Rect(); // includes decorations (e.g. status bar)
101+
view.getLocationOnScreen(screenPos);
102+
view.getWindowVisibleDisplayFrame(displayFrame);
103+
104+
final Context context = view.getContext();
105+
final int viewWidth = view.getWidth();
106+
final int viewHeight = view.getHeight();
107+
final int viewCenterX = screenPos[0] + viewWidth / 2;
108+
final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
109+
final int estimatedToastHeight = (int) (ESTIMATED_TOAST_HEIGHT_DIPS
110+
* context.getResources().getDisplayMetrics().density);
111+
112+
Toast cheatSheet = Toast.makeText(context, text, Toast.LENGTH_SHORT);
113+
int currentNightMode = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
114+
boolean isNightMode = currentNightMode == Configuration.UI_MODE_NIGHT_YES;
115+
cheatSheet.getView().setBackgroundResource(
116+
!isNightMode ?
117+
android.support.v7.appcompat.R.drawable.tooltip_frame_dark :
118+
android.support.v7.appcompat.R.drawable.tooltip_frame_light);
119+
TextView textView = cheatSheet.getView().findViewById(android.R.id.message);
120+
textView.setTextAppearance(context, R.style.TextAppearance_AppCompat_Body1);
121+
textView.setTextColor(context.getResources().getColor(R.color.white_in_dark));
122+
int dp16 = (int) ScreenUtils.dpToPx(context, 16);
123+
textView.setPaddingRelative(dp16, 0, dp16, 0);
124+
boolean showBelow = screenPos[1] < estimatedToastHeight;
125+
if (showBelow) {
126+
// Show below
127+
// Offsets are after decorations (e.g. status bar) are factored in
128+
cheatSheet.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL,
129+
viewCenterX - screenWidth / 2,
130+
screenPos[1] - displayFrame.top + viewHeight);
131+
} else {
132+
// Show above
133+
// Offsets are after decorations (e.g. status bar) are factored in
134+
// NOTE: We can't use Gravity.BOTTOM because when the keyboard is up
135+
// its height isn't factored in.
136+
cheatSheet.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL,
137+
viewCenterX - screenWidth / 2,
138+
screenPos[1] - displayFrame.top - estimatedToastHeight);
139+
}
140+
141+
cheatSheet.show();
142+
return true;
143+
}
144+
145+
}

mobile/src/main/java/info/papdt/express/helper/ui/DetailsActivity.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import info.papdt.express.helper.dao.PackageDatabase;
3131
import info.papdt.express.helper.model.BaseMessage;
3232
import info.papdt.express.helper.model.Package;
33+
import info.papdt.express.helper.support.CheatSheet;
3334
import info.papdt.express.helper.support.ClipboardUtils;
3435
import info.papdt.express.helper.support.ScreenUtils;
3536
import info.papdt.express.helper.support.Settings;
@@ -97,6 +98,7 @@ public void onClick(View view) {
9798
showNameEditDialog();
9899
}
99100
});
101+
CheatSheet.setup(mFAB);
100102
}
101103

102104
private void setUpData() {

mobile/src/main/java/info/papdt/express/helper/ui/MainActivity.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import info.papdt.express.helper.R;
2525
import info.papdt.express.helper.dao.PackageDatabase;
2626
import info.papdt.express.helper.model.Package;
27+
import info.papdt.express.helper.support.CheatSheet;
2728
import info.papdt.express.helper.support.PushUtils;
2829
import info.papdt.express.helper.support.Settings;
2930
import info.papdt.express.helper.ui.common.AbsActivity;
@@ -95,6 +96,7 @@ public void onClick(View view) {
9596
startActivityForResult(intent, REQUEST_ADD);
9697
}
9798
});
99+
CheatSheet.setup(fab);
98100
}
99101

100102
@Override

mobile/src/main/java/info/papdt/express/helper/ui/items/DetailsTwoLineItemBinder.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import android.view.View;
1111
import android.view.ViewGroup;
1212
import info.papdt.express.helper.R;
13+
import info.papdt.express.helper.support.CheatSheet;
1314
import info.papdt.express.helper.support.ClipboardUtils;
1415
import info.papdt.express.helper.ui.DetailsActivity;
1516
import me.drakeet.multitype.ItemViewBinder;
@@ -78,6 +79,7 @@ public boolean onLongClick(View v) {
7879
itemView.getResources()
7980
.getString(R.string.list_package_show_toggle_desc)
8081
);
82+
CheatSheet.setup(button);
8183
}
8284
button.setVisibility(View.VISIBLE);
8385
button.setOnClickListener(new View.OnClickListener() {

mobile/src/main/res/layout/item_list_details_info_normal.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
xmlns:tools="http://schemas.android.com/tools"
44
android:layout_width="match_parent"
55
android:layout_height="wrap_content"
6-
android:paddingEnd="16dp"
6+
android:paddingEnd="24dp"
77
android:gravity="center_vertical"
88
android:orientation="horizontal"
99
android:foreground="?attr/selectableItemBackground"
@@ -38,8 +38,8 @@
3838
</LinearLayout>
3939

4040
<android.support.v7.widget.AppCompatImageButton
41-
android:layout_width="48dp"
42-
android:layout_height="48dp"
41+
android:layout_width="36dp"
42+
android:layout_height="36dp"
4343
android:id="@+id/btn_action"
4444
android:background="?attr/selectableItemBackgroundBorderless"
4545
android:visibility="gone"

mobile/src/main/res/values-night/colors.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
<color name="dark_theme_translucent_app_bar">#4F000000</color>
3838

3939
<color name="black_in_light">@android:color/white</color>
40+
<color name="white_in_dark">@color/grey_900</color>
4041

4142
<color name="colorAccentDark">@color/indigo_accent_200</color>
4243

mobile/src/main/res/values/colors.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
<color name="dark_theme_translucent_app_bar">#4F000000</color>
7474

7575
<color name="black_in_light">@android:color/black</color>
76+
<color name="white_in_dark">@android:color/white</color>
7677

7778
<color name="colorAccentDark">@color/pink_900</color>
7879

0 commit comments

Comments
 (0)