Skip to content

Instantly share code, notes, and snippets.

@robUx4
Last active December 28, 2015 18:29
Show Gist options
  • Save robUx4/7543300 to your computer and use it in GitHub Desktop.
Save robUx4/7543300 to your computer and use it in GitHub Desktop.
OrientationDrawable: a Drawable that handles orientation changes without allocating anything updated with a fix when a Matrix is already applied in the canvas
/*
* Copyright (C) 2013 LevelUp Studio
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.levelup.touiteur.pictures;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.drawable.Drawable;
/**
* A {@link android.graphics.drawable.Drawable Drawable} that handles an {@link OrientationDrawable.Orientation Orientation}
* change without allocating anything
*/
public class OrientationDrawable extends Drawable implements Drawable.Callback {
private final Drawable mDrawable;
private Orientation orientation = Orientation.NORMAL;
public enum Orientation {
NORMAL,
ROTATE_90,
ROTATE_180,
ROTATE_270
};
/**
* Wrap a {@link android.graphics.drawable.Drawable Drawable} to allow {@link OrientationDrawable.Orientation Orientation}
* changes
*
* @param drawable wrapped {@code Drawable}
*/
public OrientationDrawable(Drawable drawable) {
this.mDrawable = drawable;
mDrawable.setCallback(this);
}
/**
* Set the {@link OrientationDrawable.Orientation Orientation} to use to layout and display the wrapped
* {@link android.graphics.drawable.Drawable Drawable}
*
* @param orientation
* @return the {@code OrientationDrawable} that was modified
*/
public OrientationDrawable setOrientation(Orientation orientation) {
if (this.orientation != orientation) {
this.orientation = orientation;
invalidateSelf();
}
return this;
}
@Override
public void setBounds(int left, int top, int right, int bottom) {
super.setBounds(left, top, right, bottom);
if (orientation == Orientation.ROTATE_90 || orientation == Orientation.ROTATE_270) {
int tmp = left;
left = top;
top = tmp;
tmp = right;
right = bottom;
bottom = tmp;
}
mDrawable.setBounds(left, top, right, bottom);
}
@Override
public boolean getPadding(Rect padding) {
return mDrawable.getPadding(padding);
}
@Override
public void draw(Canvas canvas) {
if (orientation == Orientation.NORMAL)
mDrawable.draw(canvas);
else {
Matrix m = new Matrix(canvas.getMatrix());
canvas.save();
switch (orientation) {
case ROTATE_90:
m.preRotate(90, mDrawable.getIntrinsicHeight()/2, mDrawable.getIntrinsicHeight()/2);
canvas.setMatrix(m);
break;
case ROTATE_180:
m.preRotate(180, mDrawable.getIntrinsicWidth()/2, mDrawable.getIntrinsicHeight()/2);
canvas.setMatrix(m);
break;
case ROTATE_270:
m.preRotate(-90, mDrawable.getIntrinsicWidth()/2, mDrawable.getIntrinsicWidth()/2);
canvas.setMatrix(m);
break;
default:
break;
}
mDrawable.draw(canvas);
canvas.restore();
}
}
@Override
public boolean isStateful() {
return mDrawable.isStateful();
}
@Override
public boolean setState(final int[] stateSet) {
return mDrawable.setState(stateSet);
}
@Override
public int[] getState() {
return mDrawable.getState();
}
@Override
public void jumpToCurrentState() {
mDrawable.jumpToCurrentState();
}
@Override
public Drawable getCurrent() {
return mDrawable.getCurrent();
}
@Override
public void setChangingConfigurations(int configs) {
mDrawable.setChangingConfigurations(configs);
}
@Override
public int getChangingConfigurations() {
return mDrawable.getChangingConfigurations();
}
@Override
public boolean setVisible(boolean visible, boolean restart) {
return super.setVisible(visible, restart) || mDrawable.setVisible(visible, restart);
}
@Override
public void setAlpha(int alpha) {
mDrawable.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter cf) {
mDrawable.setColorFilter(cf);
}
@Override
public int getOpacity() {
return mDrawable.getOpacity();
}
@Override
public Region getTransparentRegion() {
return mDrawable.getTransparentRegion();
}
@Override
public Drawable mutate() {
mDrawable.mutate();
return this;
}
@Override
public void setDither(boolean dither) {
mDrawable.setDither(dither);
}
@Override
public void setFilterBitmap(boolean filter) {
mDrawable.setFilterBitmap(filter);
}
public int getIntrinsicHeight() {
if (orientation == Orientation.ROTATE_90 || orientation == Orientation.ROTATE_270)
return mDrawable.getIntrinsicWidth();
return mDrawable.getIntrinsicHeight();
};
@Override
public int getIntrinsicWidth() {
if (orientation == Orientation.ROTATE_90 || orientation == Orientation.ROTATE_270)
return mDrawable.getIntrinsicHeight();
return mDrawable.getIntrinsicWidth();
}
@Override
public int getMinimumHeight() {
if (orientation == Orientation.ROTATE_90 || orientation == Orientation.ROTATE_270)
return mDrawable.getMinimumWidth();
return mDrawable.getMinimumHeight();
}
@Override
public int getMinimumWidth() {
if (orientation == Orientation.ROTATE_90 || orientation == Orientation.ROTATE_270)
return mDrawable.getMinimumHeight();
return mDrawable.getMinimumWidth();
}
@Override
public void invalidateDrawable(Drawable who) {
invalidateSelf();
}
@Override
public void scheduleDrawable(Drawable who, Runnable what, long when) {
scheduleSelf(what, when);
}
@Override
public void unscheduleDrawable(Drawable who, Runnable what) {
unscheduleSelf(what);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment