如何创建包含TextView与ImageView的Tooltip?求推荐相关开源库
自定义包含TextView和ImageView的Tooltip实现方案
不需要依赖第三方库,自己实现其实很简单,这里提供两种常用的实现方式:
方法一:基于PopupWindow实现(适合页面内局部提示)
1. 创建Tooltip布局文件
新建layout_tooltip.xml,按需调整布局结构和样式:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="12dp" android:background="@drawable/tooltip_bg"> <ImageView android:id="@+id/tooltip_icon" android:layout_width="24dp" android:layout_height="24dp" android:src="@drawable/ic_info" android:layout_marginEnd="8dp"/> <TextView android:id="@+id/tooltip_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="自定义Tooltip提示内容" android:textColor="@color/white" android:textSize="14sp"/> </LinearLayout>
2. 实现带箭头的背景
新建drawable/tooltip_bg.xml,用layer-list实现带箭头的深色背景:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 主体圆角背景 --> <item> <shape android:shape="rectangle"> <solid android:color="#333333"/> <corners android:radius="8dp"/> </shape> </item> <!-- 顶部箭头(可根据显示位置调整方向) --> <item android:top="-10dp" android:left="40dp" android:right="40dp"> <rotate android:fromDegrees="45"> <shape android:shape="rectangle"> <solid android:color="#333333"/> </shape> </rotate> </item> </layer-list>
3. 封装Tooltip工具类
public class CustomTooltip { private PopupWindow popupWindow; public void show(View anchorView, String tipText, Drawable icon) { // 加载布局 View tooltipView = LayoutInflater.from(anchorView.getContext()) .inflate(R.layout.layout_tooltip, null); TextView textView = tooltipView.findViewById(R.id.tooltip_text); ImageView imageView = tooltipView.findViewById(R.id.tooltip_icon); // 设置内容 textView.setText(tipText); if (icon != null) { imageView.setImageDrawable(icon); } // 初始化PopupWindow popupWindow = new PopupWindow(tooltipView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); popupWindow.setFocusable(true); popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); popupWindow.setOutsideTouchable(true); // 计算显示位置(示例为锚点View上方,间距10dp) int[] anchorLoc = new int[2]; anchorView.getLocationOnScreen(anchorLoc); int offsetX = anchorLoc[0] - (tooltipView.getMeasuredWidth() - anchorView.getWidth()) / 2; int offsetY = anchorLoc[1] - tooltipView.getMeasuredHeight() - dp2px(anchorView.getContext(), 10); popupWindow.showAtLocation(anchorView, Gravity.NO_GRAVITY, offsetX, offsetY); } public void dismiss() { if (popupWindow != null && popupWindow.isShowing()) { popupWindow.dismiss(); } } private int dp2px(Context context, int dp) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics()); } }
4. 使用示例
在点击/长按事件中触发:
Button showBtn = findViewById(R.id.btn_show_tip); showBtn.setOnClickListener(v -> { CustomTooltip tooltip = new CustomTooltip(); tooltip.show(v, "这是你的提示内容", getResources().getDrawable(R.drawable.ic_info)); });
方法二:基于WindowManager实现(适合全局悬浮提示)
如果需要在任意界面显示Tooltip,可采用此方式,注意权限申请:
1. 申请权限
在AndroidManifest.xml中添加:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
Android 6.0+需要动态申请悬浮窗权限,可通过Settings.canDrawOverlays(context)判断权限状态。
2. 封装全局Tooltip类
public class GlobalTooltip { private WindowManager windowManager; private View tooltipView; private WindowManager.LayoutParams windowParams; public GlobalTooltip(Context context) { windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); tooltipView = LayoutInflater.from(context).inflate(R.layout.layout_tooltip, null); // 配置Window参数 windowParams = new WindowManager.LayoutParams(); windowParams.type = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY : WindowManager.LayoutParams.TYPE_PHONE; windowParams.format = PixelFormat.TRANSLUCENT; windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; windowParams.width = WindowManager.LayoutParams.WRAP_CONTENT; windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT; windowParams.gravity = Gravity.TOP | Gravity.START; } public void show(View anchorView, String tipText, Drawable icon) { if (tooltipView == null) return; TextView textView = tooltipView.findViewById(R.id.tooltip_text); ImageView imageView = tooltipView.findViewById(R.id.tooltip_icon); textView.setText(tipText); if (icon != null) imageView.setImageDrawable(icon); // 计算锚点位置 int[] anchorLoc = new int[2]; anchorView.getLocationOnScreen(anchorLoc); windowParams.x = anchorLoc[0] - (tooltipView.getMeasuredWidth() - anchorView.getWidth()) / 2; windowParams.y = anchorLoc[1] - tooltipView.getMeasuredHeight() - dp2px(anchorView.getContext(), 10); if (tooltipView.getParent() == null) { windowManager.addView(tooltipView, windowParams); } } public void dismiss() { if (tooltipView != null && tooltipView.getParent() != null) { windowManager.removeView(tooltipView); tooltipView = null; } } private int dp2px(Context context, int dp) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics()); } }
3. 使用示例
if (Settings.canDrawOverlays(this)) { GlobalTooltip globalTooltip = new GlobalTooltip(this); globalTooltip.show(anchorView, "全局提示内容", getResources().getDrawable(R.drawable.ic_warning)); } else { // 引导用户开启悬浮窗权限 Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())); startActivityForResult(intent, 100); }
内容的提问来源于stack exchange,提问作者Alex Wesley
相关产品推荐
相关产品推荐

