gpt4 book ai didi

android - 从 fragment 中的 onLongClick 触发对话框中的 onTouch

转载 作者:太空狗 更新时间:2023-10-29 14:36:33 24 4
gpt4 key购买 nike

我有一个带有图像提要(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 ProcedureLooper.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 )

What is the purpose of Looper and how to use it? (安卓)

关于android - 从 fragment 中的 onLongClick 触发对话框中的 onTouch,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54370632/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com