我ViewPager
内有ScrollView
。我需要能够水平滚动以及垂直滚动。为了达到这个目的,只要触摸ViewPager
(v.getParent().requestDisallowInterceptTouchEvent(true);
),就必须禁用垂直滚动,以便可以水平滚动。
但与此同时,我需要能够点击viewPager以全屏模式打开它。
问题是onTouch在onClick之前被调用,我的OnClick永远不会被调用。
如何实现触摸onClick?
viewPager.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
System.out.println("TOUCHED ");
if(event.getAction() == MotionEvent.???){
//open fullscreen activity
}
v.getParent().requestDisallowInterceptTouchEvent(true); //This cannot be removed
return false;
}
});
viewPager.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("CLICKED ");
Intent fullPhotoIntent = new Intent(context, FullPhotoActivity.class);
fullPhotoIntent.putStringArrayListExtra("imageUrls", imageUrls);
startActivity(fullPhotoIntent);
}
});
答案 0 :(得分:57)
Masoud Dadashi的回答帮助我解决了问题。
这是它最终的样子。
viewPager.setOnTouchListener(new OnTouchListener() {
private int CLICK_ACTION_THRESHOLD = 200;
private float startX;
private float startY;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = event.getX();
startY = event.getY();
break;
case MotionEvent.ACTION_UP:
float endX = event.getX();
float endY = event.getY();
if (isAClick(startX, endX, startY, endY)) {
launchFullPhotoActivity(imageUrls);// WE HAVE A CLICK!!
}
break;
}
v.getParent().requestDisallowInterceptTouchEvent(true); //specific to my project
return false; //specific to my project
}
private boolean isAClick(float startX, float endX, float startY, float endY) {
float differenceX = Math.abs(startX - endX);
float differenceY = Math.abs(startY - endY);
return !(differenceX > CLICK_ACTION_THRESHOLD/* =5 */ || differenceY > CLICK_ACTION_THRESHOLD);
}
}
答案 1 :(得分:20)
我通过记录用户触摸屏幕的时间来做一些非常简单的事情。
julia> typeof(2 ^ 3 ^ 4)
Int64
另外值得注意的是GestureDetector内置了这个内容。请看onSingleTapUp
答案 2 :(得分:9)
发展两者是错误的想法。当用户通过触摸屏幕来做不同的事情时,了解用户的目的有点漂亮,你需要为它开发一段代码。
两种解决方案:
onTouch事件中的1-(更好的主意)检查是否有动作。您可以通过使用以下方法检查是否有任何移动来执行此操作:
ACTION_UP
ACTION_DOWN
ACTION_MOVE
这样做
if(event.getAction() != MotionEvent.ACTION_MOVE)
您甚至可以检查用户手指在屏幕上移动的距离,以确保发生移动而不是在点击时意外移动。这样做:
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
if(isDown == false)
{
startX = event.getX();
startY = event.getY();
isDown = true;
}
Break;
case MotionEvent.ACTION_UP
{
endX = event.getX();
endY = event.getY();
break;
}
}
如果上述情况均未发生,请将其视为点击,并执行您想要执行的操作。
2)如果使用您的UI进行设置,请创建按钮或图像按钮或任何其他内容进行全面筛选,并为其设置onClick。
祝你好运答案 3 :(得分:5)
您可能需要区分用户点击和长按。否则,你会发现两者都是同一个东西。我这样做是为了使这成为可能:
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = event.getX();
startY = event.getY();
bClick = true;
tmrClick = new Timer();
tmrClick.schedule(new TimerTask() {
public void run() {
if (bClick == true) {
bClick = false;
Log.d(LOG_TAG, "Hey, a long press event!");
//Handle the longpress event.
}
}
}, 500); //500ms is the standard longpress response time. Adjust as you see fit.
return true;
case MotionEvent.ACTION_UP:
endX = event.getX();
endY = event.getY();
diffX = Math.abs(startX - endX);
diffY = Math.abs(startY - endY);
if (diffX <= 5 && diffY <= 5 && bClick == true) {
Log.d(LOG_TAG, "A click event!");
bClick = false;
}
return true;
default:
return false;
}
}
答案 4 :(得分:4)
上面的答案主要是记住时间。但是,MotionEvent
已经覆盖了您。这是开销较小的解决方案。它用kotlin
编写,但仍然应该可以理解:
private const val ClickThreshold = 100
override fun onTouch(v: View, event: MotionEvent): Boolean {
if(event.action == MotionEvent.ACTION_UP
&& event.eventTime - event.downTime < ClickThreshold) {
v.performClick()
return true // If you don't want to do any more actions
}
// do something in case its not a click
return true // or false, whatever you need here
}
此解决方案对于大多数应用程序来说已经足够好,但是在区分单击和快速滑动之间却不是那么好。
因此,将其与上面的答案(也考虑到该职位)相结合,可能是最好的选择。
答案 5 :(得分:2)
我认为组合的解决方案时间/位置应该更好:
private float initialTouchX;
private float initialTouchY;
private long lastTouchDown;
private static int CLICK_ACTION_THRESHHOLD = 100;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lastTouchDown = System.currentTimeMillis();
//get the touch location
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
return true;
case MotionEvent.ACTION_UP:
int Xdiff = (int) (event.getRawX() - initialTouchX);
int Ydiff = (int) (event.getRawY() - initialTouchY);
if (System.currentTimeMillis() - lastTouchDown < CLICK_ACTION_THRESHHOLD && (Xdiff < 10 && Ydiff < 10)) {
//clicked!!!
}
return true;
}
return false;
}
});
答案 6 :(得分:2)
优雅的方式
class DetailedReportTable(tables.Table):
...
class Meta:
row_attrs = { "bg-color": lambda record: "#8B0000" if record['Warning'] else "#000000" }
答案 7 :(得分:0)
我相信您阻止视图以这种方式接收触摸事件,因为您的TouchListener会拦截它。 你可以
v.onTouchEvent(event)
ViewPager.onTouchEvent(MotionEvent)
而不是拦截事件此外,返回true
表示您没有使用该事件,并且您不会对以下事件感兴趣,因此在手势完成之前您不会收到以下事件(即手指又起来了。)
答案 8 :(得分:0)
您可以使用OnTouchClickListener
用法:
view.setOnTouchListener(new OnTouchClickListener(new OnTouchClickListener.OnClickListener() {
@Override
public void onClick(View v) {
//perform onClick
}
},5));
答案 9 :(得分:0)
if (event.eventTime - event.downTime < 100 && event.actionMasked == MotionEvent.ACTION_UP) {
view.performClick()
return false
}
答案 10 :(得分:0)
此代码将同时执行触摸事件和点击事件。
viewPager.setOnTouchListener(new View.OnTouchListener() {
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//remember the initial position.
initialX = params.x;
initialY = params.y;
//get the touch location
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
return true;
case MotionEvent.ACTION_UP:
int Xdiff = (int) (event.getRawX() - initialTouchX);
int Ydiff = (int) (event.getRawY() - initialTouchY);
//The check for Xdiff <10 && YDiff< 10 because sometime elements moves a little while clicking.
if (Xdiff < 10 && Ydiff < 10) {
//So that is click event.
}
return true;
case MotionEvent.ACTION_MOVE:
//Calculate the X and Y coordinates of the view.
params.x = initialX + (int) (event.getRawX() - initialTouchX);
params.y = initialY + (int) (event.getRawY() - initialTouchY);
//Update the layout with new X & Y coordinate
mWindowManager.updateViewLayout(mFloatingView, params);
return true;
}
return false;
}
});
这是source.
答案 11 :(得分:-1)
我认为你的问题来自这条线:
v.getParent().requestDisallowInterceptTouchEvent(true); //This cannot be removed
看看documentation。
你试过删除线路吗?没有删除这条线的理由是什么?
根据documentation,如果从onTouchListener返回true,则会消耗该事件,如果返回false,则传播该事件,因此您可以使用它来传播事件。 / p>
此外,您应该更改以下代码:
System.out.println("CLICKED ");
为:
Log.d("MyApp", "CLICKED ");
在logcat中获得正确的输出。