0

我开发了一个自定义组件,在其中实现了 onClick、onLongClick 和 onTouchListener。一切正常,除了 onLongClick 和 onClick 被调用两次,即使我只做了一次操作。有什么问题请指导解决方案。再次调用方法需要相当长的时间,即约 1 秒。

以下是代码:

自定义小部件:

@BindingMethods({
        @BindingMethod(type = RecordingButton.class, attribute = "progress", method = "setProgress"),
})
public class RecordingButton extends RelativeLayout {

    boolean isLongPressed;
    boolean isPressed;
    private Context mContext;
    private int progressBackground, progressColor, progressBarWidth;
    private int maxProgress, progress;
    private LayoutRecordingBtnBinding itemViewBinding;
    private OnRecordingButtonListener listener;
    private ValueAnimator progressAnimator;
    private View.OnTouchListener viewTouchListener = new View.OnTouchListener() {

        @Override
        public boolean onTouch(View pView, MotionEvent pEvent) {
            pView.onTouchEvent(pEvent);
            // We're only interested in when the button is released.
            switch (pEvent.getAction()) {
                case MotionEvent.ACTION_UP:
                    isPressed = false;
                    // We're only interested in anything if our speak button is currently pressed.
                    if (isLongPressed) {
                        AppLogger.d("usm_recording_button_2", "onTouch ACTION_UP is called to release longPress");
                        isLongPressed = false;
                        // Do something when the button is released.\
                        if (listener != null)
                            listener.onStopRecording();

                    } else {
                        setTintColor(R.color.fayvo_color);
                    }
                    break;
                case MotionEvent.ACTION_DOWN:
                    isPressed = true;
                    setTintColor(R.color.trans_fayvo_color);
                    break;

            }
            return false;
        }
    };

    public RecordingButton(Context context) {
        super(context);
        initializeView(context, null, 0);
    }

    public RecordingButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        initializeView(context, attrs, 0);
    }

    public RecordingButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initializeView(context, attrs, defStyleAttr);
    }

    private void initializeView(Context context, AttributeSet attrs, int defStyleAttr) {
        mContext = context;
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.RecordingButton, defStyleAttr, 0);

        try {
            maxProgress = array.getInteger(R.styleable.RecordingButton_android_max, 30);
            progress = array.getInteger(R.styleable.RecordingButton_android_progress, 0);
            progressBarWidth = array.getDimensionPixelSize(R.styleable.RecordingButton_progressWidth, -1);
            progressColor = array.getColor(R.styleable.RecordingButton_progressColor, Integer.MAX_VALUE);
            progressBackground = array.getColor(R.styleable.RecordingButton_progressBackgroundColor, Integer.MAX_VALUE);
        } finally {
            array.recycle();
        }

        itemViewBinding = LayoutRecordingBtnBinding.inflate(LayoutInflater.from(mContext), this, true);


        setListeners();

    }

    private void setListeners() {
        this.setOnClickListener(view -> {

            // check if recording is not running on long press already
//            if (progressAnimator != null && progressAnimator.isRunning())
//                return;

            //  AppLogger.d("usm_loading_btn_1", "onClick is called");
            if (listener != null) {
                AppLogger.d("usm_recording_button_0", "onClick is called");
                listener.onClick();
            }
        });

        /*itemViewBinding.ivCameraBtn*/
        this.setOnLongClickListener(pView -> {
            AppLogger.d("usm_recording_button_1.0", "onLongClick detected: already isLongPressed= " + isLongPressed + " ,isPressed= " + isPressed);
            if (isLongPressed /*|| !isPressed*/)  // method is calling twice , need to do action only once
                return true;
            setTintColor(R.color.trans_fayvo_color);
            // Do something when your hold starts here.
            isLongPressed = true;


            AppLogger.d("usm_recording_button_1.1", "onLongClick is called");
            animateInnerIcon(true);

            if (listener != null)
                listener.onLongClick();

            return true;
        });

        this.setOnTouchListener(viewTouchListener);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        setValues();
    }

    private void setValues() {
        try {
            setProgress(progress);
            setMaxProgress(maxProgress);
            setProgressColor(progressColor);
            setProgressBackgroundColor(progressBackground);
            setProgressBarWidth(progressBarWidth);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void setProgress(int progress) {
        itemViewBinding.circularProgressBar.setProgress(progress);
    }

    public void setMaxProgress(int maxProgress) {
        itemViewBinding.circularProgressBar.setProgressMax(maxProgress);
    }

    public void setProgressBarWidth(int strokeWidth) {
        if (strokeWidth > -1)
            itemViewBinding.circularProgressBar.setProgressBarWidth(strokeWidth);
    }

    public void setProgressColor(int color) {
        this.progressColor = color;
        if (progressColor != Integer.MAX_VALUE) {
            itemViewBinding.circularProgressBar.setColor(progressColor);
        }
    }

    public void setProgressBackgroundColor(int color) {
        this.progressBackground = color;
        if (progressBackground != Integer.MAX_VALUE) {
            itemViewBinding.circularProgressBar.setBackgroundColor(progressBackground);
        }
    }


    public void setTintColor(int tintColor) {
        // itemViewBinding.ivCameraBtn.setForegroundTintList(new ColorStateList()[]);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            itemViewBinding.ivCameraBtn.setImageTintList(ColorStateList.valueOf(ContextCompat.getColor(mContext, tintColor)));
        }
    }

    public void animateInnerIcon(boolean expand) {

        float from = expand ? 0f : 1f;
        float to = expand ? 1f : 0f;

        Animator scaleXAnimator = ObjectAnimator.ofFloat(itemViewBinding.ivInnerIcon, "scaleX", from, to);
        Animator scaleYAnimator = ObjectAnimator.ofFloat(itemViewBinding.ivInnerIcon, "scaleY", from, to);

        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.playTogether(scaleXAnimator, scaleYAnimator);
        animatorSet.setInterpolator(new DecelerateInterpolator());
        animatorSet.setDuration(expand ? 600 : 300);

        animatorSet.start();

    }


    public void animateProgress() {
        progressAnimator = ValueAnimator.ofFloat(0, maxProgress);
        progressAnimator.addUpdateListener(animation -> {
            try {
                Float val = (Float) animation.getAnimatedValue();
                itemViewBinding.circularProgressBar.setProgress(val);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        progressAnimator.setDuration(maxProgress * 1000);
        progressAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);

                isLongPressed = false;  // no action required on ActionUp of onTouch
                if (listener != null)
                    listener.onStopRecording();
                // reset();
            }
        });
        progressAnimator.setInterpolator(new LinearInterpolator());
        progressAnimator.start();
    }


    public void reset() {
        AppLogger.d("usm_recording_button_2", "reset recording button");
        if (progressAnimator != null)
            progressAnimator.cancel();

        itemViewBinding.circularProgressBar.setProgress(0);
        /*itemViewBinding.ivInnerIcon.setScaleX(0f);
        itemViewBinding.ivInnerIcon.setScaleY(0f);*/
        if (itemViewBinding.ivInnerIcon.getScaleX() > 0)
            animateInnerIcon(false);
    }

    public void setOnActionListener(OnRecordingButtonListener listener) {
        this.listener = listener;
    }

    public interface OnRecordingButtonListener {
        void onClick();

        void onLongClick();

        void onStopRecording();

    }
}
4

0 回答 0