双击自定义视图打开 2 个活动

Posted

技术标签:

【中文标题】双击自定义视图打开 2 个活动【英文标题】:Double tap on custom view opens up 2 Activities 【发布时间】:2018-12-22 10:39:17 【问题描述】:

我的片段中几乎没有自定义六边形视图,双击六边形视图后,它会打开 2 个活动。我已经尝试了几件事来避免这种行为,但似乎都不起作用。不知道为什么以下事情不起作用。

我已经尝试了这篇文章android Preventing Double Click On A Button 中的所有内容,但在我的情况下它们都不起作用。我不确定在这种特定情况下有什么奇怪的地方。

我尝试的第一件事是,将 Activties 启动模式设置为“singleTop”。那没有用。所以我尝试了其他的,比如 singleInstance、singleTask。

然后我尝试禁用单击六边形时的视图并在 onResume 中启用它。 即使这样也没有用。单击时尝试保存最后一次单击时间。即使这样也没有用。

这是我的代码片段。

public class MenuFragment extends BaseFragment implements 
OnHexagonClickListener
....
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 

    View view = inflater.inflate(R.layout.fragment_land_menu, container, false);
    ScrollView scroll_hexagon = view.findViewById(R.id.scroll_hexagon);
    isFirst = true;
    loadMenuData();
    scroll_hexagon.post(new Runnable() 
        @Override
        public void run() 
            int design_hexagon_width = getResources().getDimensionPixelSize(R.dimen.dimen_190dp);
            int design_hexagon_height = getResources().getDimensionPixelSize(R.dimen.dimen_160dp);
            int design_padding_horizontal = getResources().getDimensionPixelSize(R.dimen.dimen_5dp);
            int design_margin_horizontal = getResources().getDimensionPixelSize(R.dimen.dimen_3dp);
            int design_margin_vertical = getResources().getDimensionPixelSize(R.dimen.dimen_5dp);
            int design_margin_top = 0; //getResources().getDimensionPixelSize(R.dimen.dimen_5dp);

            int scroll_width = scroll_hexagon.getWidth();
            int hexagon_width = (int) (((scroll_width - design_padding_horizontal * 2) * 1.105f - design_margin_horizontal) / 2);
            int hexagon_margin_horizontal = hexagon_width - (int) ((scroll_width - design_padding_horizontal * 2) * 0.105f) + design_margin_horizontal;
            float scale = (float) hexagon_width / (float) design_hexagon_width;
            int hexagon_margin_vertical = ((int) (design_hexagon_height * scale) + design_margin_vertical) / 2;

            RelativeLayout hexagon_layout = view.findViewById(R.id.lyt_hexagon);
            for (int index = 0; index < mHexagonList.size(); index++) 
                Hexagon hexagon = mHexagonList.get(index);
                HexagonView hexagon_view = new HexagonView(activity, hexagon_width, hexagon_width);
                hexagon_view.setId(index);
                RelativeLayout.LayoutParams layoutparams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
                layoutparams.topMargin = design_margin_top + hexagon_margin_vertical * hexagon.getRowIndex();
                layoutparams.leftMargin = design_padding_horizontal + hexagon_margin_horizontal * hexagon.getColIndex();
                hexagon_view.setLayoutParams(layoutparams);
                hexagon_view.setData(hexagon.getType());
                hexagon_view.setOnHexagonClickListener(MenuFragment.this);
                hexagon_layout.addView(hexagon_view);
            
            hexagon_layout.requestLayout();
        
    );
    return view;


@Override
public void onClickHexagon(View view) 

    Hexagon hexagon = mHexagonList.get(view.getId());
    switch (hexagon.getType()) 
        case HexagonType.HEXAGON_PROFILE:
            startActivity(new Intent(activity, DashBoard.class));
            getActivity().overridePendingTransition(R.anim.anim_left_to_right, R.anim.anim_scale_out);
            break;
....

我的自定义视图代码:

public class HexagonView extends View implements Animation.AnimationListener 

private Paint mPaintBrush, mPaintText;
private LassoUtils mLassoUtils = null;
private List<PointF> mPointList = null;

private int mType;
private int mWidth, mHeight;
private int mWidthSpec, mHeightSpec;
private int mBackWidthSpec, mBackHeightSpec;
private int mThumbWidthSpec, mThumbHeightSpec, mThumbMarginSpec;
private int mIconWidthSpec, mIconHeightSpec, mIconMarginSpec;
private int mTextSize, mTextMarginSpec;

private String mText = "";

private Resources mResource;
private Bitmap mBackgroundBitmap = null;
private Bitmap mThumbBitmap = null;
private Bitmap mIconBitmap = null;
private OnHexagonClickListener mListener = null;
private Animation mAnim = null;

private boolean islasso = false;
private boolean isAnimating = false;

public HexagonView(Context context) 
    this(context, null);


public HexagonView(Context context, AttributeSet attr) 
    super(context, attr);


public HexagonView(Context context, int width, int height) 
    super(context, null);

    mType = HexagonType.HEXAGON_NONE;
    mResource = context.getResources();

    mWidthSpec = width;
    mHeightSpec = height;
    float scale = (float) width / (float) mResource.getDimensionPixelSize(R.dimen.dimen_190dp);
    mBackWidthSpec = (int) (mResource.getDimensionPixelSize(R.dimen.dimen_190dp) * scale);
    mBackHeightSpec = (int) (mResource.getDimensionPixelSize(R.dimen.dimen_160dp) * scale);
    mThumbWidthSpec = (int) (mResource.getDimensionPixelSize(R.dimen.dimen_185dp) * scale);
    mThumbHeightSpec = (int) (mResource.getDimensionPixelSize(R.dimen.dimen_171dp) * scale);
    mThumbMarginSpec = (int) (mResource.getDimensionPixelSize(R.dimen.dimen_10dp) * scale);
    mThumbMarginSpec = 0;
    mTextSize = (int) (mResource.getDimensionPixelSize(R.dimen.dimen_12sp) * scale);
    mTextMarginSpec = (int) (mResource.getDimensionPixelSize(R.dimen.dimen_38dp) * scale);
    mIconWidthSpec = (int) (mResource.getDimensionPixelSize(R.dimen.dimen_46dp) * scale);
    mIconHeightSpec = (int) (mResource.getDimensionPixelSize(R.dimen.dimen_44dp) * scale);
    mIconMarginSpec = (int) (mResource.getDimensionPixelSize(R.dimen.dimen_3dp) * scale);

    int backColor = mResource.getColor(R.color.transparent);
    int textColor = mResource.getColor(R.color.color_text_white);

    mBackgroundBitmap = getBitmap(mResource.getDrawable(R.drawable.ic_wk_hexagon_bg), mBackWidthSpec, mBackHeightSpec);

    mPaintBrush = new Paint();
    mPaintBrush.setAntiAlias(true);
    mPaintBrush.setStyle(Paint.Style.FILL);
    mPaintBrush.setColor(backColor);

    mPaintText = new Paint();
    mPaintText.setAntiAlias(true);
    mPaintText.setTextSize(mTextSize);
    mPaintText.setStyle(Paint.Style.FILL);
    mPaintText.setTextAlign(Paint.Align.CENTER);
    mPaintText.setColor(textColor);

    mAnim = AnimationUtils.loadAnimation(context, R.anim.hexagon_click);
    mAnim.setAnimationListener(this);


@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
    setMeasuredDimension(MeasureSpec.getSize(mWidthSpec), MeasureSpec.getSize(mHeightSpec));


@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) 
    mWidth = w;
    mHeight = h;


@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) 

    if (mWidth == 0 || mHeight == 0)
        return;

    int lenght = mWidth / 2;
    double randian30 = 30 * Math.PI / 180;
    float a = (float) (lenght * Math.sin(randian30));
    float b = (float) (lenght * Math.cos(randian30));
    float c = (mHeight - 2 * b) / 2;

    Path path = new Path();
    path.moveTo(mWidth, mHeight / 2);
    path.lineTo(mWidth - a, mHeight - c);
    path.lineTo(mWidth - a - lenght, mHeight - c);
    path.lineTo(0, mHeight / 2);
    path.lineTo(a, c);
    path.lineTo(mWidth - a, c);
    path.close();

    canvas.drawPath(path, mPaintBrush);

    if (mBackgroundBitmap != null)
        canvas.drawBitmap(mBackgroundBitmap, (float) (mWidth / 2 - mBackWidthSpec / 2), (float) (mHeight / 2 - mBackHeightSpec / 2), null);

    if (mThumbBitmap != null)
        canvas.drawBitmap(mThumbBitmap, (float) (mWidth / 2 - mThumbWidthSpec / 2), (float) (mHeight / 2 - mThumbHeightSpec / 2 + mThumbMarginSpec), null);

    if (mIconBitmap != null)
        canvas.drawBitmap(mIconBitmap, (float) (mWidth / 2 - mIconWidthSpec / 2), (float) (mHeight / 2 - mIconHeightSpec + mIconMarginSpec), null);

    if (!mText.isEmpty())
        canvas.drawText(mText, (float) (mWidth / 2), (float) (mHeight / 2 + mTextSize + mTextMarginSpec), mPaintText);

    if (mPointList == null)
        mPointList = new ArrayList<>();
    else
        mPointList.clear();

    PointF pf = new PointF();
    pf.set(mWidth, mHeight / 2);
    mPointList.add(pf);
    PointF pf1 = new PointF();
    pf1.set(mWidth - a, mHeight - c);
    mPointList.add(pf1);
    PointF pf2 = new PointF();
    pf2.set(mWidth - a - lenght, mHeight - c);
    mPointList.add(pf2);
    PointF pf3 = new PointF();
    pf3.set(0, mHeight / 2);
    mPointList.add(pf3);
    PointF pf4 = new PointF();
    pf4.set(a, c);
    mPointList.add(pf4);
    PointF pf5 = new PointF();
    pf5.set(mWidth - a, c);
    mPointList.add(pf5);

    if (mLassoUtils == null)
        mLassoUtils = new LassoUtils();
    mLassoUtils.setLassoList(mPointList);


@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) 
    switch (event.getAction()) 
        case MotionEvent.ACTION_DOWN:
            islasso = mLassoUtils.contains(event.getX(), event.getY());
            break;
        case MotionEvent.ACTION_MOVE:
            islasso = mLassoUtils.contains(event.getX(), event.getY());
            break;
        case MotionEvent.ACTION_UP:
            if (isAnimating)
                break;

            if (mType == HexagonType.HEXAGON_NONE)
                break;

            this.startAnimation(mAnim);
            break;
    
    return true;


@Override
public void onAnimationStart(Animation animation) 
    isAnimating = true;


@Override
public void onAnimationEnd(Animation animation) 
    if (islasso) 
        if (mListener != null)
            mListener.onClickHexagon(this);
    
    islasso = false;
    isAnimating = false;


@Override
public void onAnimationRepeat(Animation animation) 



public void setData(int type) 

    mType = type;
    Drawable originThumbDrawable = null;
    Drawable originIconDrawable = null;

    switch (type) 
       case HexagonType.HEXAGON_PROFILE:
            originThumbDrawable = mResource.getDrawable(R.mipmap.land_hexagon_profile);
            originIconDrawable = mResource.getDrawable(R.mipmap.land_icon_profile);
            mText = mResource.getString(R.string.landing_profile);
            break;

        case HexagonType.HEXAGON_LEARNING:
            originThumbDrawable = mResource.getDrawable(R.mipmap.land_hexagon_learning);
            originIconDrawable = mResource.getDrawable(R.mipmap.land_icon_learning);
            mText = mResource.getString(R.string.landing_learning);
            break;

    

    if (originThumbDrawable != null)
        mThumbBitmap = getBitmap(originThumbDrawable, mThumbWidthSpec, mThumbHeightSpec);

    if (originIconDrawable != null)
        mIconBitmap = getBitmap(originIconDrawable, mIconWidthSpec, mIconHeightSpec);


public void setOnHexagonClickListener(OnHexagonClickListener listener) 
    this.mListener = listener;


private Bitmap getBitmap(Drawable drawable, int width, int height) 
    Canvas canvas = new Canvas();
    Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
    canvas.setBitmap(bitmap);
    drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
    drawable.draw(canvas);
    return Bitmap.createScaledBitmap(bitmap, width, height, false);

【问题讨论】:

请问你能在HexagonView中分享setOnHexagonClickListener的代码吗? 如果答案适合您,请考虑接受它作为正确答案 @VinayRathod :我通过添加自定义视图代码更新了我的问题。请看一下。 【参考方案1】:

这是最好的 hack,双击会在不到一秒的时间内发生,您可以在第一次点击后的一秒内禁用点击。在类上添加一个全局变量

public static boolean clickable = true;

在点击过程中切换它,效果很好

    if (!clickable)
        return;
    
    clickable = false;
    new Handler().postDelayed(new Runnable() 
        @Override
        public void run() 
            clickable = true;
        
    , 1000);
    //continue with your click code

【讨论】:

如果有点奇怪,不是我的情况。这是行不通的。我已经用自定义 HexagonView 的代码更新了我的问题【参考方案2】:
public boolean clickable = true;

@Override
public void onAnimationEnd(Animation animation) 
    if (islasso) 
        if (mListener != null && clickable) 
            clickable = false;
            mListener.onClickHexagon(this);
            new Handler().postDelayed(new Runnable() 
                @Override
                public void run() 
                    clickable = true;
                
            , 1500);
        
    
    islasso = false;
    isAnimating = false;

试试这个

【讨论】:

这样,一旦我单击六边形并转到下一个活动,然后返回并再次单击,侦听器将为空。所以点击不起作用。有什么解决办法吗? 我需要在 MenuFragment onClickListener 中添加一些东西吗? 可能是你的动画开始了两次 这个答案最初几乎可以工作,在 OnResume 中添加一些额外的代码后,它工作正常。

以上是关于双击自定义视图打开 2 个活动的主要内容,如果未能解决你的问题,请参考以下文章

如何从简单列表视图的按钮打开新活动

我想在自定义列表视图中选择一项,该项目将显示在第二个活动的文本视图上

如何让自定义视图观察包含片段的生命周期事件而不是活动?

如何使用来自另一个活动的自定义适配器更新列表视图?

使用自定义视图将字符串数组传递给另一个活动

如何将一个自定义列表的选定数据显示到同一活动的另一个自定义列表视图