Используйте событие itemView onTouch, чтобы обнаружить движения пальцев перед первым выпуском после первого прикосновения.После освобождения следующее событие onTouch отправляется в диалоговое окно, если пользователь прикасается к диалоговому окну, и затем вызывается ACTION_DOWN для диалогового окна.
Движение касания будет отслеживаться тем же видом, пока пользователь продолжает касаться.Ввод или пересечение другой области просмотра не имеет значения.
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) {
}
}
Дополнительные примечания
Если функция, связанная с пользовательским интерфейсом или касанием, занимает много времени, она может блокировать другие события.В таких случаях полезен 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 () с Оконная процедура и Looper.loop () с Message Loop .
Looper на Android и насос сообщений на Windows имеют схожие концепции.Они доставляют сообщения в очереди.События ввода, такие как касание, щелчок и т. Д., Являются одним из таких сообщений.Таким образом, если некоторые функциональные блоки или обработка сообщения занимает много времени, другие сообщения остаются в ожидании получения следующей очереди.
Обработчики на Android и оконная процедура в программах Windows предназначены для обработки таких сообщений.Декодируйте то, что отправлено, и выполняйте задачи, соответствующие ему.
ViewRootImpl.ViewRootHandler.handleMessage на Android
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;
...
}
}
Looper.цикл на Android
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);
}
}
Ссылки.
Что такое насос сообщений? (Windows)
Какова цель Looper и как его использовать? (Android)