You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建包含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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 09:45:34