improve accessibility

This commit is contained in:
luvletter2333 2022-03-24 14:44:40 +08:00
parent 0ed8ff1ed3
commit 538e82ff01
No known key found for this signature in database
GPG Key ID: A26A8880836E1978
7 changed files with 147 additions and 110 deletions

View File

@ -1027,7 +1027,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
public float getProgress() {
if (currentMessageObject.isMusic()) {
return seekBar.getProgress();
} else if (currentMessageObject.isVoice()) {
} else if (currentMessageObject.isVoice() || currentMessageObject.isRoundVideo()) {
if (useSeekBarWaweform) {
return seekBarWaveform.getProgress();
} else {
@ -1042,7 +1042,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
public void setProgress(float progress) {
if (currentMessageObject.isMusic()) {
seekBar.setProgress(progress);
} else if (currentMessageObject.isVoice()) {
} else if (currentMessageObject.isVoice() || currentMessageObject.isRoundVideo()) {
if (useSeekBarWaweform) {
seekBarWaveform.setProgress(progress);
} else {
@ -10113,6 +10113,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
}
}
if (currentFocusedVirtualView == -1 && hasFocus()) announceForAccessibility((progress * 100) + "%");
}
@Override
@ -10129,6 +10130,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
}
createLoadingProgressLayout(uploadedSize, totalSize);
if (currentFocusedVirtualView == -1 && hasFocus()) announceForAccessibility((progress * 100) + "%");
}
private void createLoadingProgressLayout(TLRPC.Document document) {
@ -14576,7 +14578,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
@Override
public boolean performAccessibilityAction(int action, Bundle arguments) {
if (action == AccessibilityNodeInfo.ACTION_CLICK) {
if (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) {
currentFocusedVirtualView = -1;
} else if (action == AccessibilityNodeInfo.ACTION_CLICK) {
int icon = getIconForCurrentState();
if (icon != MediaActionDrawable.ICON_NONE && icon != MediaActionDrawable.ICON_FILE) {
didPressButton(true, false);
@ -14597,7 +14601,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
}
}
if (currentMessageObject.isVoice() || currentMessageObject.isMusic() && MediaController.getInstance().isPlayingMessage(currentMessageObject)) {
if (currentMessageObject.isVoice() || currentMessageObject.isRoundVideo() || currentMessageObject.isMusic() && MediaController.getInstance().isPlayingMessage(currentMessageObject)) {
if (seekBarAccessibilityDelegate.performAccessibilityActionInternal(action, arguments)) {
return true;
}
@ -14618,7 +14622,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
@Override
public boolean onHoverEvent(MotionEvent event) {
public boolean dispatchHoverEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
if (event.getAction() == MotionEvent.ACTION_HOVER_ENTER || event.getAction() == MotionEvent.ACTION_HOVER_MOVE) {
@ -14634,9 +14638,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
}
} else if (event.getAction() == MotionEvent.ACTION_HOVER_EXIT) {
currentFocusedVirtualView = 0;
currentFocusedVirtualView = -1;
}
return super.onHoverEvent(event);
return super.dispatchHoverEvent(event);
}
@Override
@ -15053,9 +15057,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
}
if ((currentMessageObject.isVoice() || currentMessageObject.isMusic()) && MediaController.getInstance().isPlayingMessage(currentMessageObject)) {
if ((currentMessageObject.isVoice() || currentMessageObject.isRoundVideo() || currentMessageObject.isMusic()) && MediaController.getInstance().isPlayingMessage(currentMessageObject)) {
seekBarAccessibilityDelegate.onInitializeAccessibilityNodeInfoInternal(info);
}
//smallest ids should be added at first,because talkback can focus on it not always in correct order
if (forwardedNameLayout[1] != null) {
info.addChild(ChatMessageCell.this, FORWARD);
}
int i;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
@ -15103,9 +15111,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
if (replyNameLayout != null) {
info.addChild(ChatMessageCell.this, REPLY);
}
if (forwardedNameLayout[0] != null && forwardedNameLayout[1] != null) {
info.addChild(ChatMessageCell.this, FORWARD);
}
if (drawSelectionBackground || getBackground() != null) {
info.setSelected(true);
}
@ -15309,14 +15314,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
info.setClickable(true);
} else if (virtualViewId == FORWARD) {
info.setEnabled(true);
StringBuilder sb = new StringBuilder();
if (forwardedNameLayout[0] != null && forwardedNameLayout[1] != null) {
for (int a = 0; a < 2; a++) {
sb.append(forwardedNameLayout[a].getText());
sb.append(a == 0 ? " " : "\n");
}
}
info.setContentDescription(sb.toString());
info.setContentDescription(currentForwardNameString);
info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
int x = (int) Math.min(forwardNameX - forwardNameOffsetX[0], forwardNameX - forwardNameOffsetX[1]);
@ -15332,7 +15330,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
info.setClassName("android.widget.Button");
info.setEnabled(true);
if (commentLayout != null) {
info.setText(commentLayout.getText());
//commentLayout not give for us text information about number of comments,so we shouldn't use text of layout for viryual node.
int commentCount = getRepliesCount();
info.setText(isRepliesChat ? LocaleController.getString("ViewInChat", R.string.ViewInChat) : commentCount == 0 ? LocaleController.getString("LeaveAComment", R.string.LeaveAComment) : LocaleController.formatPluralString("CommentsCount", commentCount));
}
info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
rect.set(commentButtonRect);
@ -15356,6 +15356,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
performAccessibilityAction(action, arguments);
} else {
if (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) {
currentFocusedVirtualView = virtualViewId;
sendAccessibilityEventForVirtualView(virtualViewId, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
} else if (action == AccessibilityNodeInfo.ACTION_CLICK) {
if (virtualViewId >= LINK_CAPTION_IDS_START) {

View File

@ -3322,7 +3322,6 @@ public class DialogCell extends BaseCell {
public boolean hasOverlappingRendering() {
return false;
}
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
@ -3331,83 +3330,79 @@ public class DialogCell extends BaseCell {
} else {
info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
}
}
@Override
public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
super.onPopulateAccessibilityEvent(event);
StringBuilder sb = new StringBuilder();
if (currentDialogFolderId == 1) {
sb.append(LocaleController.getString("ArchivedChats", R.string.ArchivedChats));
sb.append(". ");
} else {
if (encryptedChat != null) {
sb.append(LocaleController.getString("AccDescrSecretChat", R.string.AccDescrSecretChat));
if (checkBox != null) info.setSelected(checkBox.isChecked());
StringBuilder sb = new StringBuilder();
if (currentDialogFolderId == 1) {
sb.append(LocaleController.getString("ArchivedChats", R.string.ArchivedChats));
sb.append(". ");
}
if (user != null) {
if (UserObject.isReplyUser(user)) {
sb.append(LocaleController.getString("RepliesTitle", R.string.RepliesTitle));
} else {
if (user.bot) {
sb.append(LocaleController.getString("Bot", R.string.Bot));
sb.append(". ");
}
if (user.self) {
sb.append(LocaleController.getString("SavedMessages", R.string.SavedMessages));
} else {
sb.append(ContactsController.formatName(user.first_name, user.last_name));
}
}
sb.append(". ");
} else if (chat != null) {
if (chat.broadcast) {
sb.append(LocaleController.getString("AccDescrChannel", R.string.AccDescrChannel));
} else {
sb.append(LocaleController.getString("AccDescrGroup", R.string.AccDescrGroup));
}
sb.append(". ");
sb.append(chat.title);
sb.append(". ");
}
}
if (unreadCount > 0) {
sb.append(LocaleController.formatPluralString("NewMessages", unreadCount));
sb.append(". ");
}
if (message == null || currentDialogFolderId != 0) {
event.setContentDescription(sb.toString());
return;
}
int lastDate = lastMessageDate;
if (lastMessageDate == 0) {
lastDate = message.messageOwner.date;
}
String date = LocaleController.formatDateAudio(lastDate, true);
if (message.isOut()) {
sb.append(LocaleController.formatString("AccDescrSentDate", R.string.AccDescrSentDate, date));
} else {
sb.append(LocaleController.formatString("AccDescrReceivedDate", R.string.AccDescrReceivedDate, date));
}
sb.append(". ");
if (chat != null && !message.isOut() && message.isFromUser() && message.messageOwner.action == null) {
TLRPC.User fromUser = MessagesController.getInstance(currentAccount).getUser(message.getSenderId());
if (fromUser != null) {
sb.append(ContactsController.formatName(fromUser.first_name, fromUser.last_name));
sb.append(". ");
}
}
if (encryptedChat == null) {
sb.append(message.messageText);
if (!message.isMediaEmpty()) {
if (!TextUtils.isEmpty(message.caption)) {
} else {
if (encryptedChat != null) {
sb.append(LocaleController.getString("AccDescrSecretChat", R.string.AccDescrSecretChat));
sb.append(". ");
}
if (user != null) {
if (UserObject.isReplyUser(user)) {
sb.append(LocaleController.getString("RepliesTitle", R.string.RepliesTitle));
} else {
if (user.bot) {
sb.append(LocaleController.getString("Bot", R.string.Bot));
sb.append(". ");
}
if (user.self) {
sb.append(LocaleController.getString("SavedMessages", R.string.SavedMessages));
} else {
sb.append(ContactsController.formatName(user.first_name, user.last_name));
}
}
sb.append(". ");
} else if (chat != null) {
if (chat.broadcast) {
sb.append(LocaleController.getString("AccDescrChannel", R.string.AccDescrChannel));
} else {
sb.append(LocaleController.getString("AccDescrGroup", R.string.AccDescrGroup));
}
sb.append(". ");
sb.append(chat.title);
sb.append(". ");
sb.append(message.caption);
}
}
if (unreadCount > 0) {
sb.append(LocaleController.formatPluralString("NewMessages", unreadCount));
sb.append(". ");
}
if (message == null || currentDialogFolderId != 0) {
info.setContentDescription(sb.toString());
return;
}
int lastDate = lastMessageDate;
if (lastMessageDate == 0) {
lastDate = message.messageOwner.date;
}
String date = LocaleController.formatDateAudio(lastDate, true);
if (message.isOut()) {
sb.append(LocaleController.formatString("AccDescrSentDate", R.string.AccDescrSentDate, date));
} else {
sb.append(LocaleController.formatString("AccDescrReceivedDate", R.string.AccDescrReceivedDate, date));
}
sb.append(". ");
if (chat != null && !message.isOut() && message.isFromUser() && message.messageOwner.action == null) {
TLRPC.User fromUser = MessagesController.getInstance(currentAccount).getUser(message.getSenderId());
if (fromUser != null) {
sb.append(ContactsController.formatName(fromUser.first_name, fromUser.last_name));
sb.append(". ");
}
}
if (encryptedChat == null) {
sb.append(message.messageText);
if (!message.isMediaEmpty()) {
if (!TextUtils.isEmpty(message.caption)) {
sb.append(". ");
sb.append(message.caption);
}
}
}
info.setContentDescription(sb.toString());
}
event.setContentDescription(sb.toString());
}
public void setClipProgress(float value) {

View File

@ -674,6 +674,7 @@ public class ProfileSearchCell extends BaseCell {
builder.append(statusLayout.getText());
}
info.setText(builder.toString());
if (checkBox != null) info.setSelected(checkBox.isChecked());
}
public long getDialogId() {

View File

@ -6,6 +6,7 @@ import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
@ -14,6 +15,7 @@ import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.LinearLayout;
import android.widget.TextView;
@ -73,6 +75,18 @@ public class BotCommandsMenuView extends View {
int lastSize;
@Override
public CharSequence getAccessibilityClassName() {
return "android.Widget.Button";
}
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.addAction(isOpened()? AccessibilityNodeInfo.AccessibilityAction.ACTION_COLLAPSE : AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND);
info.setContentDescription(LocaleController.getString("AccDescrBotCommands",R.string.AccDescrBotCommands));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int size = MeasureSpec.getSize(widthMeasureSpec) + MeasureSpec.getSize(heightMeasureSpec) << 16;

View File

@ -930,6 +930,12 @@ public class Bulletin {
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
addView(textView, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL, 56, 0, 16, 0));
}
@Override
protected void onShow() {
super.onShow();
AndroidUtilities.makeAccessibilityAnnouncement(textView.getText());
}
}
@SuppressLint("ViewConstructor")
@ -949,6 +955,12 @@ public class Bulletin {
textView.setTypeface(Typeface.SANS_SERIF);
addView(textView, LayoutHelper.createFrameRelatively(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL, 56, 0, 16, 0));
}
@Override
protected void onShow() {
super.onShow();
AndroidUtilities.makeAccessibilityAnnouncement(textView.getText());
}
}
@SuppressLint("ViewConstructor")
@ -984,6 +996,11 @@ public class Bulletin {
linearLayout.addView(subtitleTextView);
}
@Override
protected void onShow() {
super.onShow();
AndroidUtilities.makeAccessibilityAnnouncement(titleTextView.getText() + ". " + subtitleTextView.getText());
}
}
public static class TwoLineLottieLayout extends ButtonLayout {
@ -1027,6 +1044,7 @@ public class Bulletin {
protected void onShow() {
super.onShow();
imageView.playAnimation();
AndroidUtilities.makeAccessibilityAnnouncement(titleTextView.getText() + ". " + subtitleTextView.getText());
}
public void setAnimation(int resId, String... layers) {
@ -1082,6 +1100,7 @@ public class Bulletin {
protected void onShow() {
super.onShow();
imageView.playAnimation();
AndroidUtilities.makeAccessibilityAnnouncement(textView.getText());
}
public void setAnimation(int resId, String... layers) {

View File

@ -50,7 +50,7 @@ public class AcceptDeclineView extends View {
private AcceptDeclineAccessibilityNodeProvider accessibilityNodeProvider;
private int buttonWidth;
private int currentFocusedVirtualViewId = View.NO_ID;
float smallRadius;
float bigRadius;
boolean expandSmallRadius = true;
@ -420,11 +420,17 @@ public class AcceptDeclineView extends View {
}
@Override
public boolean onHoverEvent(MotionEvent event) {
if (accessibilityNodeProvider != null && accessibilityNodeProvider.onHoverEvent(event)) {
public boolean dispatchHoverEvent(MotionEvent event) {
if (accessibilityNodeProvider != null && accessibilityNodeProvider.dispatchHoverEvent(event)) {
return true;
}
return super.onHoverEvent(event);
return super.dispatchHoverEvent(event);
}
@Override
public boolean performAccessibilityAction(int action, Bundle arguments) {
if (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) currentFocusedVirtualViewId = NO_ID;
return super.performAccessibilityAction(action, arguments);
}
@Override
@ -494,15 +500,12 @@ public class AcceptDeclineView extends View {
this.screenWasWakeup = screenWasWakeup;
}
private static abstract class AcceptDeclineAccessibilityNodeProvider extends AccessibilityNodeProvider {
private abstract class AcceptDeclineAccessibilityNodeProvider extends AccessibilityNodeProvider {
private final View hostView;
private final int virtualViewsCount;
private final Rect rect = new Rect();
private final AccessibilityManager accessibilityManager;
private int currentFocusedVirtualViewId = View.NO_ID;
private AcceptDeclineAccessibilityNodeProvider(View hostView, int virtualViewsCount) {
this.hostView = hostView;
this.virtualViewsCount = virtualViewsCount;
@ -545,16 +548,16 @@ public class AcceptDeclineView extends View {
return hostView.performAccessibilityAction(action, arguments);
} else {
if (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) {
currentFocusedVirtualViewId = virtualViewId;
sendAccessibilityEventForVirtualView(virtualViewId, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
} else if (action == AccessibilityNodeInfo.ACTION_CLICK) {
onVirtualViewClick(virtualViewId);
return true;
}
}
return false;
return true;// For action accessibilityFocus should be return true too,because in other case screenreader will consider,what it's the last node on the screen,and we will hear sound fron it,which announce about it.
}
public boolean onHoverEvent(MotionEvent event) {
public boolean dispatchHoverEvent(MotionEvent event) {
final int x = (int) event.getX();
final int y = (int) event.getY();
if (event.getAction() == MotionEvent.ACTION_HOVER_ENTER || event.getAction() == MotionEvent.ACTION_HOVER_MOVE) {
@ -569,8 +572,8 @@ public class AcceptDeclineView extends View {
}
}
} else if (event.getAction() == MotionEvent.ACTION_HOVER_EXIT) {
if (currentFocusedVirtualViewId != View.NO_ID) {
currentFocusedVirtualViewId = View.NO_ID;
if (currentFocusedVirtualViewId != -1) {
currentFocusedVirtualViewId = -1;
return true;
}
}

View File

@ -607,10 +607,14 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No
menu.setSubMenuOpenSide(1);
menu.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector)));
menu.addSubItem(menu_proxy, R.drawable.proxy_on, LocaleController.getString("Proxy", R.string.Proxy));
menu.addSubItem(menu_language, R.drawable.ic_translate, LocaleController.getString("Language", R.string.Language));
menu.addSubItem(menu_bot_login, R.drawable.list_bot, LocaleController.getString("BotLogin", R.string.BotLogin));
menu.addSubItem(menu_qr_login, R.drawable.wallet_qr, LocaleController.getString("ImportLogin", R.string.ImportLogin));
menu.addSubItem(menu_proxy, R.drawable.proxy_on, LocaleController.getString("Proxy", R.string.Proxy))
.setContentDescription(LocaleController.getString("Proxy", R.string.Proxy));
menu.addSubItem(menu_language, R.drawable.ic_translate, LocaleController.getString("Language", R.string.Language))
.setContentDescription(LocaleController.getString("Language", R.string.Language));
menu.addSubItem(menu_bot_login, R.drawable.list_bot, LocaleController.getString("BotLogin", R.string.BotLogin))
.setContentDescription(LocaleController.getString("BotLogin", R.string.BotLogin));
menu.addSubItem(menu_qr_login, R.drawable.wallet_qr, LocaleController.getString("ImportLogin", R.string.ImportLogin))
.setContentDescription(LocaleController.getString("ImportLogin", R.string.ImportLogin));
// otherItem.addSubItem(menu_custom_api, R.drawable.baseline_vpn_key_24, LocaleController.getString("CustomApi", R.string.CustomApi));
// menu.addSubItem(menu_custom_dc, R.drawable.baseline_sync_24, LocaleController.getString("CustomBackend", R.string.CustomBackend));