com.polites.android.GestureImageView无法强制转换为android.view.ViewGroup

时间:2015-01-27 19:05:02

标签: java android android-gesture

我好几天都在寻找这个。我想在图像上使用捏合,缩放等。我找到了一个似乎适用于所有人的教程:https://github.com/jasonpolites/gesture-imageview。但是当我在Android Studio上运行代码时,它会给我一个Cast异常。这里已经提到了这个问题(Android run time exception while using gestureImageView and ViewGroup),并且在许多页面中都提出了相同的解决方案:

您的gestureImageView不是ViewGroup。它扩展到哪一类?是View吗?如果是,请使用

View lout = (View) findViewById(R.id.gestureImageView);

但是,我所拥有的gestureImageView不会从View延伸,而是从ImageView延伸,如果我尝试更改它,它将无效。

这是我的代码

xml:

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:gesture-image="http://schemas.polites.com/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">

<com.polites.android.GestureImageView
    android:id="@+id/image"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:src="@drawable/image"
    gesture-image:min-scale="0.1"
    gesture-image:max-scale="10.0"
    gesture-image:strict="true"/>
</LinearLayout>

使用其他帖子中给出解决方案的java文件:

import com.polites.android.GestureImageView;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout.LayoutParams;

public class TramoLibre extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.tramo_libre);

    LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);

    GestureImageView view = new GestureImageView(this);
    view.setImageResource(R.drawable.image);
    view.setLayoutParams(params);

    View layout = (View) findViewById(R.id.image);

    layout.addView(view);
}
}

它在addView中给我一个错误。

通常的“致命异常”:java.lang.ClassCastException: com.polites.android.GestureImageView cannot be cast to android.view.ViewGroup

最后,我有GestureImageView

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;
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 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);

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

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

    String strStartX = attrs.getAttributeValue(LOCAL_NS, "start-x");
    String strStartY = attrs.getAttributeValue(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(LOCAL_NS, "start-scale", startingScale));
    setMinScale(attrs.getAttributeFloatValue(LOCAL_NS, "min-scale", minScale));
    setMaxScale(attrs.getAttributeFloatValue(LOCAL_NS, "max-scale", maxScale));
    setStrict(attrs.getAttributeBooleanValue(LOCAL_NS, "strict", strict));
    setRecycle(attrs.getAttributeBooleanValue(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) {
        int orientation = getResources().getConfiguration().orientation;
        if(orientation == Configuration.ORIENTATION_LANDSCAPE) {
            displayHeight = MeasureSpec.getSize(heightMeasureSpec);

            if(getLayoutParams().width == LayoutParams.WRAP_CONTENT) {
                float ratio = (float) getImageWidth() / (float) getImageHeight();
                displayWidth = Math.round( (float) displayHeight * ratio) ;
            }
            else {
                displayWidth = MeasureSpec.getSize(widthMeasureSpec);
            }
        }
        else {
            displayWidth = MeasureSpec.getSize(widthMeasureSpec);
            if(getLayoutParams().height == LayoutParams.WRAP_CONTENT) {
                float ratio = (float) getImageHeight() / (float) getImageWidth();
                displayHeight = Math.round( (float) 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) {
        int imageWidth = getImageWidth();
        int imageHeight = getImageHeight();

        hWidth = Math.round(((float)imageWidth / 2.0f));
        hHeight = Math.round(((float)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;

        this.centerX = (float) measuredWidth / 2.0f;
        this.centerY = (float) 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:
            // Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions
            // (width and height) of the image will be equal to or larger than the corresponding dimension of the view (minus padding).
            startingScale = Math.max((float) measuredHeight / (float) imageHeight, (float) measuredWidth/ (float) imageWidth);
            break;

        case CENTER_INSIDE:

            // Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions
            // (width and height) of the image will be equal to or less than the corresponding dimension of the view (minus padding).
            float wRatio = (float) imageWidth / (float) measuredWidth;
            float hRatio = (float) imageHeight / (float) measuredHeight;

            if(wRatio > hRatio) {
                startingScale = fitScaleHorizontal;
            }
            else {
                startingScale = fitScaleVertical;
            }

            break;
    }
}

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

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

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

            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(this.drawable != null) {
        this.drawable.setAlpha(alpha);
        this.drawable.setFilterBitmap(true);
        if(colorFilter != null) {
            this.drawable.setColorFilter(colorFilter);
        }
    }

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

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

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

public void setImageResource(int id) {
    if(this.drawable != null) {
        this.recycle();
    }
    if(id >= 0) {
        this.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) {
    this.minScale = min;
    if(gestureImageViewTouchListener != null) {
        gestureImageViewTouchListener.setMinScale(min * fitScaleHorizontal);
    }
}

public void setMaxScale(float max) {
    this.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;
    if (gestureImageViewTouchListener != null) {
        gestureImageViewTouchListener.reset();
    }
    redraw();
}

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

public void setGestureImageViewListener(GestureImageViewListener pinchImageViewListener) {
    this.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) {
    this.colorFilter = cf;
    if(drawable != null) {
        drawable.setColorFilter(cf);
    }
}

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

            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);
                Bitmap bmp = BitmapFactory.decodeStream(in);

                if(imageOrientation != 0) {
                    Matrix m = new Matrix();
                    m.postRotate(imageOrientation);
                    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 (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) {
    this.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) {
    this.startX = x;
    this.startY = y;
}

@Override
public void setOnClickListener(OnClickListener l) {
    this.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;
}

我非常绝望。你可以看到我是一个完全的菜鸟,但我真的付出了巨大的努力。

1 个答案:

答案 0 :(得分:0)

您正尝试将ImageView添加到另一个ImageView中。

你可以

答案1:保留xml并删除以下代码“layout.addView(view);”

答案2:使用空布局并将ImageView添加到其中。

<LinearLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:gesture-image="http://schemas.polites.com/android"
android:id="@+id/empty_layout_for_image"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
代码中的

获取上面定义的LinearLayout。

// : 
// the rest of your codes
// :
View layout =  findViewById(R.id.empty_layout_for_image);
layout.addView(view);