How can i change text rotation in Luck Wheel (Android) - android

Here the link of GitHub Code https://github.com/thanhniencung/LuckyWheel
I try to change the rotation of canvas using this piece of code
private void drawText(Canvas canvas, float tmpAngle, float sweepAngle, String mStr) {
Path path = new Path();
path.addArc(mRange,tmpAngle,sweepAngle);
float textWidth = mTextPaint.measureText(mStr);
int hOffset = (int) (mRadius * Math.PI / mLuckyItemList.size()/2-textWidth/2);
int vOffset = mRadius/2/4;
canvas.drawTextOnPath(mStr, path, hOffset, vOffset, mTextPaint);
}
I want to change orientation of text like picture shown below

In the latest version of the LuckyWheel, when initialising LuckyItems data, you can set the values for luckyItem.secondaryText instead of luckyItem.topText, and you will have the wanted text orientation.
Like this:
List<LuckyItem> data = new ArrayList<>();
for (int i = 0; i < sectorsTitles.length; i++) {
LuckyItem luckyItem = new LuckyItem();
// luckyItem.topText = sectorsTitles[i]; // Don't use this
luckyItem.secondaryText = sectorsTitles[i]; // Use this instead
luckyItem.color = Color.parseColor(ROULETTE_COLORS[i]);
data.add(luckyItem);
}
luckyWheelView.setData(data);

In XML code you can change the rotation by using
android:rotation="120" (Then any angle you want positive or negative)
But, you may need to rotate this image when it is in the bottom and then rotate it again when it is in the top. So you can rotate it programatically whenever you want.
TextView textView = findViewById(R.id.textView);
ImageView imageView = findViewById(R.id.imageView);
textView.setRotation(120);
imageView.setRotation(120);
And then if you want to comeback it latter to the position it was in the beginning. You just add the negative sign.
textView.setRotation(-120);
imageView.setRotation(-120);
Of course, the angle is up to you.

Related

How to set LineSpacing programmatically?

i am new to Android Studio . I want to increase or decrease textView's line spacing on click. currently i am using this one and it works but i want when user click + than line spacing increased and decreased for - .
here is my code.
textView.setLineSpacing(0,1.1f);
i have tried this but not works
private int textSpace = (int) 1.0f;
private int diff = (int) 0.1f;
and than this
textSize = textSpace+diff;
textView.setLineSpacing(0,textSize);
same for minus, but its not working , please help
Here is a checked example. I hope everything is well described
// Here put ids of your views
TextView textView = findViewById(R.id.textView);
Button plusButton = findViewById(R.id.plus);
Button minusButton = findViewById(R.id.minus);
// The multiplier may be unchanged
final float multiplier = textView.getLineSpacingMultiplier();
// Set the appropriate offset
final float offset = 1f;
plusButton.setOnClickListener(view -> textView.setLineSpacing(textView.getLineSpacingExtra() + offset, multiplier));
minusButton.setOnClickListener(view -> textView.setLineSpacing(textView.getLineSpacingExtra() - offset, multiplier));
I suppose you want to achieve something like this:
private int textSize = 20;
button.setOnClickListerner {
textSize += diff;
textView.setLineSpacing(0, textSize);
}

draw Canvas multiple times - best practice

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.

Fix text mirroring on rear view of Object3D

My Class extends Renderer(org.rajawali3d.renderer.Renderer)
Following function in the class is called from activity :
public void makeText(float[] openGLPpoint, int color, String text,float depth)
{
double adjust_angle_o = 0;
Material mSphereMaterial = new Material();
Bitmap bitmap= setTextInImage(text);
Texture t = new Texture("text",bitmap);
mSphereMaterial.addTexture(t);
Object3D object3D = new Plane(0.3f,0.1f,100,100);
object3D.setMaterial(mSphereMaterial);
object3D.setDoubleSided(true);
object3D.setColor(color);
if(!depth >= 1)
{
adjust_angle_o = 0.2;
}
object3D.setPosition(openGLPpoint[0],
openGLPpoint[1],
openGLPpoint[2]-adjust_angle_o);
getCurrentScene().addChild(object3D);
}
public Bitmap setTextInImage(String text){
Bitmap src =
BitmapFactory.decodeResource(mContext.getResources(),R.drawable.label_bg_sm);
Bitmap dest =
Bitmap.createBitmap(src.getWidth(),
src.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas cs = new Canvas(dest);
Paint tPaint = new Paint();
tPaint.setTextSize(50 * mContext.getResources().getDisplayMetrics().density);
tPaint.setColor(Color.GREEN);
tPaint.setStyle(Paint.Style.FILL_AND_STROKE);
tPaint.setFakeBoldText(true);
cs.drawBitmap(src, 0f, 0f, null);
float height = tPaint.measureText("yY");
float width_o = tPaint.measureText(text+" m");
float x_coord = (src.getWidth() - width_o)/2;
// 15f is to put space between top edge and the text
cs.drawText(text+" m", x_coord, height+15f, tPaint);
return dest;
}
I need the factor object3D.setDoubleSided(true); , which is working fine .
The text is correct when seen from front view but when the object is seen from the rear side , the text naturally mirrors .
Following is a snap :
Mirrored text observed from rear view
How can the text be corrected , as it should be readable from both front and rear views ? Any articles to fix text-mirroring ?
I figured it out , object3D.setDoubleSided(false) created a duplicate object and rotated it 180 at y axis . It worked fine now .
Edit : The rotated side is showing dark then the original . Increasing alpha isnt working. Can anyone guide futher ?

Drawing a Heart with Sharp Corner in Android

The following question might sound a bit stupid but I guess stupidity has no limit so here it goes. I am drawing a Heart using Canvas in Android and have got no issues in drawing the heart but I am not able to make the heart sharp in the meeting point. My heart looks like
CODE :
left_x_moveto = 200;
left_y_moveto = 45;
left_x1 = 197;
left_y1 = -35;
left_x2 = 60;
left_y2 = 20;
left_x3 = 193;
left_y3 = 130;
right_x_moveto = 200;
right_y_moveto = 45;
right_x1 = 197;
right_y1 = -35;
right_x2 = 345;
right_y2 = 20;
right_x3 = 193;
right_y3 = 130;
heart_outline_paint.setColor(getResources().getColor(R.color.heart_outline_color)); // Change the boundary color
heart_outline_paint.setStrokeWidth(15);
heart_outline_paint.setStyle(Paint.Style.STROKE);
path.moveTo(left_x_moveto, left_y_moveto);
path.cubicTo(left_x1, left_y1, left_x2, left_y2, left_x3, left_y3);
path.moveTo(right_x_moveto, right_y_moveto);
path.cubicTo(right_x1, right_y1, right_x2, right_y2, right_x3, right_y3);
canvas.drawPath(path, heart_outline_paint);
What have I tried so far :
Reducing or increasing the points of left_x_moveto,left_y_moveto and vice versa but the heart is completely disfigured for which I am unable to find the reason.
When the right_x_moveto = 198 and right_y_moveto = 45, the heart looks like
I am not sure why this is happening.
Reducing the width of the heart_outline_paint would give me what I want but I want the thickness of the heart to be the same so reducing the setStrokeWidth is not an option.
In short, I want both the curves to MEET AND MERGE and not just MEET.
Any help will be much appreciated. Thanks in advance.
You need to perform a couple of this.
Close the path via path.close().
You need to set the stroke join via heart_outline_paint.setStrokeJoin(Paint.Join.MITER);
A path can be closed only if it's drawn continuously. Hence I have modified the code so that path.close() can be done properly. Below is the code.
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
heart_outline_paint = new Paint(Paint.ANTI_ALIAS_FLAG);
heart_outline_paint.setStrokeJoin(Paint.Join.MITER);
path = new Path();
int left_x_moveto = 200;
int left_y_moveto = 45;
int left_x1 = 180;
int left_y1 = -20;
int left_x2 = 30;
int left_y2 = 20;
int left_x3 = 193;
int left_y3 = 130;
int right_x_moveto = 200;
int right_y_moveto = 45;
int right_x1 = 214;
int right_y1 = -20;
int right_x2 = 375;
int right_y2 = 20;
int right_x3 = 193;
int right_y3 = 130;
heart_outline_paint.setColor(Color.RED); // Change the boundary color
heart_outline_paint.setStrokeWidth(15);
heart_outline_paint.setStyle(Paint.Style.STROKE);
path.moveTo(left_x_moveto, left_y_moveto);
path.cubicTo(left_x1, left_y1, left_x2, left_y2, left_x3, left_y3);
path.cubicTo(right_x2, right_y2, right_x1, right_y1, right_x_moveto, right_y_moveto);
path.close();
canvas.drawPath(path, heart_outline_paint);
}
Paint.Join.MITER is the one that does what you want.
The outer edges of a join meet at a sharp angle
Now this MITER join works only when the angle is <= 90 degree. But here, based on the values that you have provided, the angle is 90 degree and hence the MITER join doesn't work. I have modified the values to get the following image. The image is not exact, but you need to play around with the value the get the right one.
You could set the ROUND join method to get the following.
The problem is with Path.cubicTo(). It's very hard to get the MITTER join work without getting the heart shape squished. So instead of cubicTo, I tried with lineTo and arcTo to create a simple heart. The below is the code for that. You will notice that I have rotated the canvas to 45 degrees and then drew the heart shape. This is purely for convenience, so that the coordinates are simple and does not involve pythagoras theorem.
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
heart_outline_paint = new Paint(Paint.ANTI_ALIAS_FLAG);
heart_outline_paint.setStrokeJoin(Paint.Join.MITER);
heart_outline_paint.setColor(Color.RED); // Change the boundary color
heart_outline_paint.setStrokeWidth(15);
heart_outline_paint.setStyle(Paint.Style.STROKE);
path = new Path();
float length = 100;
float x = canvas.getWidth()/2;
float y = canvas.getHeight()/2;
canvas.rotate(45,x,y);
path.moveTo(x,y);
path.lineTo(x-length, y);
path.arcTo(new RectF(x-length-(length/2),y-length,x-(length/2),y),90,180);
path.arcTo(new RectF(x-length,y-length-(length/2),x,y-(length/2)),180,180);
path.lineTo(x,y);
path.close();
canvas.drawPath(path, heart_outline_paint);
}
The final rendered image of this code is below:
What's happening is that the thickness of the line is being drawn on one side, not on both. In true MS paint fashion:
(The left is what's happening, the right is what you want. Black is the actual position of the line would width be 1px, red is the "padding", the 2nd, 3rd through 15th pixel, heart_outline_paint.setStrokeWidth(15);)
To fix this, try to subtract half the width of the line from the x of right line, and add it to the x of the left line. Doing so will work around this problem, not fix it

Set button textSize as large as possible without enlarging the button background in android

I would like to set the textSize of my button's text to be as large as possible but limit it in a way that will not change my button dimension which is equal to the resource file.
Do you know any way to achieve it?
May this helps you
// Determine Scaled Density for later calculations
Display dd = ((Activity) m_Context).getWindowManager().getDefaultDisplay();
DisplayMetrics dm = new DisplayMetrics();
dd.getMetrics(dm);
float m_ScaledDensity = dm.scaledDensity;
Rect bounds = new Rect();
Paint p = new Paint();
p.setTypeface(btn.getTypeface());
// W is a very wide character
String sample = "NeedsToFIt"
int maxFont;
for (maxFont= 1
; -bounds.top <= btn.getHeight() && bounds.right <= btn.getWidth()
; maxFont++) {
p.setTextSize(maxFont);
p.getTextBounds(sample, 0, sample.length(), bounds);
}
maxFont = (int) ((maxFont - 1) / m_ScaledDensity);
btn.setTextSize(maxFont);
you can use Auto scale textview for that.

Categories

Resources