kotlin 如何在聊天应用程序中制作向左滑动回复动画?

qni6mghb  于 2023-02-09  发布在  Kotlin
关注(0)|答案(1)|浏览(144)

我正在做一个信使项目,它即将完成。但是我想做一个通过滑动回复特定消息的功能。我搜索了一下,发现了一个惊人的article。所以我刚刚实现了它,它应该工作。
现在的问题是如何让它工作的右侧消息,向左滑动回复。或者我们可以说只是相反的通常。我只是想让它看起来像WhatsApp的专业。
我试过这种方式,但它只是向左滑动,没有回复动画没有振动。Source Code

override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
    mView = viewHolder.itemView
    imageDrawable = context.getDrawable(R.drawable.ic_reply_black_24dp)!!
    shareRound = context.getDrawable(R.drawable.ic_round_shape)!!
    val direction = if (viewHolder.itemViewType != MessageType.SEND) {
        RIGHT
    } else {
        LEFT
    }
    return ItemTouchHelper.Callback.makeMovementFlags(ACTION_STATE_IDLE, direction)
}
nhn9ugyo

nhn9ugyo1#

公共类SwipeReply扩展了ItemTouchHelper。回调{

private Drawable imageDrawable;
private Drawable shareRound;
private RecyclerView.ViewHolder currentItemViewHolder;
private View mView;
private float dX = 0f;
private float replyButtonProgress = 0f;
private long lastReplyButtonAnimationTime = 0;
private boolean swipeBack = false;
private boolean isVibrate = false;
private boolean startTracking = false;
private float density;
private final Context context;
private final SwipeControllerActions swipeControllerActions;
public SwipeReply(@NotNull Context context, @NotNull SwipeControllerActions swipeControllerActions) {
    super();
    this.context = context;
    this.swipeControllerActions = swipeControllerActions;
    this.density = 1.0F;
}
@Override
public int getMovementFlags(@NonNull RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    mView = viewHolder.itemView;
    if(viewHolder.getItemViewType()== MessageAdapter.RECEIVER_VIEW_TYPE||viewHolder.getItemViewType()== MessageAdapter.RECEIVER_VIEW_IMAGE||viewHolder.getItemViewType()== MessageAdapter.RECEIVED_MESSAGE_IMAGE){
        imageDrawable = context.getDrawable(R.drawable.ic_reply);
        shareRound = context.getDrawable(R.drawable.ic_round);
        return ItemTouchHelper.Callback.makeMovementFlags(ACTION_STATE_IDLE, RIGHT);
    }
    if(viewHolder.getItemViewType()== MessageAdapter.SENDER_VIEW_TYPE||viewHolder.getItemViewType()== MessageAdapter.SENDER_VIEW_IMAGE||viewHolder.getItemViewType()== MessageAdapter.SENDER_MESSAGE_IMAGE){
        imageDrawable = context.getDrawable(R.drawable.ic_reply);
        shareRound = context.getDrawable(R.drawable.ic_round);
        return ItemTouchHelper.Callback.makeMovementFlags(ACTION_STATE_IDLE, LEFT);
    }

    return 0;
}
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
    return false;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
}
@Override
public int convertToAbsoluteDirection(int flags, int layoutDirection) {
    if (swipeBack) {
        swipeBack = false;
        return 0;
    }
    return super.convertToAbsoluteDirection(flags, layoutDirection);
}
@Override
public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
    if (actionState == ACTION_STATE_SWIPE) {
        setTouchListener(recyclerView, viewHolder);
    }
    super.onChildDraw(c, recyclerView, viewHolder, dX/2, dY, actionState, isCurrentlyActive);
    this.dX = dX;
    startTracking = true;
    currentItemViewHolder = viewHolder;
    drawReplyButton(c);
}
@SuppressLint("ClickableViewAccessibility")
private void setTouchListener(RecyclerView recyclerView, final RecyclerView.ViewHolder viewHolder) {
    recyclerView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            swipeBack = motionEvent.getAction() == MotionEvent.ACTION_CANCEL || motionEvent.getAction() == MotionEvent.ACTION_UP;
            if (swipeBack) {
                if (Math.abs(mView.getTranslationX()) >=convertTodp(80)) {
                    swipeControllerActions.showReplyUI(viewHolder.getAdapterPosition());
                }
            }
            return false;
        }
    });
}
private void drawReplyButton(Canvas canvas) {
    if (currentItemViewHolder == null) {
        return;
    }
    float translationX = mView.getTranslationX();
    long newTime = System.currentTimeMillis();
    long dt = Math.min(17, newTime - lastReplyButtonAnimationTime)/2;
    lastReplyButtonAnimationTime = newTime;
    boolean showing = translationX >= convertTodp(30);
    boolean showing1 = translationX <=-convertTodp(30);
    if (showing|showing1) {
        if (replyButtonProgress < 1.0f) {
            replyButtonProgress += dt / 180.0f;
            if (replyButtonProgress > 1.0f) {
                replyButtonProgress = 1.0f;
            } else {
                mView.invalidate();
            }
        }
    } else if (translationX == 0.0f) {
        replyButtonProgress = 0f;
        startTracking = false;
        isVibrate = false;
    }else {
        if (replyButtonProgress > 0.0f) {
            replyButtonProgress -= dt / 180.0f;
            if (replyButtonProgress < 0.1f) {
                replyButtonProgress = 0f;
            } else {
                mView.invalidate();
            }
        }
    }
    int alpha;
    float scale;
    if (showing||showing1) {
        scale = this.replyButtonProgress <= 0.8F ? 1.2F * (this.replyButtonProgress / 0.8F) : 1.2F - 0.2F * ((this.replyButtonProgress - 0.8F) / 0.2F);
        alpha = (int) Math.min(255.0F, (float) 255 * (this.replyButtonProgress / 0.8F));
    } else {
        scale = this.replyButtonProgress;
        alpha = (int) Math.min(255.0F, (float) 255 * this.replyButtonProgress);
    }
    shareRound.setAlpha(alpha);
    imageDrawable.setAlpha(alpha);
    if (startTracking) {
        if (!isVibrate && (mView.getTranslationX() >= convertTodp(80)||mView.getTranslationX() <= -convertTodp(80))) {
            mView.performHapticFeedback(
                    HapticFeedbackConstants.KEYBOARD_TAP,
                    HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING
            );
            isVibrate = true;
        }
    }

    int x;
    float y;
    y = (float) ((mView.getTop() + mView.getMeasuredHeight() / 2));
    if(mView.getTranslationX()>0){
        if (mView.getTranslationX() > (float) this.convertTodp(130)) {
            x = this.convertTodp(130) / 2;
        }else {
            x = (int) (mView.getTranslationX() / (float) 2);
        }
        shareRound.setBounds((int) ((float) x - (float) this.convertTodp(16) * scale), (int) (y - (float) this.convertTodp(16) * scale), (int) ((float) x + (float) this.convertTodp(16) * scale), (int) (y + (float) this.convertTodp(16) * scale));
        shareRound.draw(canvas);
        imageDrawable.setBounds((int) ((float) x - (float) this.convertTodp(10) * scale), (int) (y - (float) this.convertTodp(10) * scale), (int) ((float) x + (float) this.convertTodp(10) * scale), (int) (y + (float) this.convertTodp(8) * scale));
        imageDrawable.draw(canvas);
        shareRound.setAlpha(255);
        imageDrawable.setAlpha(255);
    }
    else if(0>mView.getTranslationX()){
        if (mView.getTranslationX() < -(float) this.convertTodp(130)) {
            x = mView.getRight()+(int) (mView.getTranslationX() / (float) 2);
        }else {
            x = mView.getRight()+(int) (mView.getTranslationX() / (float) 2);
        }
        shareRound.setBounds((int) ((float) x - (float) this.convertTodp(16) * scale), (int) (y - (float) this.convertTodp(16) * scale), (int) ((float) x + (float) this.convertTodp(16) * scale), (int) (y + (float) this.convertTodp(16) * scale));
        shareRound.draw(canvas);
        imageDrawable.setBounds((int) ((float) x - (float) this.convertTodp(10) * scale), (int) (y - (float) this.convertTodp(10) * scale), (int) ((float) x + (float) this.convertTodp(10) * scale), (int) (y + (float) this.convertTodp(8) * scale));
        imageDrawable.draw(canvas);
        shareRound.setAlpha(255);
        imageDrawable.setAlpha(255);

    }
}

private int convertTodp(int pixel) {
    return this.dp((float) pixel, this.context);
}

public int dp(Float value, Context context) {
    if (this.density == 1.0F) {
        this.checkDisplaySize(context);
    }

    return value == 0.0F ? 0 : (int) Math.ceil((double) (this.density * value));
}

private void checkDisplaySize(Context context) {
    try {
        this.density = context.getResources().getDisplayMetrics().density;
    } catch (Exception e) {
        e.printStackTrace();
    }

}

public interface SwipeControllerActions {
    void showReplyUI(int position);
}

}

相关问题