I have a custom view where in I'm drawing 6 circles using canvas in Android. Those circles act as Page indicators; which means that on the click of each circle (drawn using canvas), the different items are being displayed in a view pager. Now my requirement is to set individual focus to each circles and set different accessibility to each one. Please help. Thanks in advance. Thanks, Rakesh
-
You have to use on TouchListener and get cordinate after touch, and match these cordinates to them circle contains or not. – D.J Sep 26 '16 at 09:15
-
@Bansal, I have done that. Touchlistener works fine. Now my requirement is how to set accessibility to individual circles which I have drawn. – Rakesh Sep 26 '16 at 09:23
-
"""and set different accessibility to each one""" what do you mean by `accessibility` here? something related to [this](https://developer.android.com/guide/topics/ui/accessibility/index.html)? – pskink Sep 26 '16 at 09:26
-
@pskink, Please refer this : https://developer.android.com/guide/topics/ui/accessibility/apps.html This is what I meant by accessibility. When TalkBack feature is turned ON in the phone, I need the focus to go to each circle (drawn using canvas) and speak out the text which I set as contectDescription. – Rakesh Sep 26 '16 at 09:33
-
so if you are drawing your circles on the `Canvas` then i assume you have your custom view, so read [this](https://developer.android.com/guide/topics/ui/accessibility/apps.html#custom-views) – pskink Sep 26 '16 at 09:34
-
@pskink, I have gone through this. When I tried this, I could only set the accessibility to the whole view, which contains all the 6 circles drawn using canvas. How do I set accessibility to the individual circles and gain individual focus? – Rakesh Sep 26 '16 at 09:39
-
how do you want to gain individual focus? are you using directional controller clicks? – pskink Sep 26 '16 at 09:57
-
@pskink , When you turn ON TalkBack in your device, you would be able to traverse through all of the actionable items in your phone. Eg: buttons, EditText etc. When the focus reaches each widget, it's contentDescription would be read out. Likewise I need those circles to be individually accessed with talkBack ON in the device. Please help! – Rakesh Sep 26 '16 at 10:00
-
if you want such "virtual" regions in your view them read: https://developer.android.com/guide/topics/ui/accessibility/apps.html#virtual-hierarchy – pskink Sep 26 '16 at 11:44
-
You can use `ExploreByTouchHelper`. See the answer at http://stackoverflow.com/questions/24065375/how-to-do-android-accessibility-for-custom-viewgroups. – alanv Sep 26 '16 at 20:58
-
@alanv Do you happen to have a sample code or snippet to set accessibility to something which is drawn using canvas? – Rakesh Sep 27 '16 at 03:45
-
indeed, `ExploreByTouchHelper` is muuuuch more easier then using the low level accessibility API: its enough to implement 3 simple methods... `getVisibleVirtualViews`, `onPopulateNodeForVirtualView` and `getVirtualViewAt` – pskink Sep 28 '16 at 10:35
-
@pskink Ok. I'll try it out. – Rakesh Sep 28 '16 at 12:30
-
@alanv, It works like a charm buddy. Thanks for your help :) – Rakesh Oct 03 '16 at 06:10
-
@pskink, ExploreByTouchHelper does work. Thanks for your help man :) – Rakesh Oct 03 '16 at 06:10
2 Answers
I had to use ExploreByTouchHelper to achieve my requirement as explained by @alanv and @pskink in the comment.
https://youtu.be/ld7kZRpMGb8?t=1196
Thanks guys!
-
-
Does ExploreByTouchHelper class also work with External Keyboard DPAD events ? – Karan Sharma Jun 02 '21 at 02:56
You should take position of the view with View.getX() and View.getY() to get x and y of the upper left corner and also assuming You know the radius (or able to obtain width/height of the view to determine radius). After that, obtain :
xTouch = MotionEvent.getX();
yTouch = MotionEvent.getY();
Then check the condition if:
(xTouch - (x + radius)) * (xTouch - (x + radius)) + (yTouch - (y + radius)) * (yTouch - (y + radius)) <= radius * radius
The formula is just interpretation of schools geometry for determining if dot is inside circle area or not. Refer to circle equation for Cartesian coordinates for more details.
Values explanation is:
(x + radius) and (y + radius) is the center of circle.
(xTouch - (x + radius)) is distance from touch point to center by X.
(yTouch - (y + radius)) is distance from touch point to center by Y.
for the accessibility of the each circle and the accessibility text to be read it out if the TackBack is turned on then so the code for the complete scenario is:
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);
}
}
}
}

- 151
- 1
- 8
-
onTouch works fine. Now I need each of those circles to be accessible when TalkBack is turned ON in Android device.Thanks! – Rakesh Sep 26 '16 at 09:42
-
My requirement here is to achieve accessibility. (Refer https://developer.android.com/guide/topics/ui/accessibility/apps.html). I have a view where in I'm drawing 6 circles using canvas. Each of these 6 circles has onTouch as you mentioned above. Now my requirement is when I turn on TalkBack in the phone, when the user clicks on a particular circle, I need to set a focus to that circle and read out its accessibility text. How do I achieve this? And How do I set accessibility text to each of these circles drawn using canvas? – Rakesh Sep 26 '16 at 11:39
-
k @RAkeshH i got your point and just give me some time i am working on your pronblem only.. so see you soon at here.. – kishan sahu Sep 26 '16 at 11:45
-
-
@RakeshH i already answered what you need: [virtual view hierarchy](https://developer.android.com/guide/topics/ui/accessibility/apps.html#virtual-hierarchy) – pskink Sep 26 '16 at 12:55
-
@pskink, Can you please provide a code snippet? In my view, I'm drawing circles like: canvas.drawcircle(....). Can you please hint me how to set accessibility for these custom circles? – Rakesh Sep 26 '16 at 13:16
-
@pskink, In the sample activity, they're just asking us to do what needs to be done when that view is clicked. – Rakesh Sep 27 '16 at 03:48
-
Hii @RakeshH i got the solution for your querry so check my code i had updated the code – kishan sahu Sep 27 '16 at 05:00
-
-
@RakeshH just look at to the code i had posted and tell me that is it full filled your requirement or not – kishan sahu Sep 27 '16 at 06:17
-
@kishansahu, The above doesn't help in getting the focus to each circles. – Rakesh Sep 28 '16 at 12:30
-
@kishansahu, I had to use ExplpreByTouchHelper to attain focus. Thanks a lot for your help :) – Rakesh Oct 03 '16 at 11:12