【问题标题】:How to set accessibility to circles drawn using Canvas?如何设置使用 Canvas 绘制的圆圈的可访问性?
【发布时间】:2017-09-20 00:48:53
【问题描述】:

我有一个自定义视图,我在 Android 中使用画布绘制 6 个圆圈。这些圆圈充当页面指示器;这意味着单击每个圆圈(使用画布绘制)时,不同的项目将显示在视图寻呼机中。现在我的要求是为每个圈子设置单独的焦点,并为每个圈子设置不同的可访问性。请帮忙。提前致谢。 谢谢, 拉克什

【问题讨论】:

  • 你必须在 TouchListener 上使用并在触摸后获取坐标,并将这些坐标与它们的圆圈是否包含相匹配。
  • @Bansal,我已经做到了。 Touchlistener 工作正常。现在我的要求是如何为我绘制的各个圆圈设置可访问性。
  • """并为每个人设置不同的可访问性""" accessibility 是什么意思?与this相关的东西?
  • @pskink,请参考:developer.android.com/guide/topics/ui/accessibility/apps.html 这就是我所说的可访问性。当手机中的 TalkBack 功能打开时,我需要将焦点转到每个圆圈(使用画布绘制)并说出我设置为 contectDescription 的文本。
  • 所以如果你在Canvas上画你的圈子那么我假设你有你的自定义视图,所以请阅读this

标签: android accessibility


【解决方案1】:

正如@alanv 和@pskink 在评论中解释的那样,我必须使用 ExploreByTouchHelper 来实现我的要求。

https://youtu.be/ld7kZRpMGb8?t=1196

谢谢大家!

【讨论】:

  • 你是救命稻草
  • ExploreByTouchHelper 类是否也适用于外部键盘 DPAD 事件?
【解决方案2】:

您应该使用 View.getX() 和 View.getY() 获取视图的位置以获取左上角的 x 和 y 并假设您知道半径(或能够获得视图的宽度/高度确定半径)。之后,获取:

xTouch = MotionEvent.getX();
yTouch = MotionEvent.getY();

然后检查条件如果:

     (xTouch - (x + radius)) * (xTouch - (x + radius)) + (yTouch - (y + radius)) * (yTouch - (y + radius)) <= radius * radius

该公式只是对学校几何形状的解释,用于确定点是否在圆形区域内。更多细节请参考笛卡尔坐标的圆方程。

数值解释是:

(x + radius) 和 (y + radius) 是圆心。

(xTouch - (x + radius)) 是触摸点到中心 X 的距离。

(yTouch - (y + radius)) 是触摸点到中心的 Y 距离。

对于每个圈子的可访问性和要读取的可访问性文本,如果 TackBack 已打开,那么完整场景的代码是:

package com.example.hello_world;

import java.util.Locale;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.RectF;
import android.graphics.Region;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity implements OnInitListener {
    String mText_To_Speach_text;
    private int MY_DATA_CHECK_CODE = 0;
    TextToSpeech myTTS;
    int initStatus = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new MyView(this));

        Intent checkTTSIntent = new Intent();
        checkTTSIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
        startActivityForResult(checkTTSIntent, MY_DATA_CHECK_CODE);
    }

    class MyView extends View {

        private Path mPath, mPath2, mPath3, mPath4, mPath5;
        private Paint mPaint;
        private RectF mOval, mOval2;
        Region mRegion1, mRegion2, mRegion3, mRegion4, mRegion5, mRegion6;

        public MyView(Context context) {
            super(context);
            mPath = new Path();
            mPath2 = new Path();
            mPath3 = new Path();
            mPath4 = new Path();
            mPath5 = new Path();
            mPaint = new Paint();
            mPaint.setColor(0xffff0000);
        }

        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            mPath.reset();
            mPath.addCircle((w / 2) - 120, h / 2, 30, Direction.CW);
            mPath.close();

            mPath2.reset();
            mPath2.addCircle((w / 2) - 60, h / 2, 30, Direction.CW);
            mPath2.close();

            mPath3.reset();
            mPath3.addCircle(w / 2, h / 2, 30, Direction.CW);
            mPath3.close();

            mPath4.reset();
            mPath4.addCircle((w / 2) + 60, h / 2, 30, Direction.CW);
            mPath4.close();

            mPath5.reset();
            mPath5.addCircle((w / 2) + 120, h / 2, 30, Direction.CW);
            mPath5.close();

        }

        @Override
        protected void onDraw(Canvas canvas) {
            canvas.drawColor(0xffffffff);

            mPaint.setStyle(Style.FILL);
            canvas.drawPath(mPath, mPaint);
            canvas.drawPath(mPath2, mPaint);
            canvas.drawPath(mPath3, mPaint);
            canvas.drawPath(mPath4, mPaint);
            canvas.drawPath(mPath5, mPaint);

            RectF rectF1 = new RectF();
            mPath.computeBounds(rectF1, true);
            mRegion1 = new Region();
            mRegion1.setPath(mPath, new Region((int) rectF1.left,
                    (int) rectF1.top, (int) rectF1.right, (int) rectF1.bottom));

            RectF rectF2 = new RectF();
            mPath2.computeBounds(rectF2, true);
            mRegion2 = new Region();
            mRegion2.setPath(mPath2, new Region((int) rectF2.left,
                    (int) rectF2.top, (int) rectF2.right, (int) rectF2.bottom));

            RectF rectF3 = new RectF();
            mPath3.computeBounds(rectF3, true);
            mRegion3 = new Region();
            mRegion3.setPath(mPath3, new Region((int) rectF3.left,
                    (int) rectF3.top, (int) rectF3.right, (int) rectF3.bottom));

            RectF rectF4 = new RectF();
            mPath4.computeBounds(rectF4, true);
            mRegion4 = new Region();
            mRegion4.setPath(mPath4, new Region((int) rectF4.left,
                    (int) rectF4.top, (int) rectF4.right, (int) rectF4.bottom));

            RectF rectF5 = new RectF();
            mPath5.computeBounds(rectF5, true);
            mRegion5 = new Region();
            mRegion5.setPath(mPath5, new Region((int) rectF5.left,
                    (int) rectF5.top, (int) rectF5.right, (int) rectF5.bottom));

        }

        @Override
        public boolean onTouchEvent(MotionEvent event) {
            int x = (int) event.getX();
            int y = (int) event.getY();

            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                if (mRegion1.contains(x, y)) {
                    mText_To_Speach_text = "Circle1";
                    speakWords(mText_To_Speach_text);
                } else if (mRegion2.contains(x, y)) {
                    mText_To_Speach_text = "Circle2";
                    speakWords(mText_To_Speach_text);
                } else if (mRegion3.contains(x, y)) {
                    mText_To_Speach_text = "Circle3";
                    speakWords(mText_To_Speach_text);
                } else if (mRegion4.contains(x, y)) {
                    mText_To_Speach_text = "Circle4";
                    speakWords(mText_To_Speach_text);
                } else if (mRegion5.contains(x, y)) {
                    mText_To_Speach_text = "Circle5";
                    speakWords(mText_To_Speach_text);
                }
            }
            return true;
        }
    }

    private void speakWords(String speech) {
        myTTS.speak(speech, TextToSpeech.QUEUE_FLUSH, null);
    }

    @Override
    public void onInit(int status) {
        if (initStatus == TextToSpeech.SUCCESS) {
            if (myTTS.isLanguageAvailable(Locale.US) == TextToSpeech.LANG_AVAILABLE)
                myTTS.setLanguage(Locale.US);
        } else if (initStatus == TextToSpeech.ERROR) {
            Toast.makeText(this, "Sorry! Text To Speech failed...",
                    Toast.LENGTH_LONG).show();
        }

    }

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == MY_DATA_CHECK_CODE) {
            if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
                myTTS = new TextToSpeech(this, this);
            } else {
                Intent installTTSIntent = new Intent();
                installTTSIntent
                        .setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
                startActivity(installTTSIntent);
            }
        }
    }

}

【讨论】:

  • onTouch 工作正常。现在,我需要在 Android 设备中打开 TalkBack 时可以访问这些圈子。谢谢!
  • 我这里的要求是实现可访问性。 (请参阅developer.android.com/guide/topics/ui/accessibility/apps.html)。我有一个视图,我正在使用画布绘制 6 个圆圈。如上所述,这 6 个圆圈中的每一个都有 onTouch。现在我的要求是当我在手机中打开 TalkBack 时,当用户点击一个特定的圈子时,我需要将焦点设置在该圈子上并读出它的辅助功能文本。我如何实现这一目标?以及如何为使用画布绘制的每个圆圈设置可访问性文本?
  • k @RAkeshH 我明白了你的意思,请给我一些时间,我正在处理你的问题。所以很快就会在这里见到你。。
  • 谢谢哥们。我在等你的帮助:)
  • @RakeshH 我已经回答了您的需求:virtual view hierarchy
猜你喜欢
  • 1970-01-01
  • 2014-07-03
  • 2013-03-19
  • 2014-09-25
  • 1970-01-01
  • 1970-01-01
  • 2015-04-08
  • 1970-01-01
  • 2016-08-30
相关资源
最近更新 更多