Skip to content

Commit

Permalink
[hapjs-platform#631]【1300联盟版本】无障碍新增组件属性方法
Browse files Browse the repository at this point in the history
Change-Id: Ib491decfcc32050c9799dd2546ed163564e602bc
Signed-off-by: cmc <mingcan.chen@vivo.com>
  • Loading branch information
mingcan-mc committed Dec 13, 2023
1 parent 839910c commit 90d388e
Show file tree
Hide file tree
Showing 64 changed files with 597 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.view.accessibility.AccessibilityEvent;
import android.widget.RelativeLayout;
import androidx.annotation.NonNull;
import androidx.collection.ArraySet;
Expand Down Expand Up @@ -101,12 +102,15 @@
import org.hapjs.runtime.RuntimeActivity;
import org.hapjs.system.SysOpProvider;
import org.json.JSONException;
import org.hapjs.system.utils.TalkBackUtils;
import org.json.JSONObject;

public abstract class Component<T extends View>
implements ActivityStateListener, ComponentDataHolder, IHybridViewHolder {

public static final int INVALID_PAGE_ID = -1;
public static final String METHOD_TALKBACK_FOCUS = "requestTalkBackFocus";
public static final String METHOD_TALKBACK_ANNOUNCE = "announceForTalkBack";
public static final String METHOD_FOCUS = "focus";
public static final String METHOD_ANIMATE = "animate";
public static final String METHOD_REQUEST_FULLSCREEN = "requestFullscreen";
Expand Down Expand Up @@ -981,10 +985,12 @@ protected boolean setAttribute(String key, Object attribute) {
setFocusable(focusable);
return true;
case Attributes.Style.ARIA_LABEL:
case Attributes.Style.ARIA_LABEL_LOWER:
String ariaLabel = Attributes.getString(attribute);
setAriaLabel(ariaLabel);
return true;
case Attributes.Style.ARIA_UNFOCUSABLE:
case Attributes.Style.ARIA_UNFOCUSABLE_LOWER:
boolean ariaUnfocusable = Attributes.getBoolean(attribute, true);
setAriaUnfocusable(ariaUnfocusable);
return true;
Expand Down Expand Up @@ -2926,6 +2932,14 @@ public void invokeMethod(String methodName, final Map<String, Object> args) {
focus = Attributes.getBoolean(args.get("focus"), true);
}
focus(focus);
} else if (METHOD_TALKBACK_FOCUS.equals(methodName)) {
requestTalkBackFocus();
} else if (METHOD_TALKBACK_ANNOUNCE.equals(methodName)) {
String content = null;
if (args != null && args.get("content") != null) {
content = Attributes.getString(args.get("content"), "");
}
announceForTalkBack(content);
} else if (METHOD_REQUEST_FULLSCREEN.equals(methodName)) {
int screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
if (args != null) {
Expand Down Expand Up @@ -4250,4 +4264,57 @@ public void setFullScreenView(View view) {
public boolean preConsumeEvent(String eventName, Map<String, Object> data, boolean immediately) {
return false;
}


public void requestTalkBackFocus() {
if (isEnableTalkBack() && mHost != null) {
if (mHost.isAttachedToWindow()) {
mHost.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
} else {
Log.w(TAG, "requestTalkBackFocus is not valid.");
mHost.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
mHost.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
mHost.removeOnAttachStateChangeListener(this);
}

@Override
public void onViewDetachedFromWindow(View v) {

}
});
}
}
}

public void announceForTalkBack(String content) {
if (isEnableTalkBack() && mHost != null && !TextUtils.isEmpty(content)) {
if (mHost.isAttachedToWindow()) {
mHost.announceForAccessibility(content);
} else {
Log.w(TAG, "announceForTalkBack is not valid.");
mHost.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
mHost.announceForAccessibility(content);
mHost.removeOnAttachStateChangeListener(this);
}

@Override
public void onViewDetachedFromWindow(View v) {

}
});
}
}
}

public boolean isEnableTalkBack() {
return TalkBackUtils.isEnableTalkBack(mContext, false);
}

public void performComponentClick(MotionEvent event) {

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public abstract class RecyclerDataItem implements ComponentDataHolder {
private final CombinedMap<String, CSSValues> mStyleDomData = new CombinedMap<>();
private final CombinedMap<String, Object> mAttrsDomData = new CombinedMap<>();
private final CombinedMap<String, Boolean> mEventDomData = new CombinedMap<>();
private final ComponentCreator mComponentCreator;
public final ComponentCreator mComponentCreator;
protected Node mCssNode;
private Container.RecyclerItem mParent;
private Component mBoundRecycleComponent;
Expand Down Expand Up @@ -384,6 +384,10 @@ public static class ComponentCreator {
private RenderEventCallback mCallback;
private Widget mWidget;

public Context getContext() {
return mContext;
}

public ComponentCreator(
HapEngine hapEngine, Context context, RenderEventCallback callback, Widget widget) {
mHapEngine = hapEngine;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,9 @@ public interface Style {
String MODE = "mode";

String ARIA_LABEL = "ariaLabel";
String ARIA_LABEL_LOWER = "arialabel";
String ARIA_UNFOCUSABLE = "ariaUnfocusable";
String ARIA_UNFOCUSABLE_LOWER = "ariaunfocusable";

String FORCE_DARK = "forcedark";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,40 @@ public class PercentFlexboxLayout extends YogaLayout implements ComponentHost, G

private List<Integer> mPositionArray;
private boolean mDisallowIntercept = false;
private boolean mIsEnableTalkBack;
private MotionEvent mLastMotionEvent = null;

public PercentFlexboxLayout(Context context) {
super(context);
mIsEnableTalkBack = TalkBackUtils.isEnableTalkBack(context, false);
getYogaNode().setFlexDirection(YogaFlexDirection.ROW);
getYogaNode().setFlexShrink(1f);
}

@Override
public boolean performClick() {
boolean isConsume = super.performClick();
if (mIsEnableTalkBack) {
if (null != mComponent) {
mComponent.performComponentClick(mLastMotionEvent);
}
}
return isConsume;
}


@Override
protected boolean dispatchHoverEvent(MotionEvent event) {
mLastMotionEvent = event;
return super.dispatchHoverEvent(event);
}

@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mLastMotionEvent = null;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (!(getParent() instanceof YogaLayout)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.hapjs.model.videodata.VideoCacheManager;
import org.hapjs.render.RootView;
import org.hapjs.render.jsruntime.JsThread;
import org.hapjs.system.utils.TalkBackUtils;

public class RuntimeActivity extends AppCompatActivity {
public static final String PROP_APP = "runtime.app";
Expand Down Expand Up @@ -418,6 +419,7 @@ protected void onResume() {
if (mHybridView != null) {
mHybridView.getHybridManager().onResume();
}
TalkBackUtils.isEnableTalkBack(RuntimeActivity.this,true);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -535,4 +535,8 @@ public int getSafeAreaWidth(Context context) {
return 0;
}

@Override
public boolean isEnableTalkBack(Context context) {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,6 @@ interface OnUpdateMenubarDataCallback {
int getFoldDisplayWidth(Context context);

int getSafeAreaWidth(Context context);

boolean isEnableTalkBack(Context context);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright (C) 2022, hapjs.org. All rights reserved.
*/
package org.hapjs.system.utils;

import android.content.ComponentName;
import android.content.Context;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;

import org.hapjs.runtime.ProviderManager;
import org.hapjs.system.SysOpProvider;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

public class TalkBackUtils {
private final static String TAG = "TalkBackUtils";
/*
* 获取当前开启的所有辅助功能服务
*/
static int sTalkBackEnable = -1;
static volatile boolean sIsForceCheck;
static volatile boolean sIsChecking;
static final int TALKBACK_ENABLE = 1;
static final int TALKBACK_DISABLE = 0;
static final int TALKBACK_DEFAULT = -1;
static final char ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR = ':';
static final ComponentName TALKBACK_SERVICE_ENABLE = ComponentName.unflattenFromString("com.google.android.marvin.talkback/com.google.android.marvin.talkback.TalkBackService");
final static TextUtils.SimpleStringSplitter sStringColonSplitter =
new TextUtils.SimpleStringSplitter(ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR);

private static Set<ComponentName> getEnabledServicesFromSettings(Context context) {
Set<ComponentName> enabledServices = null;
if (null == context) {
return enabledServices;
}
try {
String enabledServicesSetting = Settings.Secure.getString(context.getContentResolver(), "enabled_accessibility_services");
if (TextUtils.isEmpty(enabledServicesSetting)) {
return Collections.emptySet();
} else {
enabledServices = new HashSet();
TextUtils.SimpleStringSplitter colonSplitter = sStringColonSplitter;
colonSplitter.setString(enabledServicesSetting);
while (colonSplitter.hasNext()) {
String componentNameString = colonSplitter.next();
ComponentName enabledService = ComponentName.unflattenFromString(componentNameString);
if (enabledService != null) {
enabledServices.add(enabledService);
}
}
return enabledServices;
}
} catch (Exception e) {
Log.w(TAG, "getEnabledServicesFromSettings error : " + e.getMessage());
}
return enabledServices;
}

public static void setIsForceCheck(boolean isForceCheck) {
TalkBackUtils.sIsForceCheck = isForceCheck;
}

public static boolean isEnableTalkBack(Context context, boolean forceCheck) {
if (sIsChecking) {
return true;
}
if ((sIsForceCheck || forceCheck || sTalkBackEnable == TALKBACK_DEFAULT) && null != context) {
sIsForceCheck = false;
sIsChecking = true;
boolean isEnable = false;
SysOpProvider provider = ProviderManager.getDefault().getProvider(SysOpProvider.NAME);
if (null != provider) {
isEnable = provider.isEnableTalkBack(context);
}
if (isEnable) {
Set<ComponentName> componentNames = getEnabledServicesFromSettings(context);
if (null != componentNames && componentNames.contains(TALKBACK_SERVICE_ENABLE)) {
sTalkBackEnable = TALKBACK_ENABLE;
sIsChecking = false;
return true;
}
}
sTalkBackEnable = TALKBACK_DISABLE;
sIsChecking = false;
return false;
} else {
return sTalkBackEnable == TALKBACK_ENABLE;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
Component.METHOD_ANIMATE,
Component.METHOD_GET_BOUNDING_CLIENT_RECT,
Component.METHOD_TO_TEMP_FILE_PATH,
Component.METHOD_FOCUS
Component.METHOD_FOCUS,
Component.METHOD_TALKBACK_FOCUS,
Component.METHOD_TALKBACK_ANNOUNCE
})
public class A extends Text {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@
Camera.METHOD_GET_EXPOSURE_VALUE,
Camera.METHOD_GET_FPS_RANGE,
Camera.METHOD_START_RECORD,
Camera.METHOD_STOP_RECORD
Camera.METHOD_STOP_RECORD,
Component.METHOD_TALKBACK_FOCUS,
Component.METHOD_TALKBACK_ANNOUNCE
})
public class Camera extends Component<CameraView> {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
Component.METHOD_ANIMATE,
Component.METHOD_GET_BOUNDING_CLIENT_RECT,
Component.METHOD_TO_TEMP_FILE_PATH,
Component.METHOD_FOCUS
Component.METHOD_FOCUS,
Component.METHOD_TALKBACK_FOCUS,
Component.METHOD_TALKBACK_ANNOUNCE
})
public class Div extends Container<PercentFlexboxLayout> {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@
Component.METHOD_TO_TEMP_FILE_PATH,
Component.METHOD_FOCUS,
Image.METHOD_START_ANIMATION,
Image.METHOD_STOP_ANIMAION
Image.METHOD_STOP_ANIMAION,
Component.METHOD_TALKBACK_FOCUS,
Component.METHOD_TALKBACK_ANNOUNCE
}
)
public class Image extends Component<FlexImageView> implements Autoplay, InnerSpannable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@
Component.METHOD_ANIMATE,
Component.METHOD_TO_TEMP_FILE_PATH,
Component.METHOD_FOCUS,
Component.METHOD_GET_BOUNDING_CLIENT_RECT
Component.METHOD_GET_BOUNDING_CLIENT_RECT,
Component.METHOD_TALKBACK_FOCUS,
Component.METHOD_TALKBACK_ANNOUNCE
})
public class Popup extends Container<PercentFlexboxLayout> implements Floating {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@
Component.METHOD_ANIMATE,
Component.METHOD_GET_BOUNDING_CLIENT_RECT,
Component.METHOD_TO_TEMP_FILE_PATH,
Component.METHOD_FOCUS
Component.METHOD_FOCUS,
Component.METHOD_TALKBACK_FOCUS,
Component.METHOD_TALKBACK_ANNOUNCE
})
public class Rating extends Component<HapRatingBar> implements SwipeObserver {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@
ReaderDiv.METHOD_PRELOAD_CONTENT,
ReaderDiv.METHOD_SET_PAGE_LINE_SPACE,
ReaderDiv.METHOD_SET_PAGE_COLOR,
ReaderDiv.METHOD_GET_PAGE_CONTENT
ReaderDiv.METHOD_GET_PAGE_CONTENT,
Component.METHOD_TALKBACK_FOCUS,
Component.METHOD_TALKBACK_ANNOUNCE
}
)
public class ReaderDiv extends Container<ReaderLayoutView> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@
Component.METHOD_ANIMATE,
Component.METHOD_GET_BOUNDING_CLIENT_RECT,
Component.METHOD_TO_TEMP_FILE_PATH,
Component.METHOD_FOCUS
Component.METHOD_FOCUS,
Component.METHOD_TALKBACK_FOCUS,
Component.METHOD_TALKBACK_ANNOUNCE
})
public class Refresh extends Container<HapRefreshLayout> {

Expand Down
Loading

0 comments on commit 90d388e

Please sign in to comment.