Search code examples
androidandroid-layouttouchrotationondraw

Trying to rotate a layout in android, canvas does not appear to rotate


I've taken the tutorial here (which dynamically rotates an image on touch/fling) and tried to refactor it with a whole layout instead of just one image, so I've changed the rotateDialer() method from the TutorialActivity like so:

private void rotateDialer(float degrees) {
    //matrix.postRotate(degrees, dialerWidth / 2, dialerHeight / 2);
    //dialer.setImageMatrix(matrix);
    dialer.setNextRotation(degrees, dialerWidth / 2, dialerHeight  / 2);
    dialer.invalidate();
    info.setText("Current Quadrant Touched = "+currentQuadrantTouched
            +"\nAngle = "+degrees);
}

where dialer is a custom layout I've created with an overridden onDraw() method that rotates the canvas however many degrees set in the setNextRotation() method, but the canvas does not appear to rotate! Here is my custom layout:

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RelativeLayout;

public class DialView extends FrameLayout {
public static final String LOG_TAG = "DialView";
RelativeLayout dialView;
float degrees;
float px;
float py;

public DialView(Context context) {
    super(context);
    init();
    // TODO Auto-generated constructor stub
}

public DialView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
    // TODO Auto-generated constructor stub
}
public DialView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    // TODO Auto-generated constructor stub
    init();
}


private void init()
{
    //initialise rotation
    this.degrees = 0;
    this.px = 0;
    this.py = 0;
    LayoutInflater inflator = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    dialView = (RelativeLayout) inflator.inflate(R.layout.dial_view, this,false);
    addView(dialView);
    Log.d(LOG_TAG, "DialView: init() "+ degrees+"degrees around ("+getWidth() / 2+","+getHeight() / 2+")");

}



public void setNextRotation(float degrees, float px, float py)
{
    this.degrees = degrees;
    this.px = px;
    this.py = py;
    Log.d(LOG_TAG, "Next Rotation = "+ degrees+"degrees around ("+px+","+py+")");
}

@Override
protected void onDraw(Canvas canvas) {
    canvas.save();
    // canvas.rotate(45,<appropriate x pivot value>,<appropriate y pivot value>);
     canvas.rotate(degrees, px, py);
     Log.d(LOG_TAG, "onDraw: Rotation = "+ degrees+"degrees around ("+px+","+py+")");
     super.onDraw(canvas);
     canvas.restore();

}


}

this is the dial_view.xml:

<ImageView
    android:id="@+id/topLeftImage"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"
    android:layout_marginLeft="38dp"
    android:clickable="true"
    android:layout_marginTop="28dp"
    android:src="@drawable/icon" />

<ImageView
    android:id="@+id/topRightImage"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:clickable="true"
    android:layout_alignParentRight="true"
    android:layout_marginRight="50dp"
    android:src="@drawable/icon" />

<ImageView
    android:id="@+id/bottomLeftImage"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:clickable="true"
    android:layout_marginBottom="24dp"
    android:layout_marginLeft="22dp"
    android:src="@drawable/icon" />

<ImageView
    android:id="@+id/bottomRightImage"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:clickable="true"
    android:layout_alignParentRight="true"
    android:layout_marginRight="28dp"
    android:src="@drawable/icon" />

</RelativeLayout>

Why does the canvas not visibly rotate? I'm invalidating the dialler in onTouch() after the calculation of the degrees, and the calculation is working correctly (I'm getting changing values in the log) but the view just doesn't seem to be rotating, what am I doing wrong?


Solution

  • Ok it turns out the onDraw() method was never being called, I just simply had to add

    setWillNotDraw(false)
    

    to my init() function and hey presto the onDraw() method is being called, and my view is rotating!!!!