জনপ্রিয় পোস্টসমূহ

শনিবার, ৯ জুন, ২০১২

Android PinchImage View Tutorial For Update 2.1 Supported





1/imageview.xml



<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:isScrollContainer="true"
    >
<com.droidbd.pinchlib.PinchImageView
android:id="@+id/image"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:scaleType="fitXY"
    android:adjustViewBounds="true"
    android:src="@drawable/ic_launcher"
    />
</RelativeLayout>






2/standard_image.xml




<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:isScrollContainer="true"
    >
<com.droidbd.pinchlib.PinchImageView  
android:id="@+id/image"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:scaleType="fitXY"
    android:adjustViewBounds="true"
    android:src="@drawable/ic_launcher"
    />
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:gesture-image="http://schemas.polites.com/android"
    android:id="@+id/layout"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" 
    android:background="#000000">
    
    <RelativeLayout
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/schedulebar"
               >
               
                 <Button
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Back"
                    android:textColor="#ffffff"
                    android:layout_marginLeft="5dip"
                    android:layout_centerVertical="true"
                    android:textSize="14sp"
                    android:background="@drawable/back_bttn"
                    android:onClick="setBackToEvent"
                    android:textStyle="bold" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Sign Up Page "
                    android:id="@+id/fulleventtitle"
                    android:textColor="#ffffff"
                    android:layout_centerInParent="true"
                    android:textSize="14sp"
                    android:textStyle="bold" />
                
                
                  <Button
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                 
                    android:textColor="#ffffff"
                    android:layout_marginRight="5dip"
                    android:layout_alignParentRight="true"
                    android:layout_centerVertical="true"
                    android:textSize="14sp"
                    android:background="@drawable/plusbutton"
                    android:onClick="openURL"
                    android:textStyle="bold" />
                  
                  
                  
            </RelativeLayout>
            
    <com.polites.android.GestureImageView
        android:id="@+id/image"
        android:layout_width="fill_parent"
    android:layout_height="fill_parent" 
    gesture-image:min-scale="0.75"
    gesture-image:max-scale="10.0"
    android:src="@drawable/ic_launcher"/>
</LinearLayout>




Pakage :com.polites.android

/*
 * Copyright (c) 2012 Jason Polites
 * 
 * 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.polites.android;

/**
 * @author Jason Polites
 * 
 */
public interface Animation {

/**
* Transforms the view.
* @param view
* @param diffTime
* @return true if this animation should remain active. False otherwise.
*/
public boolean update(GestureImageView view, long time);

}




/*
 * Copyright (c) 2012 Jason Polites
 * 
 * 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.polites.android;

/**
 * @author Jason Polites
 * 
 */
public class Animator extends Thread {

private final GestureImageView view;
private Animation animation;
private boolean running = false;
private boolean active = false;
private long lastTime = -1L;

public Animator(GestureImageView view, String threadName) {
super(threadName);
this.view = view;
}

@Override
public void run() {

running = true;

while (running) {

while (active && animation != null) {
final long time = System.currentTimeMillis();
active = animation.update(view, time - lastTime);
view.redraw();
lastTime = time;

while (active) {
try {
if (view.waitForDraw(32)) { // 30Htz
break;
}
} catch (final InterruptedException ignore) {
active = false;
}
}
}

synchronized (this) {
if (running) {
try {
wait();
} catch (final InterruptedException ignore) {
}
}
}
}
}

public synchronized void finish() {
running = false;
active = false;
notifyAll();
}

public void play(Animation transformer) {
if (active) {
cancel();
}
animation = transformer;

activate();
}

public synchronized void activate() {
lastTime = System.currentTimeMillis();
active = true;
notifyAll();
}

public void cancel() {
active = false;
}
}



/*
 * Copyright (c) 2012 Jason Polites
 * 
 * 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.polites.android;

/**
 * @author Jason Polites
 * 
 */
public class FlingAnimation implements Animation {

private float velocityX;
private float velocityY;

private float factor = 0.85f;

private final float threshold = 10;

private FlingAnimationListener listener;

/*
* (non-Javadoc)
* @see
* com.polites.android.Transformer#update(com.polites.android.GestureImageView
* , long)
*/
@Override
public boolean update(GestureImageView view, long time) {
final float seconds = time / 1000.0f;

final float dx = velocityX * seconds;
final float dy = velocityY * seconds;

velocityX *= factor;
velocityY *= factor;

final boolean active = Math.abs(velocityX) > threshold
&& Math.abs(velocityY) > threshold;

if (listener != null) {
listener.onMove(dx, dy);

if (!active) {
listener.onComplete();
}
}

return active;
}

public void setVelocityX(float velocityX) {
this.velocityX = velocityX;
}

public void setVelocityY(float velocityY) {
this.velocityY = velocityY;
}

public void setFactor(float factor) {
this.factor = factor;
}

public void setListener(FlingAnimationListener listener) {
this.listener = listener;
}
}


/*
 * Copyright (c) 2012 Jason Polites
 * 
 * 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.polites.android;

/**
 * @author Jason Polites
 * 
 */
public class FlingAnimation implements Animation {

private float velocityX;
private float velocityY;

private float factor = 0.85f;

private final float threshold = 10;

private FlingAnimationListener listener;

/*
* (non-Javadoc)
* @see
* com.polites.android.Transformer#update(com.polites.android.GestureImageView
* , long)
*/
@Override
public boolean update(GestureImageView view, long time) {
final float seconds = time / 1000.0f;

final float dx = velocityX * seconds;
final float dy = velocityY * seconds;

velocityX *= factor;
velocityY *= factor;

final boolean active = Math.abs(velocityX) > threshold
&& Math.abs(velocityY) > threshold;

if (listener != null) {
listener.onMove(dx, dy);

if (!active) {
listener.onComplete();
}
}

return active;
}

public void setVelocityX(float velocityX) {
this.velocityX = velocityX;
}

public void setVelocityY(float velocityY) {
this.velocityY = velocityY;
}

public void setFactor(float factor) {
this.factor = factor;
}

public void setListener(FlingAnimationListener listener) {
this.listener = listener;
}
}




/*
 * Copyright (c) 2012 Jason Polites
 * 
 * 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.polites.android;

import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;

/**
 * @author Jason Polites
 * 
 */
public class FlingListener extends SimpleOnGestureListener {

private float velocityX;
private float velocityY;

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
this.velocityX = velocityX;
this.velocityY = velocityY;
return true;
}

public float getVelocityX() {
return velocityX;
}

public float getVelocityY() {
return velocityY;
}
}



/*
 * Copyright (c) 2012 Jason Polites
 * 
 * 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.polites.android;

import java.io.InputStream;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

import android.content.Context;
import android.content.res.Configuration;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.provider.MediaStore.Images.ImageColumns;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;

public class GestureImageView extends ImageView {

public static final String GLOBAL_NS = "http://schemas.android.com/apk/res/android";
public static final String LOCAL_NS = "http://schemas.polites.com/android";

private final Semaphore drawLock = new Semaphore(0);
private Animator animator;

private Drawable drawable;

private float x = 0, y = 0;

private boolean layout = false;

private float scaleAdjust = 1.0f;
private float startingScale = -1.0f;

private final float scale = 1.0f;
private float maxScale = 5.0f;
private float minScale = 0.75f;
private float fitScaleHorizontal = 1.0f;
private float fitScaleVertical = 1.0f;
private float rotation = 0.0f;

private float centerX;
private float centerY;

private Float startX, startY;

private int hWidth;
private int hHeight;

private int resId = -1;
private boolean recycle = false;
private boolean strict = false;

private int displayHeight;
private int displayWidth;

private int alpha = 255;
private ColorFilter colorFilter;

private int deviceOrientation = -1;
private int imageOrientation;

private GestureImageViewListener gestureImageViewListener;
private GestureImageViewTouchListener gestureImageViewTouchListener;

private OnTouchListener customOnTouchListener;
private OnClickListener onClickListener;

public GestureImageView(Context context, AttributeSet attrs, int defStyle) {
this(context, attrs);
}

public GestureImageView(Context context, AttributeSet attrs) {
super(context, attrs);

final String scaleType = attrs.getAttributeValue(
GestureImageView.GLOBAL_NS, "scaleType");

if (scaleType == null || scaleType.trim().length() == 0) {
setScaleType(ScaleType.CENTER_INSIDE);
}

final String strStartX = attrs.getAttributeValue(
GestureImageView.LOCAL_NS, "start-x");
final String strStartY = attrs.getAttributeValue(
GestureImageView.LOCAL_NS, "start-y");

if (strStartX != null && strStartX.trim().length() > 0) {
startX = Float.parseFloat(strStartX);
}

if (strStartY != null && strStartY.trim().length() > 0) {
startY = Float.parseFloat(strStartY);
}

setStartingScale(attrs.getAttributeFloatValue(
GestureImageView.LOCAL_NS, "start-scale", startingScale));
setMinScale(attrs.getAttributeFloatValue(GestureImageView.LOCAL_NS,
"min-scale", minScale));
setMaxScale(attrs.getAttributeFloatValue(GestureImageView.LOCAL_NS,
"max-scale", maxScale));
setStrict(attrs.getAttributeBooleanValue(GestureImageView.LOCAL_NS,
"strict", strict));
setRecycle(attrs.getAttributeBooleanValue(GestureImageView.LOCAL_NS,
"recycle", recycle));

initImage();
}

public GestureImageView(Context context) {
super(context);
setScaleType(ScaleType.CENTER_INSIDE);
initImage();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

if (drawable != null) {
final int orientation = getResources().getConfiguration().orientation;
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
displayHeight = MeasureSpec.getSize(heightMeasureSpec);

if (getLayoutParams().width == LayoutParams.WRAP_CONTENT) {
final float ratio = (float) getImageWidth()
/ (float) getImageHeight();
displayWidth = Math.round(displayHeight * ratio);
} else {
displayWidth = MeasureSpec.getSize(widthMeasureSpec);
}
} else {
displayWidth = MeasureSpec.getSize(widthMeasureSpec);
if (getLayoutParams().height == LayoutParams.WRAP_CONTENT) {
final float ratio = (float) getImageHeight()
/ (float) getImageWidth();
displayHeight = Math.round(displayWidth * ratio);
} else {
displayHeight = MeasureSpec.getSize(heightMeasureSpec);
}
}
} else {
displayHeight = MeasureSpec.getSize(heightMeasureSpec);
displayWidth = MeasureSpec.getSize(widthMeasureSpec);
}

setMeasuredDimension(displayWidth, displayHeight);
}

@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (changed || !layout) {
setupCanvas(displayWidth, displayHeight, getResources()
.getConfiguration().orientation);
}
}

protected void setupCanvas(int measuredWidth, int measuredHeight,
int orientation) {

if (deviceOrientation != orientation) {
layout = false;
deviceOrientation = orientation;
}

if (drawable != null && !layout) {
final int imageWidth = getImageWidth();
final int imageHeight = getImageHeight();

hWidth = Math.round((imageWidth / 2.0f));
hHeight = Math.round((imageHeight / 2.0f));

measuredWidth -= getPaddingLeft() + getPaddingRight();
measuredHeight -= getPaddingTop() + getPaddingBottom();

computeCropScale(imageWidth, imageHeight, measuredWidth,
measuredHeight);

if (startingScale <= 0.0f) {
computeStartingScale(imageWidth, imageHeight, measuredWidth,
measuredHeight);
}

scaleAdjust = startingScale;

centerX = measuredWidth / 2.0f;
centerY = measuredHeight / 2.0f;

if (startX == null) {
x = centerX;
} else {
x = startX;
}

if (startY == null) {
y = centerY;
} else {
y = startY;
}

gestureImageViewTouchListener = new GestureImageViewTouchListener(
this, measuredWidth, measuredHeight);

if (isLandscape()) {
gestureImageViewTouchListener.setMinScale(minScale
* fitScaleHorizontal);
} else {
gestureImageViewTouchListener.setMinScale(minScale
* fitScaleVertical);
}

gestureImageViewTouchListener.setMaxScale(maxScale * startingScale);

gestureImageViewTouchListener
.setFitScaleHorizontal(fitScaleHorizontal);
gestureImageViewTouchListener.setFitScaleVertical(fitScaleVertical);
gestureImageViewTouchListener.setCanvasWidth(measuredWidth);
gestureImageViewTouchListener.setCanvasHeight(measuredHeight);
gestureImageViewTouchListener.setOnClickListener(onClickListener);

drawable.setBounds(-hWidth, -hHeight, hWidth, hHeight);

super.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (customOnTouchListener != null) {
customOnTouchListener.onTouch(v, event);
}
return gestureImageViewTouchListener.onTouch(v, event);
}
});

layout = true;
}
}

protected void computeCropScale(int imageWidth, int imageHeight,
int measuredWidth, int measuredHeight) {
fitScaleHorizontal = (float) measuredWidth / (float) imageWidth;
fitScaleVertical = (float) measuredHeight / (float) imageHeight;
}

protected void computeStartingScale(int imageWidth, int imageHeight,
int measuredWidth, int measuredHeight) {
switch (getScaleType()) {
case CENTER:
// Center the image in the view, but perform no scaling.
startingScale = 1.0f;
break;

case CENTER_CROP:
startingScale = Math.max((float) measuredHeight
/ (float) imageHeight, (float) measuredWidth
/ (float) imageWidth);
break;

case CENTER_INSIDE:
if (isLandscape()) {
startingScale = fitScaleHorizontal;
} else {
startingScale = fitScaleVertical;
}
break;
}
}

protected boolean isRecycled() {
if (drawable != null && drawable instanceof BitmapDrawable) {
final Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
if (bitmap != null) {
return bitmap.isRecycled();
}
}
return false;
}

protected void recycle() {
if (recycle && drawable != null && drawable instanceof BitmapDrawable) {
final Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
if (bitmap != null) {
bitmap.recycle();
}
}
}

@Override
protected void onDraw(Canvas canvas) {
if (layout) {
if (drawable != null && !isRecycled()) {
canvas.save();

final float adjustedScale = scale * scaleAdjust;

canvas.translate(x, y);

if (rotation != 0.0f) {
canvas.rotate(rotation);
}

if (adjustedScale != 1.0f) {
canvas.scale(adjustedScale, adjustedScale);
}

drawable.draw(canvas);

canvas.restore();
}

if (drawLock.availablePermits() <= 0) {
drawLock.release();
}
}
}

/**
* Waits for a draw
* @param max
*            time to wait for draw (ms)
* @throws InterruptedException
*/
public boolean waitForDraw(long timeout) throws InterruptedException {
return drawLock.tryAcquire(timeout, TimeUnit.MILLISECONDS);
}

@Override
protected void onAttachedToWindow() {
animator = new Animator(this, "GestureImageViewAnimator");
animator.start();

if (resId >= 0 && drawable == null) {
setImageResource(resId);
}

super.onAttachedToWindow();
}

public void animationStart(Animation animation) {
if (animator != null) {
animator.play(animation);
}
}

public void animationStop() {
if (animator != null) {
animator.cancel();
}
}

@Override
protected void onDetachedFromWindow() {
if (animator != null) {
animator.finish();
}
if (recycle && drawable != null && !isRecycled()) {
recycle();
drawable = null;
}
super.onDetachedFromWindow();
}

protected void initImage() {
if (drawable != null) {
drawable.setAlpha(alpha);
drawable.setFilterBitmap(true);
if (colorFilter != null) {
drawable.setColorFilter(colorFilter);
}
}

if (!layout) {
requestLayout();
redraw();
}
}

@Override
public void setImageBitmap(Bitmap image) {
drawable = new BitmapDrawable(getResources(), image);
initImage();
}

@Override
public void setImageDrawable(Drawable drawable) {
this.drawable = drawable;
initImage();
}

@Override
public void setImageResource(int id) {
if (drawable != null) {
recycle();
}
if (id >= 0) {
resId = id;
setImageDrawable(getContext().getResources().getDrawable(id));
}
}

public int getScaledWidth() {
return Math.round(getImageWidth() * getScale());
}

public int getScaledHeight() {
return Math.round(getImageHeight() * getScale());
}

public int getImageWidth() {
if (drawable != null) {
return drawable.getIntrinsicWidth();
}
return 0;
}

public int getImageHeight() {
if (drawable != null) {
return drawable.getIntrinsicHeight();
}
return 0;
}

public void moveBy(float x, float y) {
this.x += x;
this.y += y;
}

public void setPosition(float x, float y) {
this.x = x;
this.y = y;
}

public void redraw() {
postInvalidate();
}

public void setMinScale(float min) {
minScale = min;
if (gestureImageViewTouchListener != null) {
gestureImageViewTouchListener.setMinScale(min * fitScaleHorizontal);
}
}

public void setMaxScale(float max) {
maxScale = max;
if (gestureImageViewTouchListener != null) {
gestureImageViewTouchListener.setMaxScale(max * startingScale);
}
}

public void setScale(float scale) {
scaleAdjust = scale;
}

public float getScale() {
return scaleAdjust;
}

public float getImageX() {
return x;
}

public float getImageY() {
return y;
}

public boolean isStrict() {
return strict;
}

public void setStrict(boolean strict) {
this.strict = strict;
}

public boolean isRecycle() {
return recycle;
}

public void setRecycle(boolean recycle) {
this.recycle = recycle;
}

public void reset() {
x = centerX;
y = centerY;
scaleAdjust = startingScale;
redraw();
}

@Override
public void setRotation(float rotation) {
this.rotation = rotation;
}

public void setGestureImageViewListener(
GestureImageViewListener pinchImageViewListener) {
gestureImageViewListener = pinchImageViewListener;
}

public GestureImageViewListener getGestureImageViewListener() {
return gestureImageViewListener;
}

@Override
public Drawable getDrawable() {
return drawable;
}

@Override
public void setAlpha(int alpha) {
this.alpha = alpha;
if (drawable != null) {
drawable.setAlpha(alpha);
}
}

@Override
public void setColorFilter(ColorFilter cf) {
colorFilter = cf;
if (drawable != null) {
drawable.setColorFilter(cf);
}
}

@Override
public void setImageURI(Uri mUri) {
if ("content".equals(mUri.getScheme())) {
try {
final String[] orientationColumn = { ImageColumns.ORIENTATION };

final Cursor cur = getContext().getContentResolver().query(
mUri, orientationColumn, null, null, null);

if (cur != null && cur.moveToFirst()) {
imageOrientation = cur.getInt(cur
.getColumnIndex(orientationColumn[0]));
}

InputStream in = null;

try {
in = getContext().getContentResolver()
.openInputStream(mUri);
final Bitmap bmp = BitmapFactory.decodeStream(in);

if (imageOrientation != 0) {
final Matrix m = new Matrix();
m.postRotate(imageOrientation);
final Bitmap rotated = Bitmap.createBitmap(bmp, 0, 0,
bmp.getWidth(), bmp.getHeight(), m, true);
bmp.recycle();
setImageDrawable(new BitmapDrawable(getResources(),
rotated));
} else {
setImageDrawable(new BitmapDrawable(getResources(), bmp));
}
} finally {
if (in != null) {
in.close();
}

if (cur != null) {
cur.close();
}
}
} catch (final Exception e) {
Log.w("GestureImageView", "Unable to open content: " + mUri, e);
}
} else {
setImageDrawable(Drawable.createFromPath(mUri.toString()));
}

if (drawable == null) {
Log.e("GestureImageView", "resolveUri failed on bad bitmap uri: "
+ mUri);
// Don't try again.
mUri = null;
}
}

@Override
public Matrix getImageMatrix() {
if (strict) {
throw new UnsupportedOperationException("Not supported");
}
return super.getImageMatrix();
}

@Override
public void setScaleType(ScaleType scaleType) {
if (scaleType == ScaleType.CENTER || scaleType == ScaleType.CENTER_CROP
|| scaleType == ScaleType.CENTER_INSIDE) {

super.setScaleType(scaleType);
} else if (strict) {
throw new UnsupportedOperationException("Not supported");
}
}

@Override
public void invalidateDrawable(Drawable dr) {
if (strict) {
throw new UnsupportedOperationException("Not supported");
}
super.invalidateDrawable(dr);
}

@Override
public int[] onCreateDrawableState(int extraSpace) {
if (strict) {
throw new UnsupportedOperationException("Not supported");
}
return super.onCreateDrawableState(extraSpace);
}

@Override
public void setAdjustViewBounds(boolean adjustViewBounds) {
if (strict) {
throw new UnsupportedOperationException("Not supported");
}
super.setAdjustViewBounds(adjustViewBounds);
}

@Override
public void setImageLevel(int level) {
if (strict) {
throw new UnsupportedOperationException("Not supported");
}
super.setImageLevel(level);
}

@Override
public void setImageMatrix(Matrix matrix) {
if (strict) {
throw new UnsupportedOperationException("Not supported");
}
}

@Override
public void setImageState(int[] state, boolean merge) {
if (strict) {
throw new UnsupportedOperationException("Not supported");
}
}

@Override
public void setSelected(boolean selected) {
if (strict) {
throw new UnsupportedOperationException("Not supported");
}
super.setSelected(selected);
}

@Override
public void setOnTouchListener(OnTouchListener l) {
customOnTouchListener = l;
}

public float getCenterX() {
return centerX;
}

public float getCenterY() {
return centerY;
}

public boolean isLandscape() {
return getImageWidth() >= getImageHeight();
}

public boolean isPortrait() {
return getImageWidth() <= getImageHeight();
}

public void setStartingScale(float startingScale) {
this.startingScale = startingScale;
}

public void setStartingPosition(float x, float y) {
startX = x;
startY = y;
}

@Override
public void setOnClickListener(OnClickListener l) {
onClickListener = l;

if (gestureImageViewTouchListener != null) {
gestureImageViewTouchListener.setOnClickListener(l);
}
}

/**
* Returns true if the image dimensions are aligned with the orientation of
* the device.
* @return
*/
public boolean isOrientationAligned() {
if (deviceOrientation == Configuration.ORIENTATION_LANDSCAPE) {
return isLandscape();
} else if (deviceOrientation == Configuration.ORIENTATION_PORTRAIT) {
return isPortrait();
}
return true;
}

public int getDeviceOrientation() {
return deviceOrientation;
}
}




/*
 * Copyright (c) 2012 Jason Polites
 * 
 * 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.polites.android;

/**
 * @author jasonpolites
 * 
 */
public interface GestureImageViewListener {

public void onTouch(float x, float y);

public void onScale(float scale);

public void onPosition(float x, float y);

}






/*
 * Copyright (c) 2012 Jason Polites
 * 
 * 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.polites.android;

import android.content.res.Configuration;
import android.graphics.PointF;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;

public class GestureImageViewTouchListener implements OnTouchListener {

private GestureImageView image;
private OnClickListener onClickListener;

private final PointF current = new PointF();
private final PointF last = new PointF();
private final PointF next = new PointF();
private final PointF midpoint = new PointF();

private final VectorF scaleVector = new VectorF();
private final VectorF pinchVector = new VectorF();

private boolean touched = false;
private boolean inZoom = false;

private float initialDistance;
private float lastScale = 1.0f;
private float currentScale = 1.0f;

private float boundaryLeft = 0;
private float boundaryTop = 0;
private float boundaryRight = 0;
private float boundaryBottom = 0;

private float maxScale = 5.0f;
private float minScale = 0.25f;
private float fitScaleHorizontal = 1.0f;
private float fitScaleVertical = 1.0f;

private int canvasWidth = 0;
private int canvasHeight = 0;

private float centerX = 0;
private float centerY = 0;

private float startingScale = 0;

private boolean canDragX = false;
private boolean canDragY = false;

private boolean multiTouch = false;

private int displayWidth;
private int displayHeight;

private int imageWidth;
private int imageHeight;

private FlingListener flingListener;
private FlingAnimation flingAnimation;
private ZoomAnimation zoomAnimation;
private MoveAnimation moveAnimation;
private GestureDetector tapDetector;
private GestureDetector flingDetector;
private GestureImageViewListener imageListener;

public GestureImageViewTouchListener(final GestureImageView image,
int displayWidth, int displayHeight) {
super();

this.image = image;

this.displayWidth = displayWidth;
this.displayHeight = displayHeight;

centerX = displayWidth / 2.0f;
centerY = displayHeight / 2.0f;

imageWidth = image.getImageWidth();
imageHeight = image.getImageHeight();

startingScale = image.getScale();

currentScale = startingScale;
lastScale = startingScale;

boundaryRight = displayWidth;
boundaryBottom = displayHeight;
boundaryLeft = 0;
boundaryTop = 0;

next.x = image.getImageX();
next.y = image.getImageY();

flingListener = new FlingListener();
flingAnimation = new FlingAnimation();
zoomAnimation = new ZoomAnimation();
moveAnimation = new MoveAnimation();

flingAnimation.setListener(new FlingAnimationListener() {
@Override
public void onMove(float x, float y) {
handleDrag(current.x + x, current.y + y);
}

@Override
public void onComplete() {
}
});

zoomAnimation.setZoom(2.0f);
zoomAnimation.setZoomAnimationListener(new ZoomAnimationListener() {
@Override
public void onZoom(float scale, float x, float y) {
if (scale <= maxScale && scale >= minScale) {
handleScale(scale, x, y);
}
}

@Override
public void onComplete() {
inZoom = false;
handleUp();
}
});

moveAnimation.setMoveAnimationListener(new MoveAnimationListener() {

@Override
public void onMove(float x, float y) {
image.setPosition(x, y);
image.redraw();
}
});

tapDetector = new GestureDetector(image.getContext(),
new SimpleOnGestureListener() {
@Override
public boolean onDoubleTap(MotionEvent e) {
startZoom(e);
return true;
}

@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
if (!inZoom) {
if (onClickListener != null) {
onClickListener.onClick(image);
return true;
}
}

return false;
}
});

flingDetector = new GestureDetector(image.getContext(), flingListener);
imageListener = image.getGestureImageViewListener();

calculateBoundaries();
}

private void startFling() {
flingAnimation.setVelocityX(flingListener.getVelocityX());
flingAnimation.setVelocityY(flingListener.getVelocityY());
image.animationStart(flingAnimation);
}

private void startZoom(MotionEvent e) {
inZoom = true;
zoomAnimation.reset();

float zoomTo = 1.0f;

if (image.isLandscape()) {
if (image.getDeviceOrientation() == Configuration.ORIENTATION_PORTRAIT) {
final int scaledHeight = image.getScaledHeight();

if (scaledHeight < canvasHeight) {
zoomTo = fitScaleVertical / currentScale;
zoomAnimation.setTouchX(e.getX());
zoomAnimation.setTouchY(image.getCenterY());
} else {
zoomTo = fitScaleHorizontal / currentScale;
zoomAnimation.setTouchX(image.getCenterX());
zoomAnimation.setTouchY(image.getCenterY());
}
} else {
final int scaledWidth = image.getScaledWidth();

if (scaledWidth == canvasWidth) {
zoomTo = currentScale * 4.0f;
zoomAnimation.setTouchX(e.getX());
zoomAnimation.setTouchY(e.getY());
} else if (scaledWidth < canvasWidth) {
zoomTo = fitScaleHorizontal / currentScale;
zoomAnimation.setTouchX(image.getCenterX());
zoomAnimation.setTouchY(e.getY());
} else {
zoomTo = fitScaleHorizontal / currentScale;
zoomAnimation.setTouchX(image.getCenterX());
zoomAnimation.setTouchY(image.getCenterY());
}
}
} else {
if (image.getDeviceOrientation() == Configuration.ORIENTATION_PORTRAIT) {

final int scaledHeight = image.getScaledHeight();

if (scaledHeight == canvasHeight) {
zoomTo = currentScale * 4.0f;
zoomAnimation.setTouchX(e.getX());
zoomAnimation.setTouchY(e.getY());
} else if (scaledHeight < canvasHeight) {
zoomTo = fitScaleVertical / currentScale;
zoomAnimation.setTouchX(e.getX());
zoomAnimation.setTouchY(image.getCenterY());
} else {
zoomTo = fitScaleVertical / currentScale;
zoomAnimation.setTouchX(image.getCenterX());
zoomAnimation.setTouchY(image.getCenterY());
}
} else {
final int scaledWidth = image.getScaledWidth();

if (scaledWidth < canvasWidth) {
zoomTo = fitScaleHorizontal / currentScale;
zoomAnimation.setTouchX(image.getCenterX());
zoomAnimation.setTouchY(e.getY());
} else {
zoomTo = fitScaleVertical / currentScale;
zoomAnimation.setTouchX(image.getCenterX());
zoomAnimation.setTouchY(image.getCenterY());
}
}
}

zoomAnimation.setZoom(zoomTo);
image.animationStart(zoomAnimation);
}

private void stopAnimations() {
image.animationStop();
}

@Override
public boolean onTouch(View v, MotionEvent event) {

if (!inZoom) {

if (!tapDetector.onTouchEvent(event)) {
if (event.getPointerCount() == 1
&& flingDetector.onTouchEvent(event)) {
startFling();
}

if (event.getAction() == MotionEvent.ACTION_UP) {
handleUp();
} else if (event.getAction() == MotionEvent.ACTION_DOWN) {
stopAnimations();

last.x = event.getX();
last.y = event.getY();

if (imageListener != null) {
imageListener.onTouch(last.x, last.y);
}

touched = true;
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (event.getPointerCount() > 1) {
multiTouch = true;
if (initialDistance > 0) {

pinchVector.set(event);
pinchVector.calculateLength();

final float distance = pinchVector.length;

if (initialDistance != distance) {

final float newScale = distance
/ initialDistance * lastScale;

if (newScale <= maxScale) {
scaleVector.length *= newScale;

scaleVector.calculateEndPoint();

scaleVector.length /= newScale;

final float newX = scaleVector.end.x;
final float newY = scaleVector.end.y;

handleScale(newScale, newX, newY);
}
}
} else {
initialDistance = MathUtils.distance(event);

MathUtils.midpoint(event, midpoint);

scaleVector.setStart(midpoint);
scaleVector.setEnd(next);

scaleVector.calculateLength();
scaleVector.calculateAngle();

scaleVector.length /= lastScale;
}
} else {
if (!touched) {
touched = true;
last.x = event.getX();
last.y = event.getY();
next.x = image.getImageX();
next.y = image.getImageY();
} else if (!multiTouch) {
if (handleDrag(event.getX(), event.getY())) {
image.redraw();
}
}
}
}
}
}

return true;
}

protected void handleUp() {

multiTouch = false;

initialDistance = 0;
lastScale = currentScale;

if (!canDragX) {
next.x = centerX;
}

if (!canDragY) {
next.y = centerY;
}

boundCoordinates();

if (!canDragX && !canDragY) {

if (image.isLandscape()) {
currentScale = fitScaleHorizontal;
lastScale = fitScaleHorizontal;
} else {
currentScale = fitScaleVertical;
lastScale = fitScaleVertical;
}
}

image.setScale(currentScale);
image.setPosition(next.x, next.y);

if (imageListener != null) {
imageListener.onScale(currentScale);
imageListener.onPosition(next.x, next.y);
}

image.redraw();
}

protected void handleScale(float scale, float x, float y) {

currentScale = scale;

if (currentScale > maxScale) {
currentScale = maxScale;
} else if (currentScale < minScale) {
currentScale = minScale;
} else {
next.x = x;
next.y = y;
}

calculateBoundaries();

image.setScale(currentScale);
image.setPosition(next.x, next.y);

if (imageListener != null) {
imageListener.onScale(currentScale);
imageListener.onPosition(next.x, next.y);
}

image.redraw();
}

protected boolean handleDrag(float x, float y) {
current.x = x;
current.y = y;

final float diffX = current.x - last.x;
final float diffY = current.y - last.y;

if (diffX != 0 || diffY != 0) {

if (canDragX) {
next.x += diffX;
}
if (canDragY) {
next.y += diffY;
}

boundCoordinates();

last.x = current.x;
last.y = current.y;

if (canDragX || canDragY) {
image.setPosition(next.x, next.y);

if (imageListener != null) {
imageListener.onPosition(next.x, next.y);
}

return true;
}
}

return false;
}

public void reset() {
currentScale = startingScale;
next.x = centerX;
next.y = centerY;
calculateBoundaries();
image.setScale(currentScale);
image.setPosition(next.x, next.y);
image.redraw();
}

public float getMaxScale() {
return maxScale;
}

public void setMaxScale(float maxScale) {
this.maxScale = maxScale;
}

public float getMinScale() {
return minScale;
}

public void setMinScale(float minScale) {
this.minScale = minScale;
}

public void setOnClickListener(OnClickListener onClickListener) {
this.onClickListener = onClickListener;
}

protected void setCanvasWidth(int canvasWidth) {
this.canvasWidth = canvasWidth;
}

protected void setCanvasHeight(int canvasHeight) {
this.canvasHeight = canvasHeight;
}

protected void setFitScaleHorizontal(float fitScale) {
fitScaleHorizontal = fitScale;
}

protected void setFitScaleVertical(float fitScaleVertical) {
this.fitScaleVertical = fitScaleVertical;
}

protected void boundCoordinates() {
if (next.x < boundaryLeft) {
next.x = boundaryLeft;
} else if (next.x > boundaryRight) {
next.x = boundaryRight;
}

if (next.y < boundaryTop) {
next.y = boundaryTop;
} else if (next.y > boundaryBottom) {
next.y = boundaryBottom;
}
}

protected void calculateBoundaries() {

final int effectiveWidth = Math.round(imageWidth * currentScale);
final int effectiveHeight = Math.round(imageHeight * currentScale);

canDragX = effectiveWidth > displayWidth;
canDragY = effectiveHeight > displayHeight;

if (canDragX) {
final float diff = (effectiveWidth - displayWidth) / 2.0f;
boundaryLeft = centerX - diff;
boundaryRight = centerX + diff;
}

if (canDragY) {
final float diff = (effectiveHeight - displayHeight) / 2.0f;
boundaryTop = centerY - diff;
boundaryBottom = centerY + diff;
}
}
}







/*
 * Copyright (c) 2012 Jason Polites
 * 
 * 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.polites.android;

import android.graphics.PointF;
import android.util.FloatMath;
import android.view.MotionEvent;

public class MathUtils {

public static float distance(MotionEvent event) {
final float x = event.getX(0) - event.getX(1);
final float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
}

public static float distance(PointF p1, PointF p2) {
final float x = p1.x - p2.x;
final float y = p1.y - p2.y;
return FloatMath.sqrt(x * x + y * y);
}

public static float distance(float x1, float y1, float x2, float y2) {
final float x = x1 - x2;
final float y = y1 - y2;
return FloatMath.sqrt(x * x + y * y);
}

public static void midpoint(MotionEvent event, PointF point) {
final float x1 = event.getX(0);
final float y1 = event.getY(0);
final float x2 = event.getX(1);
final float y2 = event.getY(1);
MathUtils.midpoint(x1, y1, x2, y2, point);
}

public static void midpoint(float x1, float y1, float x2, float y2,
PointF point) {
point.x = (x1 + x2) / 2.0f;
point.y = (y1 + y2) / 2.0f;
}

/**
* Rotates p1 around p2 by angle degrees.
* @param p1
* @param p2
* @param angle
*/
public void rotate(PointF p1, PointF p2, float angle) {
final float px = p1.x;
final float py = p1.y;
final float ox = p2.x;
final float oy = p2.y;
p1.x = FloatMath.cos(angle) * (px - ox) - FloatMath.sin(angle)
* (py - oy) + ox;
p1.y = FloatMath.sin(angle) * (px - ox) + FloatMath.cos(angle)
* (py - oy) + oy;
}

public static float angle(PointF p1, PointF p2) {
return MathUtils.angle(p1.x, p1.y, p2.x, p2.y);
}

public static float angle(float x1, float y1, float x2, float y2) {
return (float) Math.atan2(y2 - y1, x2 - x1);
}
}






/*
 * Copyright (c) 2012 Jason Polites
 * 
 * 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.polites.android;

/**
 * @author Jason Polites
 * 
 */
public class MoveAnimation implements Animation {

private boolean firstFrame = true;

private float startX;
private float startY;

private float targetX;
private float targetY;
private long animationTimeMS = 100;
private long totalTime = 0;

private MoveAnimationListener moveAnimationListener;

/*
* (non-Javadoc)
* @see
* com.polites.android.Animation#update(com.polites.android.GestureImageView
* , long)
*/
@Override
public boolean update(GestureImageView view, long time) {
totalTime += time;

if (firstFrame) {
firstFrame = false;
startX = view.getImageX();
startY = view.getImageY();
}

if (totalTime < animationTimeMS) {

final float ratio = (float) totalTime / animationTimeMS;

final float newX = (targetX - startX) * ratio + startX;
final float newY = (targetY - startY) * ratio + startY;

if (moveAnimationListener != null) {
moveAnimationListener.onMove(newX, newY);
}

return true;
} else {
if (moveAnimationListener != null) {
moveAnimationListener.onMove(targetX, targetY);
}
}

return false;
}

public void reset() {
firstFrame = true;
totalTime = 0;
}

public float getTargetX() {
return targetX;
}

public void setTargetX(float targetX) {
this.targetX = targetX;
}

public float getTargetY() {
return targetY;
}

public void setTargetY(float targetY) {
this.targetY = targetY;
}

public long getAnimationTimeMS() {
return animationTimeMS;
}

public void setAnimationTimeMS(long animationTimeMS) {
this.animationTimeMS = animationTimeMS;
}

public void setMoveAnimationListener(
MoveAnimationListener moveAnimationListener) {
this.moveAnimationListener = moveAnimationListener;
}
}





/*
 * Copyright (c) 2012 Jason Polites
 * 
 * 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.polites.android;

/**
 * @author Jason Polites
 * 
 */
public interface MoveAnimationListener {

public void onMove(float x, float y);

}




/*
 * Copyright (c) 2012 Jason Polites
 * 
 * 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.polites.android;

import android.graphics.PointF;
import android.util.FloatMath;
import android.view.MotionEvent;

public class VectorF {

public float angle;
public float length;

public final PointF start = new PointF();
public final PointF end = new PointF();

public void calculateEndPoint() {
end.x = FloatMath.cos(angle) * length + start.x;
end.y = FloatMath.sin(angle) * length + start.y;
}

public void setStart(PointF p) {
start.x = p.x;
start.y = p.y;
}

public void setEnd(PointF p) {
end.x = p.x;
end.y = p.y;
}

public void set(MotionEvent event) {
start.x = event.getX(0);
start.y = event.getY(0);
end.x = event.getX(1);
end.y = event.getY(1);
}

public float calculateLength() {
length = MathUtils.distance(start, end);
return length;
}

public float calculateAngle() {
angle = MathUtils.angle(start, end);
return angle;
}

}



/*
 * Copyright (c) 2012 Jason Polites
 * 
 * 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.polites.android;

import android.graphics.PointF;

/**
 * @author Jason Polites
 * 
 */
public class ZoomAnimation implements Animation {

private boolean firstFrame = true;

private float touchX;
private float touchY;

private float zoom;

private float startX;
private float startY;
private float startScale;

private float xDiff;
private float yDiff;
private float scaleDiff;

private long animationLengthMS = 200;
private long totalTime = 0;

private ZoomAnimationListener zoomAnimationListener;

/*
* (non-Javadoc)
* @see
* com.polites.android.Animation#update(com.polites.android.GestureImageView
* , long)
*/
@Override
public boolean update(GestureImageView view, long time) {
if (firstFrame) {
firstFrame = false;

startX = view.getImageX();
startY = view.getImageY();
startScale = view.getScale();
scaleDiff = zoom * startScale - startScale;

if (scaleDiff > 0) {
// Calculate destination for midpoint
final VectorF vector = new VectorF();

// Set the touch point as start because we want to move the end
vector.setStart(new PointF(touchX, touchY));
vector.setEnd(new PointF(startX, startY));

vector.calculateAngle();

// Get the current length
final float length = vector.calculateLength();

// Multiply length by zoom to get the new length
vector.length = length * zoom;

// Now deduce the new endpoint
vector.calculateEndPoint();

xDiff = vector.end.x - startX;
yDiff = vector.end.y - startY;
} else {
// Zoom out to center
xDiff = view.getCenterX() - startX;
yDiff = view.getCenterY() - startY;
}
}

totalTime += time;

final float ratio = (float) totalTime / (float) animationLengthMS;

if (ratio < 1) {

if (ratio > 0) {
// we still have time left
final float newScale = ratio * scaleDiff + startScale;
final float newX = ratio * xDiff + startX;
final float newY = ratio * yDiff + startY;

if (zoomAnimationListener != null) {
zoomAnimationListener.onZoom(newScale, newX, newY);
}
}

return true;
} else {

final float newScale = scaleDiff + startScale;
final float newX = xDiff + startX;
final float newY = yDiff + startY;

if (zoomAnimationListener != null) {
zoomAnimationListener.onZoom(newScale, newX, newY);
zoomAnimationListener.onComplete();
}

return false;
}
}

public void reset() {
firstFrame = true;
totalTime = 0;
}

public float getZoom() {
return zoom;
}

public void setZoom(float zoom) {
this.zoom = zoom;
}

public float getTouchX() {
return touchX;
}

public void setTouchX(float touchX) {
this.touchX = touchX;
}

public float getTouchY() {
return touchY;
}

public void setTouchY(float touchY) {
this.touchY = touchY;
}

public long getAnimationLengthMS() {
return animationLengthMS;
}

public void setAnimationLengthMS(long animationLengthMS) {
this.animationLengthMS = animationLengthMS;
}

public ZoomAnimationListener getZoomAnimationListener() {
return zoomAnimationListener;
}

public void setZoomAnimationListener(
ZoomAnimationListener zoomAnimationListener) {
this.zoomAnimationListener = zoomAnimationListener;
}
}




/*
 * Copyright (c) 2012 Jason Polites
 * 
 * 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.polites.android;

/**
 * @author Jason Polites
 * 
 */
public interface ZoomAnimationListener {
public void onZoom(float scale, float x, float y);

public void onComplete();
}


Activity Class:

package com.droidbd.pinchlib;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.TextView;

import com.droidbd.lamsoca.http.BaseURL;
import com.droidbd.lamsoca.http.CurrentData;
import com.droidbd.projectsocaradio.R;
import com.polites.android.GestureImageView;

public class PinchImageActivity extends Activity {

GestureImageView view;

Bitmap bit = null;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

requestWindowFeature(Window.FEATURE_NO_TITLE);

setContentView(R.layout.standard_image);

bit = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher);

if (CurrentData.getEvant().getBitmap() != null) {
bit = CurrentData.getEvant().getBitmap();
}

view = (GestureImageView) findViewById(R.id.image);
view.setImageBitmap(bit);
// new SqueezeView(webView);

final TextView title = (TextView) findViewById(R.id.fulleventtitle);
title.setText(CurrentData.getEvant().getEvantstitle());
}

public void setBackToEvent(View v) {
finish();

}

public void openURL(View v) {

try
{
final Intent intent = new Intent(Intent.ACTION_VIEW,
Uri.parse(BaseURL.LOGINURL));
startActivity(intent);
}catch (Exception e) {
// TODO: handle exception
}
}

}







কোন মন্তব্য নেই:

একটি মন্তব্য পোস্ট করুন