【问题标题】:Android drag elevation translationz on cardview with itemTouchHelper in RecyclerviewAndroid在Recyclerview中使用itemTouchHelper在cardview上拖动海拔翻译
【发布时间】:2019-03-23 04:31:19
【问题描述】:

我在弄清楚如何在拖动时暂时提升 cardViews 时遇到问题。我使用带有 cardViews 的回收站视图,这是我的 itemtouchhelper:

class ListTouchHelper extends ItemTouchHelper.Callback {

    private final ActionCompletionContract contract;

    public ListTouchHelper(ActionCompletionContract contract) {
        this.contract = contract;
    }
    @Override
    public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
        int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
        return makeMovementFlags(dragFlags, swipeFlags);
    }

    @Override
    public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
        contract.onViewMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
        return true;
    }

    @Override
    public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
        if (direction == ItemTouchHelper.LEFT) {
            contract.onViewSwipedLeft(viewHolder.getAdapterPosition());
        } else if (direction == ItemTouchHelper.RIGHT) {
            contract.onViewSwipedRight(viewHolder.getAdapterPosition());
        }
    }

    public interface ActionCompletionContract {
        void onViewMoved(int oldPosition, int newPosition);
        void onViewSwipedLeft(int position);
        void onViewSwipedRight(int position);
    }
}


我已经设法通过以下方式暂时提升它:

导致:(阴影以某种方式被剪裁了?)

但是,只要稍微移动视图,高度就会消失:

我的问题是:当卡片被拖动时,我如何获得高程(包括阴影)?

提前致谢!

【问题讨论】:

    标签: android android-recyclerview cardview android-elevation


    【解决方案1】:

    好的,我解决了,有点。我认为由于某些其他原因默认情况下它不起作用,但是我设法编写了一个解决方法。

    private boolean first = true; //first draw of cardView?
    private boolean last = false; //last draw of cardView?
    
    @Override
    public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
        //add elevation on first draw
        if (first) {
            ViewPropertyAnimator animator = viewHolder.itemView.animate();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //consider SDK version
                viewHolder.itemView.setTranslationZ(7);
                animator.start();
            }
            first = false;
        }
        //remove translationZ in last edit
        if (last) {
            ViewPropertyAnimator animator = viewHolder.itemView.animate();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //consider SDK version
                viewHolder.itemView.setTranslationZ(0);
                animator.start();
            }
            //reset values
            last=false;
            first=true;
        }
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
    }
    
    @Override
    public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
        super.clearView(recyclerView, viewHolder);
        last = true; //only one more OnChildDrawWillBeCalled
    }
    

    上面的代码已添加到您的 ItemTouchHelper.Callback 中,并且应该可以正常工作。 基本思想是手动控制平移z的绘制。 为此,我知道何时绘制第一个画布,何时绘制最后一个画布,而 cancas 将显示阴影。

    Maxbe 还有一条评论:ViewPropertyAnimator 与 xml 布局文件结合起来非常不直观且存在错误,因此如果可以避免,我建议您这样做,而是尝试以编程方式为视图更改和效果设置动画。

    希望这可以帮助某人。

    【讨论】:

      【解决方案2】:

      @LivinTheNoobLife 在您的解决方案中,您正在使用 ViewPropertyAnimator,但您没有对其设置任何翻译,因此不会应用任何动画。

      这是我的解决方案,带有正常工作的浮动动画:

      class DragHelper extends ItemTouchHelper.Callback {    
      private boolean cardPicked = true;
      private boolean reset = false;
      
      @Override
      public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
      
          // elevate only when picked for the first time
          if (cardPicked) { 
              ViewPropertyAnimator animator = viewHolder.itemView.animate();
              animator.translationZ(16);
              animator.setDuration(200);
              animator.setInterpolator(new AccelerateDecelerateInterpolator());
              animator.start();
      
              cardPicked = false;
          }
      
          // when your item is not floating anymore
          if (reset){
              ViewPropertyAnimator animator = viewHolder.itemView.animate();
      
              animator.translationZ(0);
              animator.setDuration(200);
              animator.setInterpolator(new AccelerateInterpolator());
              animator.start();
      
              cardPicked = true;
              reset = false;
          }
          super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
      }
      
      // As the doc says
      // Called by the ItemTouchHelper when the user interaction with an element is over and it also completed its animation.
      @Override
      public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
          super.clearView(recyclerView, viewHolder);
      
           // interaction is over, time to reset our elevation
           reset = true;
      }
      }
      

      【讨论】:

        猜你喜欢
        • 2018-01-13
        • 1970-01-01
        • 2021-07-19
        • 2015-01-15
        • 2023-03-06
        • 2017-02-05
        • 1970-01-01
        • 2017-06-11
        • 2016-02-03
        相关资源
        最近更新 更多