MyActionBar, LineView: use setTooltipText() rather than our own CheatSheet

This commit is contained in:
Andreas Schildbach 2022-09-10 16:11:44 +02:00
parent a5c17eaff2
commit 1c6dc66814
3 changed files with 17 additions and 146 deletions

View file

@ -19,6 +19,7 @@ package de.schildbach.oeffi;
import android.content.Context;
import android.content.res.Resources;
import android.os.Build;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.Gravity;
@ -33,7 +34,6 @@ import android.widget.ImageView.ScaleType;
import android.widget.LinearLayout;
import android.widget.PopupMenu;
import android.widget.TextView;
import de.schildbach.oeffi.util.CheatSheet;
import de.schildbach.oeffi.util.ToggleImageButton;
public class MyActionBar extends LinearLayout {
@ -147,7 +147,8 @@ public class MyActionBar extends LinearLayout {
if (descriptionRes != 0) {
final String description = context.getString(descriptionRes);
button.setContentDescription(description);
CheatSheet.setup(button, description);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
button.setTooltipText(description);
}
addView(button, BUTTON_INSERT_INDEX, buttonParams);
@ -166,7 +167,8 @@ public class MyActionBar extends LinearLayout {
if (descriptionRes != 0) {
final String description = context.getString(descriptionRes);
button.setContentDescription(description);
CheatSheet.setup(button, description);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
button.setTooltipText(description);
}
addView(button, BUTTON_INSERT_INDEX, buttonParams);
@ -176,7 +178,8 @@ public class MyActionBar extends LinearLayout {
public View addProgressButton() {
progressAlwaysVisible = true;
progressView.setVisibility(View.VISIBLE);
CheatSheet.setup(progressButton);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
progressButton.setTooltipText(progressButton.getContentDescription());
return getProgressButton();
}

View file

@ -28,6 +28,7 @@ import android.graphics.Paint.FontMetrics;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.Typeface;
import android.os.Build;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ReplacementSpan;
@ -36,7 +37,6 @@ import android.widget.TextView;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import de.schildbach.oeffi.R;
import de.schildbach.oeffi.util.CheatSheet;
import de.schildbach.pte.Standard;
import de.schildbach.pte.dto.Line;
import de.schildbach.pte.dto.Line.Attr;
@ -177,16 +177,19 @@ public class LineView extends TextView {
"product_" + Character.toLowerCase(line.productCode()), "string", context.getPackageName());
final String sheet = Joiner.on('\n').skipNulls().join(line.name,
productResId != 0 ? context.getString(productResId) : null, line.network);
if (Strings.emptyToNull(sheet) != null)
CheatSheet.setup(this, sheet);
else
CheatSheet.remove(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
if (Strings.emptyToNull(sheet) != null)
setTooltipText(sheet);
else
setTooltipText(null);
} else {
CheatSheet.remove(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
setTooltipText(null);
}
} else {
setText(null);
CheatSheet.remove(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
setTooltipText(null);
}
}

View file

@ -1,135 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.schildbach.oeffi.util;
import android.content.Context;
import android.graphics.Rect;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.View;
import android.widget.Toast;
/**
* Helper class for showing cheat sheets (tooltips) for icon-only UI elements on long-press. This is already
* default platform behavior for icon-only {@link android.app.ActionBar} items and tabs. This class provides
* this behavior for any other such UI element.
*
* <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">
* ActionMenuItemView.java</a>.
*/
public class CheatSheet {
/**
* The estimated height of a toast, in dips (density-independent pixels). This is used to determine
* whether or not the toast should appear above or below the UI element.
*/
private static final int ESTIMATED_TOAST_HEIGHT_DIPS = 48;
/**
* Sets up a cheat sheet (tooltip) for the given view by setting its
* {@link android.view.View.OnLongClickListener}. When the view is long-pressed, a {@link Toast} with the
* view's {@link android.view.View#getContentDescription() content description} will be shown either above
* (default) or below the view (if there isn't room above it).
*
* @param view
* The view to add a cheat sheet for.
*/
public static void setup(View view) {
view.setOnLongClickListener(v -> showCheatSheet(v, v.getContentDescription()));
}
/**
* Sets up a cheat sheet (tooltip) for the given view by setting its
* {@link android.view.View.OnLongClickListener}. When the view is long-pressed, a {@link Toast} with the
* given text will be shown either above (default) or below the view (if there isn't room above it).
*
* @param view
* The view to add a cheat sheet for.
* @param textResId
* The string resource containing the text to show on long-press.
*/
public static void setup(View view, final int textResId) {
view.setOnLongClickListener(v -> showCheatSheet(v, v.getContext().getString(textResId)));
}
/**
* Sets up a cheat sheet (tooltip) for the given view by setting its
* {@link android.view.View.OnLongClickListener}. When the view is long-pressed, a {@link Toast} with the
* given text will be shown either above (default) or below the view (if there isn't room above it).
*
* @param view
* The view to add a cheat sheet for.
* @param text
* The text to show on long-press.
*/
public static void setup(View view, final CharSequence text) {
view.setOnLongClickListener(v -> showCheatSheet(v, text));
}
/**
* Removes the cheat sheet for the given view by removing the view's
* {@link android.view.View.OnLongClickListener}.
*
* @param view
* The view whose cheat sheet should be removed.
*/
public static void remove(final View view) {
view.setOnLongClickListener(null);
}
/**
* Internal helper method to show the cheat sheet toast.
*/
private static boolean showCheatSheet(View view, CharSequence text) {
if (TextUtils.isEmpty(text)) {
return false;
}
final int[] screenPos = new int[2]; // origin is device display
final Rect displayFrame = new Rect(); // includes decorations (e.g. status bar)
view.getLocationOnScreen(screenPos);
view.getWindowVisibleDisplayFrame(displayFrame);
final Context context = view.getContext();
final int viewWidth = view.getWidth();
final int viewHeight = view.getHeight();
final int viewCenterX = screenPos[0] + viewWidth / 2;
final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
final int estimatedToastHeight = (int) (ESTIMATED_TOAST_HEIGHT_DIPS
* context.getResources().getDisplayMetrics().density);
Toast cheatSheet = Toast.makeText(context, text, Toast.LENGTH_SHORT);
boolean showBelow = screenPos[1] < estimatedToastHeight;
if (showBelow) {
// Show below
// Offsets are after decorations (e.g. status bar) are factored in
cheatSheet.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL, viewCenterX - screenWidth / 2,
screenPos[1] - displayFrame.top + viewHeight);
} else {
// Show above
// Offsets are after decorations (e.g. status bar) are factored in
// NOTE: We can't use Gravity.BOTTOM because when the keyboard is up
// its height isn't factored in.
cheatSheet.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL, viewCenterX - screenWidth / 2,
screenPos[1] - displayFrame.top - estimatedToastHeight);
}
cheatSheet.show();
return true;
}
}