Rotating an image around a specified point doesn't work! (Android) - android

I'm rotating an ImageView with postRotate(float degrees, float px, float py), setting px and py to a few differnt values including (0,0) and (imgView.getHeight(),imgView.getWidth()) but it refuses to rotate around any other point than the center. I'm wondering whether it's got anything to do with the fact that my gravity is center in the LinearLayout?
My layout:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center">
<ImageView
android:id="#+id/imageTraj"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="matrix"
android:src="#drawable/impactangle" />
How I'm rotating the image:
matrix.postRotate(degrees,imageView.getHeight(),imageView.getWidth());
imageView.setImageBitmap(Bitmap.createBitmap(imageScaled, 0, 0,
imageScaled.getWidth(), imageScaled.getHeight(), matrix, true));
PS I've noticed there are a few similar questions, but none of them have suitable answers.

I am using a custom ImageView where I set the angle rotation.
public class CompassImage extends ImageView {
private float angleRotation;
public CompassImage(Context context) {
super(context);
}
public CompassImage(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CompassImage(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setAngleRotation(float angleRotation) {
this.angleRotation = angleRotation;
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
Rect clipBounds = canvas.getClipBounds();
canvas.save();
canvas.rotate(angleRotation, clipBounds.exactCenterX(), clipBounds.exactCenterY());
super.onDraw(canvas);
canvas.restore();
}
}
If you play around with clipBounds you may find that helpful.

A slight "hack", you could probably adjust the image size using something like Paint.net or Gimp, depending on your OS. That would make the image appear to spin on another point. This solution would be pointless if you are planning on using a lot of images though. This is a spinning cube tutorial using opengl.

Related

Override Button to draw text upside down

How could I go about overriding the Button class to draw the text upside down? The formatting of other libraries I'm using screw up when the button itself it rotated, but I need the text flipped.
I'm not familiar with the onDraw method, and I'm not sure how I could make a subclass for this.
Any help is appreciated, thanks!
You can use the rotation attribute in your button something like this:
<Button
android:id="#+id/test_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="text button"
android:rotation="180"/>
Or if you prefer using a custom button, you can create it something like this:
public class FlippedTextButton extends Button {
public FlippedTextButton(Context context) {
super(context);
}
public FlippedTextButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FlippedTextButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.save();
float y = this.getHeight() / 2.0f;
float x = this.getWidth() / 2.0f;
canvas.rotate(180, x, y);
super.onDraw(canvas);
canvas.restore();
}
}
Then you can use it with:
<!-- Change to your class package name. -->
<com.example.flippedtext.FlippedTextButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Flipped text"/>
Here is the sample project on github: https://github.com/isnotmenow/FlippedText

Masking properties for Textview in android

I have a scrollView in my Activity,the background of scrollView is of multiple colours.
<ScrollView ---------->
<RelativeLayout -------------/>
</ScrollView>
To my RelativeLayout I have added Views dynamically.
inflated xml:
<RelativeLayout --------------android:background="some transparent image">
<TextView --------- ---------/>
</RelativeLayout>
I want my Text coloured to be same as Background colour. I have tried for the solution in many ways but could not succeed.
In iOS for achieving this they have used RSMaskedLabel (third party class), but I didn’t find anything similar to this in Android.
Still I didnt find any solution,can anyone help me please. I tried by using Bitmaps and Canvas but didnt worked for me.
Some guidelines how to achieve this with custom TextView:
Extend TextView component
Create Bitmap and Canvas where you draw background and text
Draw wanted background color into allocated Canvas(e.g. Color.argb(80, 255, 255, 255))
Draw the text with Paint having mode PorterDuffXfermode(Mode.CLEAR) (Remember: Only allocate Bitmap and Canvas once) since you draw it into Bitmap
Draw the Bitmap into TextViews canvas
Here is some sample code to get started with:
public class TransparentTextView extends TextView {
private Paint mTextPaint;
private Bitmap mBitmapToDraw;
public TransparentTextView(Context context) {
super(context);
setup();
}
public TransparentTextView(Context context, AttributeSet attrs) {
super(context, attrs);
setup();
}
public TransparentTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setup();
}
private void setup() {
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setTextSize(getTextSize());
mTextPaint.setStyle(Paint.Style.FILL);
mTextPaint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
}
#Override
protected void onDraw(Canvas canvas) {
if (mBitmapToDraw == null) {
mBitmapToDraw = Bitmap.createBitmap(getWidth(), getHeight(),
Bitmap.Config.ARGB_8888);
if (mBitmapToDraw != null) {
Canvas c = new Canvas(mBitmapToDraw);
c.drawColor(Color.argb(80, 255, 255, 255));
c.drawText(getText().toString(), getPaddingLeft(),
getPaddingTop(), mTextPaint);
}
}
if (mBitmapToDraw != null) {
canvas.drawBitmap(mBitmapToDraw, 0, 0, null);
} else {
super.onDraw(canvas);
}
}
}
If you are setting text dynamically, you will need to reset mBitmapToDraw in order to get it refreshed.

Mirror (flip) a View / ProgressBar

I have a custom built circular progress bar used for a seconds counter on a clock, which I'd like to flip, so that the clock is counting counter-clockwise.
Searching here for a solution, I found this:
Right to Left ProgressBar?
Which obviously works for a horizontal progress bar, but I can't simply rotate it 180 degrees, since that will just move the clock 180 degrees and it will still be ticking clockwise.
Is there any other way to mirror a ProgressBar, or any View?
Edit:
Just found "android:rotationY" and the programmatic equivalent, but this ideally needs to be for 2.2 and above..
I was able to flip ProgressBar simply with attribute scaleX in XML:
android:scaleX="-1"
This works for other View as well.
Extend ProgressBar in the same way you would for a horizontal progress bar, but in the onDraw method, flip the canvas rather than rotate it:
public class InverseProgressBar extends ProgressBar {
public InverseProgressBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public InverseProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public InverseProgressBar(Context context) {
super(context);
}
#Override
protected synchronized void onDraw(Canvas canvas) {
canvas.scale(-1f, 1f, super.getWidth() * 0.5f, super.getHeight() * 0.5f);
super.onDraw(canvas);
}
}
Yes. In newer versions of material design library, the circular progress bar can be mirrored:
in the layout with this attribute
app:indicatorDirectionCircular
or programmatically with this method
setIndicatorDirection()
Refer here for more info.

How can I mirror the whole display?

I want to be able to mirror my app so it can be viewed in the windshield of a vehicle.
My XML has several nested LinearLayouts, TextViews and ImageViews. Currently I'm transforming each one and although it is mirrored, the structure of the elements is not (what was at the top is now at the bottom).
I've been looking for days and so far have tried a couple of approaches that have failed.
An animation that uses a matrix to flip on the X axis kind of works, except that it either reverts back or it stays and doesn't update, which is no good for interacting with the app.
I just tried to create a custom LinearLayout extending the parent one, hoping that I could apply a Matrix in its onDraw() method but that gives me a blank screen (I had to set setWillNotDraw(false); to hit the onDraw()).
Well eventually I found a solution that works well for me (so far it's caused no issues for users).
My solution was to override dispatchDraw to scale the canvas in my custom LinearLayout. Then I just needed to flip the touch events by overriding dispatchTouchEvent:
public class CustomContainer extends LinearLayout {
public CustomContainer(Context context) {
super(context);
this.setWillNotDraw(false);
}
public CustomContainer(Context context, AttributeSet attrs) {
super(context, attrs);
this.setWillNotDraw(false);
}
public CustomContainer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.setWillNotDraw(false);
}
#Override
protected void dispatchDraw(Canvas canvas) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
// Flip the view canvas
if (MyHUDActivity.mHUDMode) canvas.scale(1,-1, getWidth(), getHeight()/2f);
super.dispatchDraw(canvas);
canvas.restore();
}
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
// If in HUD mode then flip the touch zones
if (MyHUDActivity.mHUDMode) event.setLocation(event.getX(), getHeight()-event.getY());
return super.dispatchTouchEvent(event);
}
}
You can use the new Animation api to deal with reverting back after the horizontal flip.

Android canvas issue

I am new to android. Now I generated two ImageView in my Android XML file. I want to use canvas to draw two circles in each view. But the problem is, how can I deal with the coordinates? How can I know the coordinates? And how can I center them? Thanks!
ImageViews are for displaying image files, normally. If you want to draw your view yourself, you create your own View and override the onDraw method. Here is a class that draws a big red circle inside itself:
public class CircleView extends View {
public CircleView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CircleView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CircleView(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
Paint red = new Paint();
red.setColor(0xffff0000);
int height = getHeight();
int width = getWidth();
int radius = width < height ? width/2 : height/2;
canvas.drawCircle(width/2, height/2, radius, red);
}
}
You cannnot draw cirlces in an ImageView. You can only draw a circle in a bitmap and apply that bitmap to an ImageView.
Or you can create custom views and draw directly on their canvas.
In both cases you need to find the size of these views after they are created. Then you will know the coordinates as the 0,0 starts in the top left corner.

Categories

Resources