Extend Face Button Touch Areas on Android

This commit is contained in:
Florian Märkl 2021-01-13 19:33:54 +01:00
commit b69bf280f8
No known key found for this signature in database
GPG key ID: 125BC8A5A6A1E857
4 changed files with 67 additions and 29 deletions

View file

@ -8,6 +8,8 @@ import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import androidx.core.view.children
import com.metallic.chiaki.R
class ButtonView @JvmOverloads constructor(
@ -46,15 +48,36 @@ class ButtonView @JvmOverloads constructor(
{
super.onDraw(canvas)
val drawable = if(buttonPressed) drawablePressed else drawableIdle
drawable?.setBounds(0, 0, width, height)
drawable?.setBounds(paddingLeft, paddingTop, width - paddingRight, height - paddingBottom)
drawable?.draw(canvas)
}
/**
* If this button overlaps with others in the same layout,
* let the one whose center is closest to the touch handle it.
*/
private fun bestFittingTouchView(x: Float, y: Float): View
{
val loc = locationOnScreen + Vector(x, y)
return (parent as? ViewGroup)?.children?.filter {
it is ButtonView
}?.filter {
val pos = it.locationOnScreen
loc.x >= pos.x && loc.x < pos.x + it.width && loc.y >= pos.y && loc.y < pos.y + it.height
}?.sortedBy {
(loc - (it.locationOnScreen + Vector(it.width.toFloat(), it.height.toFloat()) * 0.5f)).lengthSq
}?.firstOrNull() ?: this
}
override fun onTouchEvent(event: MotionEvent): Boolean
{
when(event.action)
{
MotionEvent.ACTION_DOWN -> buttonPressed = true
MotionEvent.ACTION_DOWN -> {
if(bestFittingTouchView(event.x, event.y) != this)
return false
buttonPressed = true
}
MotionEvent.ACTION_UP -> buttonPressed = false
}
return true

View file

@ -2,6 +2,7 @@
package com.metallic.chiaki.touchcontrols
import android.view.View
import kotlin.math.sqrt
data class Vector(val x: Float, val y: Float)
@ -18,4 +19,10 @@ data class Vector(val x: Float, val y: Float)
val lengthSq get() = x*x + y*y
val length get() = sqrt(lengthSq)
val normalized get() = this / length
}
val View.locationOnScreen: Vector get() {
val v = intArrayOf(0, 0)
this.getLocationOnScreen(v)
return Vector(v[0].toFloat(), v[1].toFloat())
}

View file

@ -1,10 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:clipChildren="false">
android:clipChildren="false"
tools:ignore="RtlHardcoded,RtlSymmetry">
<com.metallic.chiaki.touchcontrols.ControlsBackgroundView
android:layout_width="match_parent"
@ -57,8 +59,8 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/faceButtonsLayout"
android:layout_width="144dp"
android:layout_height="144dp"
android:layout_width="@dimen/control_face_button_size_full"
android:layout_height="@dimen/control_face_button_size_full"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
@ -67,9 +69,12 @@
<com.metallic.chiaki.touchcontrols.ButtonView
android:id="@+id/crossButtonView"
android:layout_width="@dimen/control_face_button_size"
android:layout_height="@dimen/control_face_button_size"
android:padding="8dp"
android:layout_width="@dimen/control_face_button_size_full"
android:layout_height="@dimen/control_face_button_size_half"
android:paddingLeft="@dimen/control_face_button_padding_to_full"
android:paddingRight="@dimen/control_face_button_padding_to_full"
android:paddingTop="@dimen/control_face_button_padding_to_center"
android:paddingBottom="@dimen/control_face_button_padding_to_outside"
app:drawableIdle="@drawable/control_button_cross"
app:drawablePressed="@drawable/control_button_cross_pressed"
app:layout_constraintLeft_toLeftOf="parent"
@ -78,9 +83,12 @@
<com.metallic.chiaki.touchcontrols.ButtonView
android:id="@+id/moonButtonView"
android:layout_width="@dimen/control_face_button_size"
android:layout_height="@dimen/control_face_button_size"
android:padding="8dp"
android:layout_width="@dimen/control_face_button_size_half"
android:layout_height="@dimen/control_face_button_size_full"
android:paddingTop="@dimen/control_face_button_padding_to_full"
android:paddingBottom="@dimen/control_face_button_padding_to_full"
android:paddingLeft="@dimen/control_face_button_padding_to_center"
android:paddingRight="@dimen/control_face_button_padding_to_outside"
app:drawableIdle="@drawable/control_button_moon"
app:drawablePressed="@drawable/control_button_moon_pressed"
app:layout_constraintRight_toRightOf="parent"
@ -89,9 +97,12 @@
<com.metallic.chiaki.touchcontrols.ButtonView
android:id="@+id/pyramidButtonView"
android:layout_width="@dimen/control_face_button_size"
android:layout_height="@dimen/control_face_button_size"
android:padding="8dp"
android:layout_width="@dimen/control_face_button_size_full"
android:layout_height="@dimen/control_face_button_size_half"
android:paddingLeft="@dimen/control_face_button_padding_to_full"
android:paddingRight="@dimen/control_face_button_padding_to_full"
android:paddingBottom="@dimen/control_face_button_padding_to_center"
android:paddingTop="@dimen/control_face_button_padding_to_outside"
app:drawableIdle="@drawable/control_button_pyramid"
app:drawablePressed="@drawable/control_button_pyramid_pressed"
app:layout_constraintLeft_toLeftOf="parent"
@ -100,14 +111,17 @@
<com.metallic.chiaki.touchcontrols.ButtonView
android:id="@+id/boxButtonView"
android:layout_width="@dimen/control_face_button_size"
android:layout_height="@dimen/control_face_button_size"
android:padding="8dp"
android:layout_width="@dimen/control_face_button_size_half"
android:layout_height="@dimen/control_face_button_size_full"
android:paddingTop="@dimen/control_face_button_padding_to_full"
android:paddingBottom="@dimen/control_face_button_padding_to_full"
android:paddingRight="@dimen/control_face_button_padding_to_center"
android:paddingLeft="@dimen/control_face_button_padding_to_outside"
app:drawableIdle="@drawable/control_button_box"
app:drawablePressed="@drawable/control_button_box_pressed"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
@ -116,7 +130,6 @@
android:id="@+id/l3ButtonView"
android:layout_width="64dp"
android:layout_height="64dp"
android:padding="8dp"
app:drawableIdle="@drawable/control_button_l3"
app:drawablePressed="@drawable/control_button_l3_pressed"
app:layout_constraintLeft_toLeftOf="parent"
@ -126,7 +139,6 @@
android:id="@+id/r3ButtonView"
android:layout_width="64dp"
android:layout_height="64dp"
android:padding="8dp"
app:drawableIdle="@drawable/control_button_r3"
app:drawablePressed="@drawable/control_button_r3_pressed"
app:layout_constraintRight_toRightOf="parent"
@ -137,7 +149,6 @@
android:id="@+id/psButtonView"
android:layout_width="32dp"
android:layout_height="32dp"
android:padding="8dp"
android:layout_marginBottom="8dp"
app:drawableIdle="@drawable/control_button_home"
app:drawablePressed="@drawable/control_button_home_pressed"
@ -150,7 +161,6 @@
android:id="@+id/touchpadButtonView"
android:layout_width="32dp"
android:layout_height="32dp"
android:padding="8dp"
android:layout_marginTop="8dp"
app:drawableIdle="@drawable/control_button_touchpad"
app:drawablePressed="@drawable/control_button_touchpad_pressed"
@ -162,7 +172,6 @@
android:id="@+id/l2ButtonView"
android:layout_width="64dp"
android:layout_height="32dp"
android:padding="8dp"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
app:drawableIdle="@drawable/control_button_l2"
@ -174,7 +183,6 @@
android:id="@+id/l1ButtonView"
android:layout_width="64dp"
android:layout_height="32dp"
android:padding="8dp"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
app:drawableIdle="@drawable/control_button_l1"
@ -186,7 +194,6 @@
android:id="@+id/shareButtonView"
android:layout_width="32dp"
android:layout_height="32dp"
android:padding="8dp"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
app:drawableIdle="@drawable/control_button_share"
@ -198,7 +205,6 @@
android:id="@+id/r2ButtonView"
android:layout_width="64dp"
android:layout_height="32dp"
android:padding="8dp"
android:layout_marginTop="8dp"
android:layout_marginRight="8dp"
app:drawableIdle="@drawable/control_button_r2"
@ -210,7 +216,6 @@
android:id="@+id/r1ButtonView"
android:layout_width="64dp"
android:layout_height="32dp"
android:padding="8dp"
android:layout_marginTop="8dp"
android:layout_marginRight="8dp"
app:drawableIdle="@drawable/control_button_r1"
@ -222,7 +227,6 @@
android:id="@+id/optionsButtonView"
android:layout_width="32dp"
android:layout_height="32dp"
android:padding="8dp"
android:layout_marginTop="8dp"
android:layout_marginRight="8dp"
app:drawableIdle="@drawable/control_button_options"

View file

@ -1,6 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="control_face_button_size">48dp</dimen>
<dimen name="control_face_button_size_half">88dp</dimen>
<dimen name="control_face_button_size_full">176dp</dimen>
<dimen name="control_face_button_padding_to_center">24dp</dimen>
<dimen name="control_face_button_padding_to_outside">16dp</dimen>
<dimen name="control_face_button_padding_to_full">64dp</dimen>
<dimen name="control_analog_stick_radius">48dp</dimen>
<dimen name="control_analog_stick_handle_radius">32dp</dimen>
<dimen name="floating_action_button_speed_dial_anim_offset">48dp</dimen>