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

在Java的MultiTouchListener中避免点击重复添加View以消除闪烁

修复点击View重复添加导致的卡顿/闪烁问题

问题根源

每次点击View时,都会重复执行以下冗余操作:

  • 重新inflate并添加view2到frameLayout,导致布局中堆积大量重复弹窗视图
  • 重复设置frmBorder的背景资源,触发不必要的视图重绘

这些重复操作会引发频繁的布局计算和绘制流程,最终导致界面卡顿或闪烁。


修复方案

1. 提前初始化弹窗视图(避免重复创建)

将view2及其中的控件作为Activity成员变量,在初始化阶段(如onCreate)仅创建一次,不再每次点击都重新inflate。

// Activity成员变量声明
private View view2;
private TextView imgPhotoEditorEdit;
private TextView imgPhotoEditorClose;
private FrameLayout frameLayout;
// 在Activity的onCreate方法中初始化(仅执行一次)
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.your_activity_layout);
    
    frameLayout = findViewById(R.id.frameLayout);
    // 初始化弹窗视图,添加到布局后默认隐藏
    view2 = LayoutInflater.from(this).inflate(R.layout.pop_up_text, frameLayout, false);
    imgPhotoEditorEdit = view2.findViewById(R.id.imgPhotoEditorEdit);
    imgPhotoEditorClose = view2.findViewById(R.id.imgPhotoEditorClose);
    view2.setElevation(20);
    frameLayout.addView(view2);
    view2.setVisibility(View.GONE);
    
    // 给关闭按钮添加隐藏逻辑
    imgPhotoEditorClose.setOnClickListener(v -> view2.setVisibility(View.GONE));
}

2. 修改点击事件逻辑(避免重复操作)

在点击回调中,仅做显示/隐藏弹窗、更新弹窗位置和按需设置边框的操作,移除重复创建和添加视图的代码。

multiTouchListener = getMultiTouchListener();
multiTouchListener.setOnGestureControl(new MultiTouchListener.OnGestureControl() {
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public void onClick() {
        // 隐藏其他布局
        if (filter_layout.getVisibility() == View.VISIBLE)
            filter_layout.setVisibility(View.GONE);
        if (sticker_layout.getVisibility() == View.VISIBLE)
            sticker_layout.setVisibility(View.GONE);

        text_layout.setVisibility(View.VISIBLE);

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                // 仅当边框未设置时才更新,避免重复触发重绘
                Drawable targetBorder = getResources().getDrawable(R.drawable.rounded_border_tv);
                if (frmBorder.getBackground() == null || 
                    !frmBorder.getBackground().getConstantState().equals(targetBorder.getConstantState())) {
                    frmBorder.setBackgroundResource(R.drawable.rounded_border_tv);
                }

                // 显示弹窗并更新位置
                view2.setVisibility(View.VISIBLE);
                
                Rect rectf = new Rect();
                selected_View.getGlobalVisibleRect(rectf);

                View rootLayout = selected_View.getRootView().findViewById(R.id.frameLayout);
                int[] viewLocation = new int[2];
                selected_View.getLocationInWindow(viewLocation);
                int[] rootLocation = new int[2];
                rootLayout.getLocationInWindow(rootLocation);

                // 计算弹窗相对于父布局的位置
                int relativeLeft = viewLocation[0] - rootLocation[0];
                int relativeTop = viewLocation[1] - rootLocation[1];
                
                // 调整弹窗位置(可根据需求自定义)
                view2.setX(relativeLeft + rectf.width());
                view2.setY(relativeTop);
            }
        }, 100);
    }
});

额外优化建议

  • 如果支持切换选中多个View,可记录当前选中的View,仅对新选中的View设置边框,同时隐藏弹窗后重新显示到新位置
  • 移除不必要的日志输出,减少性能消耗

内容的提问来源于stack exchange,提问作者Roushan Mehmood

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 08:27:11