Improve accessibility of SMS code keyboard.
This commit is contained in:
parent
c2b5407911
commit
8be7fa8655
7 changed files with 256 additions and 56 deletions
|
@ -0,0 +1,75 @@
|
|||
package org.thoughtcrime.securesms.components
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import org.thoughtcrime.securesms.R
|
||||
|
||||
/**
|
||||
* A "forced" EN US Numeric keyboard designed solely for SMS code entry. This
|
||||
* "upgrade" over KeyboardView will ensure that the keyboard is navigable via
|
||||
* TalkBack and will read out keys as they are selected by the user. This is
|
||||
* not a perfect solution, but save being able to force the system keyboard to
|
||||
* appear in EN US, this is the best we can do for the time being.
|
||||
*/
|
||||
class NumericKeyboardView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null
|
||||
) : ConstraintLayout(context, attrs) {
|
||||
|
||||
var listener: Listener? = null
|
||||
|
||||
init {
|
||||
inflate(context, R.layout.numeric_keyboard_view, this)
|
||||
|
||||
findViewById<TextView>(R.id.numeric_keyboard_1).setOnClickListener {
|
||||
listener?.onKeyPress(1)
|
||||
}
|
||||
|
||||
findViewById<TextView>(R.id.numeric_keyboard_2).setOnClickListener {
|
||||
listener?.onKeyPress(2)
|
||||
}
|
||||
|
||||
findViewById<TextView>(R.id.numeric_keyboard_3).setOnClickListener {
|
||||
listener?.onKeyPress(3)
|
||||
}
|
||||
|
||||
findViewById<TextView>(R.id.numeric_keyboard_4).setOnClickListener {
|
||||
listener?.onKeyPress(4)
|
||||
}
|
||||
|
||||
findViewById<TextView>(R.id.numeric_keyboard_5).setOnClickListener {
|
||||
listener?.onKeyPress(5)
|
||||
}
|
||||
|
||||
findViewById<TextView>(R.id.numeric_keyboard_6).setOnClickListener {
|
||||
listener?.onKeyPress(6)
|
||||
}
|
||||
|
||||
findViewById<TextView>(R.id.numeric_keyboard_7).setOnClickListener {
|
||||
listener?.onKeyPress(7)
|
||||
}
|
||||
|
||||
findViewById<TextView>(R.id.numeric_keyboard_8).setOnClickListener {
|
||||
listener?.onKeyPress(8)
|
||||
}
|
||||
|
||||
findViewById<TextView>(R.id.numeric_keyboard_9).setOnClickListener {
|
||||
listener?.onKeyPress(9)
|
||||
}
|
||||
|
||||
findViewById<TextView>(R.id.numeric_keyboard_0).setOnClickListener {
|
||||
listener?.onKeyPress(0)
|
||||
}
|
||||
|
||||
findViewById<ImageView>(R.id.numeric_keyboard_back).setOnClickListener {
|
||||
listener?.onKeyPress(-1)
|
||||
}
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
fun onKeyPress(keyCode: Int)
|
||||
}
|
||||
}
|
|
@ -3,8 +3,6 @@ package org.thoughtcrime.securesms.components.registration;
|
|||
|
||||
import android.content.Context;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.inputmethodservice.Keyboard;
|
||||
import android.inputmethodservice.KeyboardView;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
@ -21,17 +19,18 @@ import androidx.annotation.Nullable;
|
|||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.NumericKeyboardView;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
|
||||
import org.thoughtcrime.securesms.util.concurrent.SettableFuture;
|
||||
|
||||
public class VerificationPinKeyboard extends FrameLayout {
|
||||
|
||||
private KeyboardView keyboardView;
|
||||
private ProgressBar progressBar;
|
||||
private ImageView successView;
|
||||
private ImageView failureView;
|
||||
private ImageView lockedView;
|
||||
private NumericKeyboardView keyboardView;
|
||||
private ProgressBar progressBar;
|
||||
private ImageView successView;
|
||||
private ImageView failureView;
|
||||
private ImageView lockedView;
|
||||
|
||||
private OnKeyPressListener listener;
|
||||
|
||||
|
@ -65,27 +64,8 @@ public class VerificationPinKeyboard extends FrameLayout {
|
|||
this.failureView = findViewById(R.id.failure);
|
||||
this.lockedView = findViewById(R.id.locked);
|
||||
|
||||
keyboardView.setPreviewEnabled(false);
|
||||
keyboardView.setKeyboard(new Keyboard(getContext(), R.xml.pin_keyboard));
|
||||
keyboardView.setOnKeyboardActionListener(new KeyboardView.OnKeyboardActionListener() {
|
||||
@Override
|
||||
public void onPress(int primaryCode) {
|
||||
if (listener != null) listener.onKeyPress(primaryCode);
|
||||
}
|
||||
@Override
|
||||
public void onRelease(int primaryCode) {}
|
||||
@Override
|
||||
public void onKey(int primaryCode, int[] keyCodes) {}
|
||||
@Override
|
||||
public void onText(CharSequence text) {}
|
||||
@Override
|
||||
public void swipeLeft() {}
|
||||
@Override
|
||||
public void swipeRight() {}
|
||||
@Override
|
||||
public void swipeDown() {}
|
||||
@Override
|
||||
public void swipeUp() {}
|
||||
keyboardView.setListener(keyCode -> {
|
||||
if (listener != null) listener.onKeyPress(keyCode);
|
||||
});
|
||||
|
||||
displayKeyboard();
|
||||
|
|
152
app/src/main/res/layout/numeric_keyboard_view.xml
Normal file
152
app/src/main/res/layout/numeric_keyboard_view.xml
Normal file
|
@ -0,0 +1,152 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/numeric_keyboard_1"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:gravity="center"
|
||||
android:text="@string/NumericKeyboardView__1"
|
||||
android:textAppearance="@style/Signal.Text.TitleLarge"
|
||||
app:layout_constraintBottom_toTopOf="@id/numeric_keyboard_4"
|
||||
app:layout_constraintEnd_toStartOf="@id/numeric_keyboard_2"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/numeric_keyboard_2"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:gravity="center"
|
||||
android:text="@string/NumericKeyboardView__2"
|
||||
android:textAppearance="@style/Signal.Text.TitleLarge"
|
||||
app:layout_constraintBottom_toTopOf="@id/numeric_keyboard_4"
|
||||
app:layout_constraintEnd_toStartOf="@id/numeric_keyboard_3"
|
||||
app:layout_constraintStart_toEndOf="@id/numeric_keyboard_1"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/numeric_keyboard_3"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:gravity="center"
|
||||
android:text="@string/NumericKeyboardView__3"
|
||||
android:textAppearance="@style/Signal.Text.TitleLarge"
|
||||
app:layout_constraintBottom_toTopOf="@id/numeric_keyboard_4"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/numeric_keyboard_2"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/numeric_keyboard_4"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:gravity="center"
|
||||
android:text="@string/NumericKeyboardView__4"
|
||||
android:textAppearance="@style/Signal.Text.TitleLarge"
|
||||
app:layout_constraintBottom_toTopOf="@id/numeric_keyboard_7"
|
||||
app:layout_constraintEnd_toStartOf="@id/numeric_keyboard_5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/numeric_keyboard_1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/numeric_keyboard_5"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:gravity="center"
|
||||
android:text="@string/NumericKeyboardView__5"
|
||||
android:textAppearance="@style/Signal.Text.TitleLarge"
|
||||
app:layout_constraintBottom_toTopOf="@id/numeric_keyboard_7"
|
||||
app:layout_constraintEnd_toStartOf="@id/numeric_keyboard_6"
|
||||
app:layout_constraintStart_toEndOf="@id/numeric_keyboard_4"
|
||||
app:layout_constraintTop_toBottomOf="@id/numeric_keyboard_1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/numeric_keyboard_6"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:gravity="center"
|
||||
android:text="@string/NumericKeyboardView__6"
|
||||
android:textAppearance="@style/Signal.Text.TitleLarge"
|
||||
app:layout_constraintBottom_toTopOf="@id/numeric_keyboard_7"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/numeric_keyboard_5"
|
||||
app:layout_constraintTop_toBottomOf="@id/numeric_keyboard_1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/numeric_keyboard_7"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:gravity="center"
|
||||
android:text="@string/NumericKeyboardView__7"
|
||||
android:textAppearance="@style/Signal.Text.TitleLarge"
|
||||
app:layout_constraintBottom_toTopOf="@id/numeric_keyboard_0"
|
||||
app:layout_constraintEnd_toStartOf="@id/numeric_keyboard_8"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/numeric_keyboard_4" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/numeric_keyboard_8"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:gravity="center"
|
||||
android:text="@string/NumericKeyboardView__8"
|
||||
android:textAppearance="@style/Signal.Text.TitleLarge"
|
||||
app:layout_constraintBottom_toTopOf="@id/numeric_keyboard_0"
|
||||
app:layout_constraintEnd_toEndOf="@id/numeric_keyboard_9"
|
||||
app:layout_constraintStart_toEndOf="@id/numeric_keyboard_7"
|
||||
app:layout_constraintTop_toBottomOf="@id/numeric_keyboard_4" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/numeric_keyboard_9"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:gravity="center"
|
||||
android:text="@string/NumericKeyboardView__9"
|
||||
android:textAppearance="@style/Signal.Text.TitleLarge"
|
||||
app:layout_constraintBottom_toTopOf="@id/numeric_keyboard_0"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/numeric_keyboard_8"
|
||||
app:layout_constraintTop_toBottomOf="@id/numeric_keyboard_4" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/numeric_keyboard_0"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:gravity="center"
|
||||
android:text="@string/NumericKeyboardView__0"
|
||||
android:textAppearance="@style/Signal.Text.TitleLarge"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="@id/numeric_keyboard_8"
|
||||
app:layout_constraintStart_toStartOf="@id/numeric_keyboard_8"
|
||||
app:layout_constraintTop_toBottomOf="@id/numeric_keyboard_9" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/numeric_keyboard_back"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/NumericKeyboardView__backspace"
|
||||
android:scaleType="centerInside"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="@id/numeric_keyboard_9"
|
||||
app:layout_constraintStart_toStartOf="@id/numeric_keyboard_9"
|
||||
app:layout_constraintTop_toBottomOf="@id/numeric_keyboard_9"
|
||||
app:srcCompat="@drawable/ic_backspace_24" />
|
||||
|
||||
</merge>
|
|
@ -22,6 +22,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:importantForAccessibility="yes"
|
||||
android:textColor="@color/signal_inverse_primary"
|
||||
android:textSize="28sp"
|
||||
tools:text="0" />
|
||||
|
@ -44,6 +45,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:importantForAccessibility="yes"
|
||||
android:textColor="@color/signal_inverse_primary"
|
||||
android:textSize="28sp"
|
||||
tools:text="1" />
|
||||
|
@ -66,6 +68,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:importantForAccessibility="yes"
|
||||
android:textColor="@color/signal_inverse_primary"
|
||||
android:textSize="28sp"
|
||||
tools:text="2" />
|
||||
|
@ -78,6 +81,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="4dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:text="-"
|
||||
android:textColor="@color/signal_inverse_primary"
|
||||
android:textSize="28sp"
|
||||
|
@ -101,6 +105,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:importantForAccessibility="yes"
|
||||
android:textColor="@color/signal_inverse_primary"
|
||||
android:textSize="28sp"
|
||||
tools:text="3" />
|
||||
|
@ -123,6 +128,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:importantForAccessibility="yes"
|
||||
android:textColor="@color/signal_inverse_primary"
|
||||
android:textSize="28sp"
|
||||
tools:text="4" />
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<android.inputmethodservice.KeyboardView
|
||||
<org.thoughtcrime.securesms.components.NumericKeyboardView
|
||||
android:id="@+id/keyboard_view"
|
||||
android:keyBackground="@color/grey_300"
|
||||
android:background="@color/grey_300"
|
||||
|
|
|
@ -59,6 +59,20 @@
|
|||
<string name="ApplicationPreferencesActivity_record_phrase">Record phrase</string>
|
||||
<string name="ApplicationPreferencesActivity_before_you_can_disable_your_pin">Before you can disable your PIN, you must record your payments recovery phrase to ensure you can recover your payments account.</string>
|
||||
|
||||
<!-- NumericKeyboardView -->
|
||||
<string name="NumericKeyboardView__1" translatable="false">1</string>
|
||||
<string name="NumericKeyboardView__2" translatable="false">2</string>
|
||||
<string name="NumericKeyboardView__3" translatable="false">3</string>
|
||||
<string name="NumericKeyboardView__4" translatable="false">4</string>
|
||||
<string name="NumericKeyboardView__5" translatable="false">5</string>
|
||||
<string name="NumericKeyboardView__6" translatable="false">6</string>
|
||||
<string name="NumericKeyboardView__7" translatable="false">7</string>
|
||||
<string name="NumericKeyboardView__8" translatable="false">8</string>
|
||||
<string name="NumericKeyboardView__9" translatable="false">9</string>
|
||||
<string name="NumericKeyboardView__0" translatable="false">0</string>
|
||||
<!-- Back button on numeric keyboard -->
|
||||
<string name="NumericKeyboardView__backspace">Backspace</string>
|
||||
|
||||
<!-- AppProtectionPreferenceFragment -->
|
||||
<plurals name="AppProtectionPreferenceFragment_minutes">
|
||||
<item quantity="one">%d minute</item>
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:keyWidth="33.3%p"
|
||||
android:keyHeight="10%p">
|
||||
|
||||
<Row>
|
||||
<Key android:codes="1" android:keyLabel="1" android:keyEdgeFlags="left" />
|
||||
<Key android:codes="2" android:keyLabel="2" />
|
||||
<Key android:codes="3" android:keyLabel="3" />
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
<Key android:codes="4" android:keyLabel="4" android:keyEdgeFlags="left" />
|
||||
<Key android:codes="5" android:keyLabel="5" />
|
||||
<Key android:codes="6" android:keyLabel="6" />
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
<Key android:codes="7" android:keyLabel="7" android:keyEdgeFlags="left" />
|
||||
<Key android:codes="8" android:keyLabel="8" />
|
||||
<Key android:codes="9" android:keyLabel="9" />
|
||||
</Row>
|
||||
<Row>
|
||||
<Key android:codes="0" android:keyLabel="0" android:horizontalGap="33.3%p"/>
|
||||
<Key android:codes="-1" android:keyIcon="@drawable/ic_backspace_grey600_24dp" android:isRepeatable="true"/>
|
||||
</Row>
|
||||
</Keyboard>
|
Loading…
Add table
Reference in a new issue