草庐IT

android - 拖放 + Fling 检测器不起作用

coder 2023-12-06 原文

我正在尝试实现一个可拖动的按钮,该按钮也应该是可滑动的。

不幸的是,系统在拖动开始后停止发送 MotionEvents。因此,永远不会调用 GestureDetector.OnGestureListener.onFling() 方法。

有没有办法在拖动系统消耗这些事件之前拦截它们?

我也尝试创建自己的 FlingDetector,但它在不同的设备和屏幕密度上并不可靠:

public class FlingDetector {

private final int MIN_FLING_SPEED = 3;

private OnFlingListener mOnFlingListener;

private float mCurrentX = 0;
private float mCurrentY = 0;
private long mLastMovementTime = 0;
private double  mCurrentVelocity = 0;

private final float mDensity;

public FlingDetector(OnFlingListener onFlingListener, Context context) {
    mOnFlingListener = onFlingListener;
    mDensity = context.getResources().getDisplayMetrics().density;
}


public void onMovementStart(float x, float y) {
    mCurrentX = x;
    mCurrentY = y;
    mLastMovementTime = System.currentTimeMillis();
    mCurrentVelocity = 0;
}

public void onMovementEnd(float x, float y) {

    long currentTime = System.currentTimeMillis();

    float distanceX = Math.abs(mCurrentX - x) / mDensity;
    float distanceY = Math.abs(mCurrentY - y) / mDensity;

    float distance = (float) Math.sqrt(Math.pow(distanceX, 2) +
            Math.pow(distanceY, 2));

    mCurrentVelocity = (distance / (currentTime - mLastMovementTime));

    if(mCurrentVelocity > MIN_FLING_SPEED) {
        mOnFlingListener.onFling((int) (mCurrentVelocity + 0.5));
    } else {
        Log.d("test", "Distance: " + distance);
        Log.d("test", "Time Delta: " + (currentTime - mLastMovementTime));
        Log.d("test", "Speed: " + mCurrentVelocity);
    }
}

public interface OnFlingListener {
    void onFling(int speed);
}

}

最佳答案

您可以使用 GestureDetector 通过按钮实现滑动和拖动。 GestureDetector 有点直截了当,它有自己的默认方法来处理以下运动事件。

  1. 长按
  2. 放纵
  3. onDown
  4. onShowPress
  5. onSingleTapUp
  6. 滚动

你可以这样实现。

public class MainActivity extends AppCompatActivity {

    Button button;
    GestureDetector buttonGestureDetector;
    static final int SWIPE_MIN_DISTANCE = 60;
     static final int SWIPE_THRESHOLD_VELOCITY = 100;




    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button=(Button) findViewById(R.id.button);

        buttonGestureDetector=new GestureDetector(this,new GestureDetector.OnGestureListener() {
          @Override
          public boolean onDown(MotionEvent e) {
              return false;
          }

          @Override
          public void onShowPress(MotionEvent e) {

          }

          @Override
          public boolean onSingleTapUp(MotionEvent e) {
              return false;
          }

          @Override
          public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
              return false;
          }

          @Override
          public void onLongPress(MotionEvent e) {
              Log.i("Drag","DragListening");
              View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(button);
              button.startDrag(null, shadowBuilder, button, 0);
              button.setVisibility(View.INVISIBLE);



          }

          @Override
          public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {

              Log.i("FlingListened","FlingListened");

              if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                  Toast.makeText(MainActivity.this,"OnRightToLeft Fling",Toast.LENGTH_SHORT).show();
              }
              else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY)
              {
                  Toast.makeText(MainActivity.this,"OnLeftToRight Fling",Toast.LENGTH_SHORT).show();
              }
              if (e1.getY() - e2.getY() > SWIPE_MIN_DISTANCE && Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY) {

                  Toast.makeText(MainActivity.this,"onBottomToTop Fling",Toast.LENGTH_SHORT).show();

              }
              else if (e2.getY() - e1.getY() > SWIPE_MIN_DISTANCE && Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY) {
                  Toast.makeText(MainActivity.this,"OnTopToBottom Fling",Toast.LENGTH_SHORT).show();

              }
              return true;


            }
      });

        button.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                buttonGestureDetector.onTouchEvent(event);
                return false;


            }
        });

          button.setOnDragListener(new View.OnDragListener() {
            @Override
            public boolean onDrag(View dragView, DragEvent event)
            {

                int action = event.getAction();
                switch (action) {
                    case DragEvent.ACTION_DRAG_STARTED:
                        Log.d("Drag", "Drag event started");
                        break;
                    case DragEvent.ACTION_DRAG_ENTERED:
                        Log.d("Drag", "Drag event entered into "+dragView.toString());
                        break;
                    case DragEvent.ACTION_DRAG_EXITED:
                        Log.d("Drag", "Drag event exited from "+dragView.toString());
                        break;
                    case DragEvent.ACTION_DROP:
                        Log.d("Drag", "Dropped");
                        View view = (View) event.getLocalState();
                        ViewGroup owner = (ViewGroup) view.getParent();
                        owner.removeView(view);
                        LinearLayout container = (LinearLayout) dragView;
                        container.addView(view);
                        view.setVisibility(View.VISIBLE);
                        break;
                    case DragEvent.ACTION_DRAG_ENDED:
                        Log.d("Drag", "Drag ended");
                        break;
                    default:
                        break;
                }
                return true;
            }


        });

    }
}

关于android - 拖放 + Fling 检测器不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34434241/

有关android - 拖放 + Fling 检测器不起作用的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  3. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  4. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  5. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  6. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  7. ruby-on-rails - "assigns"在 Ruby on Rails 中有什么作用? - 2

    我目前正在尝试学习RubyonRails和测试框架RSpec。assigns在此RSpec测试中做什么?describe"GETindex"doit"assignsallmymodelas@mymodel"domymodel=Factory(:mymodel)get:indexassigns(:mymodels).shouldeq([mymodel])endend 最佳答案 assigns只是检查您在Controller中设置的实例变量的值。这里检查@mymodels。 关于ruby-o

  8. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  9. += 的 Ruby 方法 - 2

    有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=

  10. ruby - 检测由 RSpec、Ruby 运行的代码 - 2

    我想知道我的代码是否在rspec下运行。这可能吗?原因是我正在加载一些错误记录器,这些记录器在测试期间会被故意错误(expect{x}.toraise_error)弄得乱七八糟。我查看了我的ENV变量,没有(明显的)测试环境变量的迹象。 最佳答案 在spec_helper.rb的开头添加:ENV['RACK_ENV']='test'现在您可以在代码中检查RACK_ENV是否经过测试。 关于ruby-检测由RSpec、Ruby运行的代码,我们在StackOverflow上找到一个类似的问题

随机推荐