I'm still searching for the right way to draw on canvas multiple times.
Wished result: ImageView set to visible, show first text, then second instead of first, finally third instead of second. Each text is visible for half a second
Idea: paint canvas with setColor(Color.WHITE)
after each text, use synchronized block for setting backgroundcolor and text, use invalidate() with custom draw()
method
I tryed different ways, this is the current version of my code:
initializeStimulus()
- called in onCreate() of my Service
private void initializeStimulus(String stimulus) {
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
stimulusOverlay = new CustomImageView(this);
stimulusOverlay.setBackgroundColor(getResources().getColor(R.color.background_stimulus));
stimulusOverlay.setVisibility(View.VISIBLE);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT
);
// Position of stimuli in relation to screen size / 2
Point displaySize = new Point();
windowManager.getDefaultDisplay().getRealSize(displaySize);
int width = displaySize.x;
int height = displaySize.y;
params.x = 0;
params.y = 0;
windowManager.addView(stimulusOverlay, params);
imageBitmap = Bitmap.createBitmap((width/3)*2, height/5, Bitmap.Config.ARGB_8888);
p = new Paint();
Canvas canvas = new Canvas(imageBitmap);
p.setColor(Color.BLACK);
Typeface non_proportional_font = Typeface.createFromAsset(getAssets(), "fonts/luximr.ttf");
p.setTypeface(non_proportional_font);
float scale = getResources().getDisplayMetrics().density;
p.setTextSize(40 * scale);
fillTextPathArray();
stimulusOverlay.setImageBitmap(imageBitmap);
stimulusOverlay.draw(canvas);
}
private void fillTextPathArray(){
mTextPaths = new ArrayList<Path>(VOC_COUNT);
String[] text = new String[VOC_COUNT];
String stimulus = getStimulusFromPref(positionStimulus);
int stimulusLength = stimulus.length();
String masking = String.format("%0" + stimulusLength + "d", 0).replace('0', 'X');
text[0] = masking;
text[1] = stimulus;
text[2] = masking;
for (int i = 0; i < text.length; i++) {
Path path = new Path();
p.getTextPath(text[i], 0, masking.length(), imageBitmap.getWidth()/4, (imageBitmap.getHeight()/3)*2, path);
path.close(); // not required on 2.2/2.3 devices
mTextPaths.add(path);
}
}
This function made an ArrayList of paths, which I need to be displayed in the right order. So at the end, the user will be able to see my canvas changing from first text to second text to third text.
I started with tips like "redraw entire view" or "draw box with backgroundcolor over old text" (Android Canvas Drawing Text and Change Text afterwards), because canvas drawing couldn't be revesed. Didn't work out for me.
The big problem remains: the code runs through and everything will be shown in one canvas, one above the other. AND: Time delays like while loop or Thread.sleep(500)
didn't have any impact on the canvas. The result was the same: The code was running through - with the given time delay - and at the end everything was painted, not step by step (first, second, third).
I even tryed to draw each text in separate methods.
So I tryed to implement each given new Canvas, new Paint and even new View - nothing changed. At the end everything was drawn instead of step by step.
Currently I have my custom ImageView (CustomImageView
), where I'm working with the invalidate()
method while using a synchronized block.
private class CustomImageView extends AppCompatImageView {
private boolean stimulusVisible = false;
private int countStimuli = 0;
public CustomImageView(Context context) {
super(context);
}
@Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
if (!stimulusVisible) {
Object lock = new Object();
synchronized (lock) {
canvas.drawPath(mTextPaths.get(countStimuli), p);
stimulusVisible = true;
countStimuli++;
}
} else {
long startTime = System.currentTimeMillis();
while((System.currentTimeMillis()-startTime) < 500){}
canvas.drawColor(Color.CYAN);
stimulusVisible = false;
}
invalidate();
}
}
The while loop should stop everything for half a sec.
I really hope for your suppoert.
Is there a better way to implement this?
Am I missing something? I though invalidate()
would redraw the canvas but it didn't have an impact. I'm trying for 2 days now, please help.