~thestr4ng3r/chiaki

b69bf280f8656df483c7f2680d52168f5cdc8c7b — Florian Märkl 2 days ago c1a4504
Extend Face Button Touch Areas on Android
M android/app/src/main/java/com/metallic/chiaki/touchcontrols/ButtonView.kt => android/app/src/main/java/com/metallic/chiaki/touchcontrols/ButtonView.kt +25 -2
@@ 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

M android/app/src/main/java/com/metallic/chiaki/touchcontrols/Vector.kt => android/app/src/main/java/com/metallic/chiaki/touchcontrols/Vector.kt +7 -0
@@ 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())
}
\ No newline at end of file

M android/app/src/main/res/layout/fragment_controls.xml => android/app/src/main/res/layout/fragment_controls.xml +30 -26
@@ 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"

M android/app/src/main/res/values/dimens.xml => android/app/src/main/res/values/dimens.xml +5 -1
@@ 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>