- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个带有图像提要(Instagram 样式)的应用程序。我正在尝试通过长按图像来显示快速图像预览。
主要思想是当用户长按时在对话框中显示图像,然后当用户向下/向上移动他的手指时修改缩放并在松开手指时关闭预览。
为了存档我在 fragment 的适配器中有一个 onLongClick,如下所示:
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
listener.onLongClick(item.getId());
return false;
}
});
然后, fragment 实现监听器并像这样调用对话框:
@Override
public void onLongClick(long itemId) {
FullscreenPhotoPreviewDialog dialog = FullscreenPhotoPreviewDialog.newInstance(itemId);
dialog.show(getActivity().getSupportFragmentManager(), "FullscreenPhotoPreviewDialog");
}
最后,Dialog 实现所有 OnTouch 逻辑,让用户在不松开手指的情况下进行缩放。
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch(motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
float scale = 0;
if (motionEvent.getHistorySize() > 0)
scale = ((motionEvent.getY() > motionEvent.getHistoricalY(motionEvent.getHistorySize() - 1)) ? 0.1f : -0.1f);
FullscreenPhotoPreviewDialog.this.applyScale(scale);
break;
case MotionEvent.ACTION_UP:
FullscreenPhotoPreviewDialog.this.dismiss();
break;
}
return true;
}
});
}
长按打开对话框的流程正常。onTouch 的问题。长按不会将 ACTION_DOWN 事件发送到 onTouch。所以我需要向上拉,然后再次向下拉以启动 onTouch。
有什么办法可以做到这一点?要通过长按自动调用 ACTION_DOWN?
谢谢,对不起我的英语!
最佳答案
使用 itemView onTouch 事件在第一次触摸后第一次释放之前检测手指运动。一旦释放,下一个 onTouch 事件被发送到对话框,如果用户触摸对话框,然后将调用对话框的 ACTION_DOWN。
当用户继续触摸时,触摸 Action 将被同一个 View 跟踪。进入或穿过另一个 View 区域无关紧要。
class SomeClass {
private int touchCount;
private ItemFunctions itemFunctions;
private FullscreenPhotoPreviewDialog dialog;
void someFunction(Holder holder) {
holder.itemView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// This block is called after first touch and before releasing his finger
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN: {
// First touch down event here.
// Second one depends on where user will touch again.
if (0 >= touchCount) {
itemFunctions = new ItemFunctions(item.getId());
}
touchCount++;
break;
}
case MotionEvent.ACTION_MOVE: {
// First touch move events here
float scale = 0;
...
if (itemFunctions.displayed) {
itemFunctions.applyScale(scale);
}
break;
}
case MotionEvent.ACTION_UP: {
// First up event here.
// Second one depends on where user will touch again.
break;
}
}
// This should be false to get long touch event
return false;
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
// dialog may need itemFunctions to manipulate zoom, dismiss state callback, etc.
dialog = FullscreenPhotoPreviewDialog.newInstance(itemFunctions.itemId);
dialog.show(getActivity().getSupportFragmentManager(), "FullscreenPhotoPreviewDialog");
itemFunctions.displayed = true;
return false;
}
});
}
}
class ItemFunctions {
long itemId;
boolean displayed;
ItemFunctions(long itemId) {
this.itemId = itemId;
}
void applyScale(float scale) {
}
}
补充说明
如果 UI 或触摸相关的功能需要很长时间,它可能会阻止其他事件。在这种情况下,Handler 很有用。
没有处理程序
void funcA() {
// funcB wiil be executed inside funcA.
funcB();
}
有处理程序
void funcA() {
// Send a request to call funcB after this point.
// Then looper will fetch the request from queue.
// And funcB will be called then.
// handler.post() -> sendMessageDelayed(getPostMessage(), ...)
// getPostMessage() -> Message m = Message.obtain(); ... return m;
handler.post(new Runnable() {
@Override
public void run() {
funcB();
}
});
}
void funcB() {
}
要理解为什么事件会被阻塞,我们应该知道输入事件是如何传递和处理的。
如果你熟悉Windows消息泵,请比较ViewRootHandler.handleMessage()与 Window Procedure和 Looper.loop()与 Message Loop .
Android 上的 Looper 和 Windows 上的消息泵具有相似的概念。他们传递排队的消息。触摸、点击等输入事件就是此类消息之一。因此,如果某些功能阻塞或需要很长时间来处理消息,则其他消息将等待下一个队列提取。
Android 上的Handlers 和Windows 程序上的window procedure 就是为了处理这样的消息。解码发送的内容并执行与之对应的任务。
Android 上的 ViewRootImpl.ViewRootHandler.handleMessage
public void handleMessage(Message msg) {
switch (msg.what) {
...
case MSG_PROCESS_INPUT_EVENTS:
mProcessInputEventsScheduled = false;
doProcessInputEvents();
break;
...
}
}
Windows 程序中的窗口过程
LRESULT CALLBACK MainWndProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam) // second message parameter
{
switch (uMsg)
{
...
case WM_MOUSEMOVE:
return 0;
...
}
}
Android 上的 Looper.loop
public static void loop() {
final Looper me = myLooper();
...
final MessageQueue queue = me.mQueue;
...
for (;;) {
Message msg = queue.next(); // might block
...
try {
msg.target.dispatchMessage(msg);
...
} finally {
...
}
}
}
Windows 程序中的消息循环
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
引用。
What is a message pump? ( window )
关于android - 从 fragment 中的 onLongClick 触发对话框中的 onTouch,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54370632/
我在 ScrollView 中使用 ImageView Controller 。在实现和测试方面,我发现滚动总是覆盖 onTouch 事件而不是 imageView (dragImage)。 我尝试使
运行代码时没有收到任何错误,但触摸屏幕时没有任何反应。全局变量 select 的值应该改变,但没有任何反应。 这是代码 public class NonmultiplierSixGame extend
我发现当我停止在屏幕上移动手指时,Android onTouch 事件不会被触发,因此我无法正确获取游戏中每个刻度的指针计数。 @Override public boolean onTouch(Vie
这个问题已经有答案了: Android beginner: understanding MotionEvent actions (2 个回答) 已关闭 9 年前。 好吧,我正在制作一个简单的秒表,当您
我正在开发一款在屏幕上运行不同位图的游戏(SurfaceView)。由于它们具有不同的速度,有时会发生两个字符叠加的情况,一个在另一个后面。我使用 OnTouch 功能来捕捉玩家触摸角色的瞬间。但是,
我正在使用 onTouch(View arg0, MotionEvent arg1)作为游戏输入。它返回 false 所以它没有被处理。在我运行 4.0.4 的 HTC HD2 上,这足以让播放器足够
我试图在我的 LoadPreview().execute 启动时禁用 onTouch(),因为如果用户点击触发我的 LoadPreview() 的按钮,将会出现重复的预览按钮。所以我想在加载过程中禁用
好的,我正在玩扩展 View 的 ontouch 事件。 我所做的是在触摸时形成一个圆圈。当你移动时,圆圈会随之而来。当你移动另一个圆圈时,它会位于递减半径的位置,直到它消失……(现在最多有 10 个
这是我的布局文件 这是我的自定义 View import android.view.MotionEvent; import android.view.View; import
在我的应用程序中,我想计算两个距离之间的比率,但我不知道为什么变量 dist1 和 dist2 没有保存我在 IF ELSE 语句中计算的值,我的代码有什么问题? 任何指导或帮助将不胜感激。 这是方法
我已将 RelativeLayout 设为可点击,但我希望整个布局在用户触摸时变为橙色。我该怎么做? 最佳答案 您可以使用描述的方法here . 关于android - 如何使用橙色制作相对布局渲
我需要在触摸屏幕时播放文件。 我尝试了以下方法,但没有成功: -(IBAction)play; { CFBundleRef mainBundle = CFBundleGetMainBundle
我在 onCreate 方法中有这段代码: ImageView iv01 = (ImageView)findViewById(R.id.hexagon01); iv01.
我正在尝试用我的观点做 3 件事。第一次“点击”我的屏幕时,我想将 View 顶部的 ImageView 完全设置为 0alpha 以显示下方 View 。当屏幕水龙头被抬起时,我希望 alpha 回
我使用 onTouchListener 在用户手指按下时更改背景颜色,并在用户手指抬起时更改回默认颜色。问题在于,当用户的手指向下时,背景颜色会发生变化,但如果用户没有抬起手指并开始滚动,背景颜色不会
我正在使用 ontouch 事件,但我遇到的问题是它调用了 down 事件,但它没有调用 move 事件或 UP 事件检查以下代码 public class DragNewActivity exten
您好,我正在 http://www.rbgrn.net/content/354-glsurfaceview-adapted-3d-live-wallpapers 的帮助下制作动态壁纸.现在我想在主屏幕
我正在玩 UI 事件处理,我发现了一些我无法从 Android Dev 中找到解释的东西:我有一个 ImageView 和一个 TextView,每当我触摸 ImageView 时,TextView
我有这样的布局: LinearLayout RelativeLayout(id = test) FrameLayout (From a LIB. id = lib) 我尝试将
如果设备上有多根手指,onTouch 监听器是针对每个手指运行一次,还是针对每个事件(手指按下、移动等)运行一次并包括每个 Activity 的触摸指针? 如果 (e.getAction() & Mo
我是一名优秀的程序员,十分优秀!