【问题标题】:android drag view smoothandroid拖动视图流畅
【发布时间】:2012-01-22 01:32:43
【问题描述】:

我必须在屏幕上拖动一些视图。我通过从触摸侦听器的 ACTION_MOVE 上的运动事件更改布局参数的左侧和顶部来修改它们的位置。有没有办法更顺畅地“拖动”物品?因为这种“拖拽”一点都不顺畅……这是代码

public boolean onTouch(View view, MotionEvent motionEvent) {
    switch (motionEvent.getAction()) {
        case MotionEvent.ACTION_DOWN:
            dx = (int) motionEvent.getX();
            dy = (int) motionEvent.getY();
            break;

        case MotionEvent.ACTION_MOVE:
            int x = (int) motionEvent.getX();
            int y = (int) motionEvent.getY();
            RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) view.getLayoutParams();
            int left = lp.leftMargin + (x - dx);
            int top = lp.topMargin + (y - dy);
            lp.leftMargin = left;
            lp.topMargin = top;
            view.setLayoutParams(lp);
            break;
    }
    return true;
}

【问题讨论】:

标签: android view drag smooth


【解决方案1】:

了解您如何处理 ACTION_MOVE 事件会很有用。 您是否使用 event.getHistorical() 方法来利用所有要点? 如果这不能给您带来更平滑的拖动,其他想法可能是在路径上插入点。我相信在实现运动的流畅性和对用户触摸的快速响应之间会有一个权衡。 HTH。

【讨论】:

  • 您是否在 ScrollView 中使用拖动?@gabi
【解决方案2】:

移动不顺畅的原因是leftMargin和topMargin的整数值。
平滑移动的位置应该是浮动的。
This 可以帮助。

【讨论】:

  • LayoutParams 需要整数。
【解决方案3】:

尝试使用motionEvent.getRawX()和motionEvent.getRawY()代替getY和getX

【讨论】:

    【解决方案4】:

    你应该四舍五入你的整数,使用边距也不会很平滑,使用不同的布局并根据屏幕尺寸设置 X 和 Y 坐标。

    【讨论】:

      【解决方案5】:

      你不需要使用 LayoutParameters 来拖动。您只需设置视图的 X 和 Y 坐标即可。你可以阅读更多关于here的内容。

      你可以这样做。

        @Override
        public boolean onTouch(View view, MotionEvent event) {
          switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
              dX = view.getX() - event.getRawX();
              dY = view.getY() - event.getRawY();
              break;
      
            case MotionEvent.ACTION_MOVE:
              view.setY(event.getRawY() + dY);
              view.setX(event.getRawX() + dX);
              break;
      
            default:
              return false;
          }
          return true;
        }
      

      【讨论】:

      • 很棒的视频干得好
      • 但是我们为什么要添加增量不是视图应该移动到没有该空间的新指针位置。
      • 谢谢你,完美的回答!!
      【解决方案6】:

      实现此目的的最简单和简洁的方法之一是创建自定义视图并在该自定义视图中实现 onTouchListener。在下面的代码 sn-p 中,我们扩展了 AppCompatImageView。相反,我们可以使用任何类型的视图。

      class DraggableImageView(context: Context, attrs: AttributeSet) :
          AppCompatImageView(context, attrs) {
      
          private var draggableListener: DraggableListener? = null
          private var widgetInitialX: Float = 0F
          private var widgetDX: Float = 0F
          private var widgetInitialY: Float = 0F
          private var widgetDY: Float = 0F
      
          init {
              draggableSetup()
          }
      
          private fun draggableSetup() {
              this.setOnTouchListener { v, event ->
                  val viewParent = v.parent as View
                  val parentHeight = viewParent.height
                  val parentWidth = viewParent.width
                  val xMax = parentWidth - v.width
                  val xMiddle = parentWidth / 2
                  val yMax = parentHeight - v.height
      
                  when (event.actionMasked) {
                      MotionEvent.ACTION_DOWN -> {
                          widgetDX = v.x - event.rawX
                          widgetDY = v.y - event.rawY
                          widgetInitialX = v.x
                          widgetInitialY = v.y
                      }
                      MotionEvent.ACTION_MOVE -> {
                          var newX = event.rawX + widgetDX
                          newX = max(0F, newX)
                          newX = min(xMax.toFloat(), newX)
                          v.x = newX
      
                          var newY = event.rawY + widgetDY
                          newY = max(0F, newY)
                          newY = min(yMax.toFloat(), newY)
                          v.y = newY
      
                          draggableListener?.onPositionChanged(v)
                      }
                      MotionEvent.ACTION_UP -> {
                          if (event.rawX >= xMiddle) {
                              v.animate().x(xMax.toFloat())
                                  .setDuration(Draggable.DURATION_MILLIS)
                                  .setUpdateListener { draggableListener?.onPositionChanged(v) }
                                  .start()
                          } else {
                              v.animate().x(0F).setDuration(Draggable.DURATION_MILLIS)
                                  .setUpdateListener { draggableListener?.onPositionChanged(v) }
                                  .start()
                          }
                          if (abs(v.x - widgetInitialX) <= DRAG_TOLERANCE && abs(v.y - widgetInitialY) <= DRAG_TOLERANCE) {
                              performClick()
                          } else draggableListener?.xAxisChanged(event.rawX >= xMiddle)
                      }
                      else -> return@setOnTouchListener false
                  }
                  true
              }
          }
      
          override fun performClick(): Boolean {
              Log.d("DraggableImageView", "click")
              return super.performClick()
          }
      
          fun setListener(draggableListener: DraggableListener?) {
              this.draggableListener = draggableListener
          }
      }
      
      object Draggable {
          const val DRAG_TOLERANCE = 16
          const val DURATION_MILLIS = 250L
      }
      
      interface DraggableListener {
          fun onPositionChanged(view: View)
          fun xAxisChanged(isInRightSide: Boolean)
      }
      

      【讨论】:

      • 非常好的解决方案
      猜你喜欢
      • 2012-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多