From 6c0c3557e5675b124cd7fff7088095bb06a0c9ce Mon Sep 17 00:00:00 2001 From: tateisu Date: Sat, 16 Jul 2022 02:07:32 +0900 Subject: [PATCH] =?UTF-8?q?=E7=B5=B5=E6=96=87=E5=AD=97=E3=83=94=E3=83=83?= =?UTF-8?q?=E3=82=AB=E3=83=BC=E3=81=AE=E5=B7=A6=E5=8F=B3=E3=83=95=E3=83=AA?= =?UTF-8?q?=E3=83=83=E3=82=AF=E3=81=8C=E6=9A=B4=E7=99=BA=E3=81=97=E3=81=8C?= =?UTF-8?q?=E3=81=A1=E3=81=AA=E3=81=AE=E3=82=92=E7=9B=B4=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subwaytooter/dialog/EmojiPicker.kt | 186 ++++++++++-------- .../main/res/layout/emoji_picker_dialog.xml | 17 +- 2 files changed, 115 insertions(+), 88 deletions(-) diff --git a/app/src/main/java/jp/juggler/subwaytooter/dialog/EmojiPicker.kt b/app/src/main/java/jp/juggler/subwaytooter/dialog/EmojiPicker.kt index 104a348a..a086aa00 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/dialog/EmojiPicker.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/dialog/EmojiPicker.kt @@ -222,6 +222,7 @@ private class EmojiPicker( ) : ViewHolderBase(view) { init { + view.setButtonBackground() view.setOnClickListener(pickerItemClickListener) view.layoutParams = RecyclerView.LayoutParams(matchParent, gridSize) } @@ -245,6 +246,7 @@ private class EmojiPicker( val view: AppCompatImageView = AppCompatImageView(activity), ) : ViewHolderBase(view) { init { + view.setButtonBackground() view.setOnClickListener(pickerItemClickListener) view.layoutParams = RecyclerView.LayoutParams(matchParent, gridSize) view.scaleType = ImageView.ScaleType.FIT_CENTER @@ -273,6 +275,7 @@ private class EmojiPicker( val view: AppCompatTextView = AppCompatTextView(activity), ) : ViewHolderBase(view) { init { + view.setButtonBackground() view.setOnClickListener(pickerItemClickListener) view.layoutParams = RecyclerView.LayoutParams(matchParent, gridSize) view.gravity = Gravity.CENTER @@ -355,6 +358,12 @@ private class EmojiPicker( } } + private enum class FlickStatus { + None, + Start, + Intercepted, + } + private lateinit var pickerCategries: List private val adapter = GridAdapter() @@ -398,10 +407,10 @@ private class EmojiPicker( private var recentCategory: PickerItemCategoryRecent? = null private val density = activity.resources.displayMetrics.density - private val cancelY = density * 16f - private val interceptX = density * 8f + private val cancelY = 16f + private val interceptX = 40f private var tracker: VelocityTracker? = null - private var dragging = false + private var dragging = FlickStatus.None private var startX = 0f private var startY = 0f @@ -413,11 +422,11 @@ private class EmojiPicker( } } - private val pickerItemClickListener = View.OnClickListener { + private val pickerItemClickListener = View.OnClickListener { v -> val targetEmoji: EmojiBase val targetName: String val targetInstance: String? - when (val item = it.getTag(R.id.btnAbout)) { + when (val item = v.getTag(R.id.btnAbout)) { is PickerItemUnicode -> { targetEmoji = applySkinTone(item.unicodeEmoji) targetName = targetEmoji.unifiedName @@ -431,11 +440,17 @@ private class EmojiPicker( else -> return@OnClickListener } - if (closeOnSelected) dialog.dismissSafe() - recentCategory?.update(targetName, targetInstance) - @Suppress("NotifyDataSetChanged") - showFiltered(lastSelectedCategory, lastSelectedKeyword) + + if (closeOnSelected) { + dialog.dismissSafe() + } else if (lastSelectedCategory == null || lastSelectedCategory == EmojiCategory.Recent) { + // 全カテゴリ表示や最近の表示は最近の絵文字の順序を変えるため更新してしまう + showFiltered(lastSelectedCategory, lastSelectedKeyword) + // XXX: タップ状態の表示が行えない… + } else { + // この場合はビューの更新は不要で、タップ状態の表示を行える + } onPicked(targetEmoji, bInstanceHasCustomEmoji) } @@ -628,83 +643,94 @@ private class EmojiPicker( showFiltered(newCategory, null) } - fun handleTouch(ev: MotionEvent, wasIntercept: Boolean) = when (ev.actionMasked) { - MotionEvent.ACTION_CANCEL -> { - log.i("ACTION_CANCEL wasIntercept=$wasIntercept") - dragging = false - wasIntercept - } - MotionEvent.ACTION_UP -> { - log.i("ACTION_UP wasIntercept=$wasIntercept") - try { - if (dragging) { - tracker?.let { - it.addMovement(ev) - it.computeCurrentVelocity(1000) - val vx = it.xVelocity - val vy = it.yVelocity - val vxDp = vx / density - val aspect = abs(vx) / abs(vy) - log.i("vx=$vx vy=$vy") - if (aspect < 2f) { - log.i("not gesture: aspect=$aspect") - } else if (abs(vxDp) < 40f) { - log.i("not gesture: vxDp=$vxDp") - } else { - movePage((vxDp.sign * -1f).toInt()) + private fun View.setButtonBackground() { + background = ContextCompat.getDrawable(context, R.drawable.btn_bg_transparent_round6dp) + } + + private fun handleTouch(ev: MotionEvent, wasIntercept: Boolean) = + try { + when (ev.actionMasked) { + MotionEvent.ACTION_CANCEL -> { + log.i("ACTION_CANCEL wasIntercept=$wasIntercept") + dragging = FlickStatus.None + wasIntercept + } + MotionEvent.ACTION_UP -> { + try { + log.i("ACTION_UP wasIntercept=$wasIntercept") + if (dragging == FlickStatus.Intercepted) { + tracker?.let { + it.addMovement(ev) + it.computeCurrentVelocity(1000) + val vx = it.xVelocity + val vy = it.yVelocity + val vxDp = vx / density + val aspect = abs(vx) / abs(vy) + log.i("vx=$vx vy=$vy") + if (aspect < 2f) { + log.i("not gesture: aspect=$aspect") + } else if (abs(vxDp) < 40f) { + log.i("not gesture: vxDp=$vxDp") + } else { + movePage((vxDp.sign * -1f).toInt()) + } + } + } + } finally { + dragging = FlickStatus.None + } + wasIntercept + } + MotionEvent.ACTION_DOWN -> { + log.i("ACTION_DOWN wasIntercept=$wasIntercept") + // ドラッグ開始 + dragging = FlickStatus.Start + if (tracker == null) { + tracker = VelocityTracker.obtain() + } + tracker?.clear() + startX = ev.x + startY = ev.y + wasIntercept + } + MotionEvent.ACTION_MOVE -> { + if (dragging == FlickStatus.None) { + wasIntercept + } else { + // 移動量追跡 + tracker?.addMovement(ev) + val deltaX = abs(ev.x - startX) / density + val deltaY = abs(ev.y - startY) / density + when { + // すでにインターセプトしている + wasIntercept -> true + + // 上下方向に大きく動かしたらそれ以上追跡しない + deltaY >= cancelY -> { + log.i("not flick! $deltaY") + dragging = FlickStatus.None + false + } + + // 横方向に大きく動かしたらインターセプトする + deltaX >= interceptX && deltaX > deltaY -> { + log.i("intercept! $deltaX") + dragging = FlickStatus.Intercepted + true + } + else -> { + log.d("not yet intercept. $deltaX, $deltaY") + false + } } } } - } catch (ex: Throwable) { - log.e(ex) + else -> log.w("handleTouch else $ev") } - dragging = false + } catch (ex: Throwable) { + log.w("handleTouch failed. ev=$ev, wasIntercept=$wasIntercept") wasIntercept } - MotionEvent.ACTION_DOWN -> { - log.i("ACTION_DOWN wasIntercept=$wasIntercept") - // ドラッグ開始 - if (!dragging) { - dragging = true - if (tracker == null) { - tracker = VelocityTracker.obtain() - } - tracker?.clear() - startX = ev.x - startY = ev.y - } - wasIntercept - } - MotionEvent.ACTION_MOVE -> { - if (!dragging) { - wasIntercept - } else { - // 移動量追跡 - tracker?.addMovement(ev) - val deltaX = ev.x - startX - val deltaY = ev.y - startY - when { - // すでにインターセプトしている - wasIntercept -> true - // 上下方向に大きく動かしたらそれ以上追跡しない - abs(deltaY) > cancelY -> { - log.i("not intercept!") - dragging = false - false - } - // 横方向に大きく動かしたらインターセプトする - abs(deltaX) > interceptX -> { - log.i("intercept!") - true - } - else -> false - } - } - } - else -> { - log.w("handleTouch $ev") - } - } suspend fun start() { pickerCategries = buildCategoryList() diff --git a/app/src/main/res/layout/emoji_picker_dialog.xml b/app/src/main/res/layout/emoji_picker_dialog.xml index 3ce28fa8..7790d7ef 100644 --- a/app/src/main/res/layout/emoji_picker_dialog.xml +++ b/app/src/main/res/layout/emoji_picker_dialog.xml @@ -54,7 +54,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="6dp" - android:layout_marginBottom="0dp" + android:layout_marginBottom="2dp" android:hint="@string/search_emojis" android:importantForAccessibility="no" android:importantForAutofill="no" @@ -64,20 +64,22 @@ android:id="@+id/svCategories" android:layout_width="match_parent" android:layout_height="wrap_content" + android:cacheColorHint="#00000000" android:clipToPadding="false" - android:padding="6dp" - android:paddingBottom="0dp" - android:scrollbars="none" + android:fadeScrollbars="false" android:fadingEdge="horizontal" android:fadingEdgeLength="32dp" - android:cacheColorHint="#00000000" - > + android:requiresFadingEdge="horizontal" + android:scrollbars="horizontal"> + android:orientation="horizontal" + android:paddingBottom="4dp" + android:paddingEnd="6dp" + android:paddingStart="6dp" />