mirror of
https://github.com/KDE/kdeconnect-android
synced 2025-08-22 09:58:08 +00:00
Accessibility improvements when using a screen reader
Fixes based on the report done by HAN University of Applied Sciences.
This commit is contained in:
parent
47fe781685
commit
8ffee90255
@ -31,13 +31,16 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
|
||||
android:layout_centerInParent="true"
|
||||
android:gravity="center"
|
||||
android:padding="12dip"
|
||||
android:importantForAccessibility="no"
|
||||
android:text="@string/mousepad_info" />
|
||||
|
||||
<org.kde.kdeconnect.Plugins.MousePadPlugin.KeyListenerView
|
||||
android:id="@+id/keyListener"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@id/mouse_buttons"/>
|
||||
android:layout_above="@id/mouse_buttons"
|
||||
android:contentDescription="@string/mousepad_info_no_gestures"
|
||||
/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/mouse_buttons"
|
||||
@ -50,6 +53,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
|
||||
android:id="@+id/mouse_click_left"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="@string/left_click"
|
||||
android:layout_weight="3"
|
||||
app:icon="@drawable/left_click_48dp"
|
||||
style="@style/KdeConnectButton.IconButton" />
|
||||
@ -57,6 +61,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/mouse_click_middle"
|
||||
android:layout_width="wrap_content"
|
||||
android:contentDescription="@string/middle_click"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
style="@style/KdeConnectButton.IconButton.Secondary" />
|
||||
@ -64,6 +69,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/mouse_click_right"
|
||||
android:layout_width="wrap_content"
|
||||
android:contentDescription="@string/right_click"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="3"
|
||||
app:icon="@drawable/right_click_48dp"
|
||||
|
@ -14,11 +14,12 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
|
||||
android:layout_height="match_parent"
|
||||
tools:context="org.kde.kdeconnect.Plugins.MprisPlugin.MprisActivity">
|
||||
|
||||
<!-- Keep in sync with toolbar.xml, copied here because it needs the nested TabLayout -->
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize" />
|
||||
|
@ -48,7 +48,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
|
||||
android:layout_gravity="top"
|
||||
android:paddingTop="@dimen/nav_header_vertical_spacing"
|
||||
android:paddingBottom="4dp"
|
||||
android:contentDescription="@string/kde_connect"
|
||||
android:importantForAccessibility="no"
|
||||
tools:src="@drawable/icon" />
|
||||
|
||||
<LinearLayout
|
||||
|
@ -30,9 +30,9 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:contentDescription="@string/device_icon_description"
|
||||
android:src="@drawable/ic_device_laptop_32dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:importantForAccessibility="no"
|
||||
app:tint="?attr/colorOnSurface" />
|
||||
|
||||
<TextView
|
||||
|
@ -26,8 +26,8 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="12dp"
|
||||
android:contentDescription="@string/device_icon_description"
|
||||
android:src="@drawable/ic_device_laptop_32dp"
|
||||
android:importantForAccessibility="no"
|
||||
app:tint="?attr/colorControlNormal"/>
|
||||
|
||||
<LinearLayout
|
||||
|
@ -14,5 +14,6 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/mouse_cursor"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/mouse_pointer" />
|
||||
</RelativeLayout>
|
||||
|
@ -19,7 +19,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
|
||||
android:layout_height="@dimen/mpris_now_playing_album_height"
|
||||
android:layout_margin="25dp"
|
||||
android:layout_weight="@integer/mpris_now_playing_album_weight"
|
||||
android:contentDescription="@string/mpris_coverart_description"
|
||||
android:importantForAccessibility="no"
|
||||
android:scaleType="fitCenter" />
|
||||
|
||||
<include
|
||||
|
@ -30,6 +30,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
|
||||
android:layout_gravity="top"
|
||||
android:paddingTop="@dimen/nav_header_vertical_spacing"
|
||||
android:paddingBottom="4dp"
|
||||
android:importantForAccessibility="no"
|
||||
tools:srcCompat="@drawable/ic_device_phone_32dp" />
|
||||
|
||||
<LinearLayout
|
||||
|
@ -39,6 +39,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
|
||||
android:layout_height="wrap_content"
|
||||
android:drawablePadding="5dp"
|
||||
android:layout_marginBottom="8dip"
|
||||
android:importantForAccessibility="no"
|
||||
android:visibility="gone"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
app:drawableStartCompat="@drawable/ic_key" />
|
||||
|
@ -30,7 +30,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
|
||||
android:layout_height="wrap_content"
|
||||
android:tint="@color/text_color"
|
||||
android:src="@drawable/ic_kde_24dp"
|
||||
android:contentDescription="@string/device_icon_description"
|
||||
android:importantForAccessibility="no"
|
||||
tools:ignore="UseAppTint"/> <!-- can't use app:tint in RemoteView -->
|
||||
|
||||
<TextView
|
||||
|
@ -66,6 +66,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
|
||||
<string name="remotekeyboard_multiple_connections" translatable="true">There is more than one remote keyboard connection, select the device to configure</string>
|
||||
<string name="open_mousepad">Remote input</string>
|
||||
<string name="mousepad_info">Move a finger on the screen to move the mouse cursor. Tap for a click, and use two/three fingers for right and middle buttons. Use 2 fingers to scroll. Use a long press to drag\'n drop. Gyro mouse functionality can be enabled from plugin preferences</string>
|
||||
<string name="mousepad_info_no_gestures">Move a finger on the screen to move the mouse cursor, tap for a click.</string>
|
||||
<string name="mousepad_keyboard_input_not_supported">Keyboard input not supported by the paired device</string>
|
||||
<string name="mousepad_single_tap_settings_title">Set one finger tap action</string>
|
||||
<string name="mousepad_double_tap_settings_title">Set two finger tap action</string>
|
||||
@ -181,6 +182,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
|
||||
<string name="my_device_fingerprint">SHA256 fingerprint of your device certificate is:</string>
|
||||
<string name="remote_device_fingerprint">SHA256 fingerprint of remote device certificate is:</string>
|
||||
<string name="pair_requested">Pair requested</string>
|
||||
<string name="pair_succeeded">Pair succeeded</string>
|
||||
<string name="pairing_request_from">Pairing request from %1s</string>
|
||||
<string name="pairing_verification_code" translatable="false">🔑%1s...</string>
|
||||
<plurals name="incoming_file_title">Receiving file from %1s>
|
||||
@ -219,6 +221,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
|
||||
<string name="received_file_text">Tap to open \'%1s\'</string>
|
||||
<string name="cannot_create_file">Cannot create file %s</string>
|
||||
<string name="tap_to_answer">Tap to answer</string>
|
||||
<string name="left_click">Send Left Click</string>
|
||||
<string name="right_click">Send Right Click</string>
|
||||
<string name="middle_click">Send Middle Click</string>
|
||||
<string name="show_keyboard">Show Keyboard</string>
|
||||
@ -345,7 +348,6 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
|
||||
<string name="telephony_pref_blocked_title">Blocked numbers</string>
|
||||
<string name="telephony_pref_blocked_dialog_desc">Don\'t show calls and SMS from these numbers. Please specify one number per line</string>
|
||||
<string name="mpris_coverart_description">Cover art of current media</string>
|
||||
<string name="device_icon_description">Device icon</string>
|
||||
<string name="settings_icon_description">Settings icon</string>
|
||||
|
||||
<string name="presenter_fullscreen">Fullscreen</string>
|
||||
|
@ -95,6 +95,7 @@ class ComposeSendActivity : AppCompatActivity() {
|
||||
KdeTopAppBar(
|
||||
title = stringResource(R.string.compose_send_title),
|
||||
navIconOnClick = { onBackPressedDispatcher.onBackPressed() },
|
||||
navIconDescription = getString(androidx.appcompat.R.string.abc_action_bar_up_description),
|
||||
actions = {
|
||||
KdeTextButton(
|
||||
modifier = Modifier.padding(horizontal = 8.dp),
|
||||
|
@ -133,10 +133,12 @@ class PresenterActivity : AppCompatActivity(), SensorEventListener {
|
||||
KdeButton(
|
||||
onClick = { plugin.sendPrevious() },
|
||||
modifier = Modifier.fillMaxSize().weight(1f),
|
||||
contentDescription = getString(R.string.mpris_previous),
|
||||
icon = Icons.Default.ArrowBack,
|
||||
)
|
||||
KdeButton(
|
||||
onClick = { plugin.sendNext() },
|
||||
contentDescription = getString(R.string.mpris_next),
|
||||
modifier = Modifier.fillMaxSize().weight(1f),
|
||||
icon = Icons.Default.ArrowForward,
|
||||
)
|
||||
@ -176,7 +178,11 @@ class PresenterActivity : AppCompatActivity(), SensorEventListener {
|
||||
|
||||
var dropdownShownState by remember { mutableStateOf(false) }
|
||||
|
||||
KdeTopAppBar(navIconOnClick = { onBackPressedDispatcher.onBackPressed() }, actions = {
|
||||
KdeTopAppBar(
|
||||
title = stringResource(R.string.pref_plugin_presenter),
|
||||
navIconOnClick = { onBackPressedDispatcher.onBackPressed() },
|
||||
navIconDescription = getString(androidx.appcompat.R.string.abc_action_bar_up_description),
|
||||
actions = {
|
||||
IconButton(onClick = { dropdownShownState = true }) {
|
||||
Icon(Icons.Default.MoreVert, stringResource(R.string.extra_options))
|
||||
}
|
||||
@ -190,6 +196,7 @@ class PresenterActivity : AppCompatActivity(), SensorEventListener {
|
||||
text = { Text(stringResource(R.string.presenter_exit)) },
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
@ -23,6 +23,10 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.semantics.heading
|
||||
import androidx.compose.ui.semantics.role
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.*
|
||||
@ -113,7 +117,7 @@ class DeviceFragment : Fragment() {
|
||||
requirePairingBinding().pairButton.setOnClickListener {
|
||||
with(requirePairingBinding()) {
|
||||
pairButton.visibility = View.GONE
|
||||
pairMessage.text = null
|
||||
pairMessage.text = getString(R.string.pair_requested)
|
||||
pairVerification.visibility = View.VISIBLE
|
||||
pairVerification.text = SslHelper.getVerificationKey(SslHelper.certificate, device?.certificate)
|
||||
pairProgress.visibility = View.VISIBLE
|
||||
@ -306,6 +310,7 @@ class DeviceFragment : Fragment() {
|
||||
}
|
||||
|
||||
override fun pairingSuccessful() {
|
||||
requirePairingBinding().pairMessage.announceForAccessibility(getString(R.string.pair_succeeded))
|
||||
mActivity?.runOnUiThread { refreshUI() }
|
||||
}
|
||||
|
||||
@ -383,7 +388,7 @@ class DeviceFragment : Fragment() {
|
||||
fun PluginButton(plugin : Plugin, modifier: Modifier) {
|
||||
Card(
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
modifier = modifier,
|
||||
modifier = modifier.semantics { role = Role.Button },
|
||||
onClick = { plugin.startMainActivity(mActivity) }
|
||||
) {
|
||||
Column(
|
||||
@ -435,7 +440,7 @@ class DeviceFragment : Fragment() {
|
||||
fun PluginsWithoutPermissions(title : String, plugins: Collection<Plugin>, action : (plugin: Plugin) -> Unit) {
|
||||
Text(
|
||||
text = title,
|
||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 6.dp)
|
||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 6.dp).semantics { heading() }
|
||||
)
|
||||
plugins.forEach { plugin ->
|
||||
Text(
|
||||
@ -444,6 +449,7 @@ class DeviceFragment : Fragment() {
|
||||
.fillMaxWidth()
|
||||
.clickable { action(plugin) }
|
||||
.padding(start = 28.dp, end = 16.dp, top = 12.dp, bottom = 12.dp)
|
||||
.semantics { role = Role.Button }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ fun KdeButton(
|
||||
modifier: Modifier = Modifier,
|
||||
colors: ButtonColors = ButtonDefaults.buttonColors(),
|
||||
text: String? = null,
|
||||
contentDescription: String? = null,
|
||||
icon: ImageVector? = null,
|
||||
) {
|
||||
//TODO uncomment when button is widely used
|
||||
@ -69,7 +70,7 @@ fun KdeButton(
|
||||
colors = colors,
|
||||
// interactionSource = interactionSource,
|
||||
content = {
|
||||
icon?.let { Icon(imageVector = it, contentDescription = text) }
|
||||
icon?.let { Icon(imageVector = it, contentDescription = contentDescription ?: text) }
|
||||
text?.let { Text(it, maxLines = 1, overflow = Ellipsis) }
|
||||
}
|
||||
)
|
||||
@ -83,6 +84,7 @@ fun IconButtonPreview() {
|
||||
Modifier.width(120.dp),
|
||||
ButtonDefaults.buttonColors(Color.Gray, Color.DarkGray),
|
||||
"Button Text",
|
||||
null,
|
||||
Icons.Default.Build,
|
||||
)
|
||||
}
|
@ -11,8 +11,11 @@ import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.heading
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import org.kde.kdeconnect_tp.R
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@ -20,14 +23,20 @@ import org.kde.kdeconnect_tp.R
|
||||
fun KdeTopAppBar(
|
||||
title: String = stringResource(R.string.kde_connect),
|
||||
navIcon: ImageVector = Icons.Default.ArrowBack,
|
||||
navIconDescription: String = "",
|
||||
navIconOnClick: () -> Unit, // = { onBackPressedDispatcher.onBackPressed() }
|
||||
actions: @Composable (RowScope.() -> Unit) = {},
|
||||
) {
|
||||
TopAppBar(
|
||||
navigationIcon = {
|
||||
IconButton(onClick = navIconOnClick, content = { Icon(navIcon, null) })
|
||||
IconButton(onClick = navIconOnClick, content = { Icon(navIcon, navIconDescription) })
|
||||
},
|
||||
title = { Text(title) },
|
||||
title = { Text(title,
|
||||
// Commented for now because the MDC and androidx toolbars don't set this either
|
||||
// https://github.com/material-components/material-components-android/issues/4073
|
||||
// https://github.com/androidx/androidx/blob/androidx-main/appcompat/appcompat/src/main/res/layout/abc_action_bar_title_item.xml
|
||||
// modifier = Modifier.semantics { heading() }
|
||||
) },
|
||||
actions = actions
|
||||
)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user