简体   繁体   中英

Intellij Idea and Eclipse and JDK 7 and Android

I start to develop application for Android using Intellij Idea because it is preferable IDE for last year. I've smashed my face with two fatal error with both IDE: Intellij Idea 1. I created custom view:

public class ImageOverlayView extends View implements View.OnTouchListener {

private static final String TAG = "ImageOverlayView";
private Bitmap image;

private float x, y, sX, sY;

private final Paint paint = new Paint();
private float scaleFactor;

private int getScaledWidth()
{
    return (int)(image.getWidth() * scaleFactor);
}

private int getScaledHeight()
{
    return (int)(image.getHeight() * scaleFactor);
}

public ImageOverlayView(Context context) {
    super(context);
}

public ImageOverlayView(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray a = context.obtainStyledAttributes(R.styleable.ImageOverlayView);
    this.setOnTouchListener(this);
}

public void setImage(Bitmap bm) {
    image = bm;
    invalidate();
}

public void setDrawable(Drawable drawable) {
    image = BitmapUtils.drawableToBitmap(drawable);
    invalidate();
}

@Override
public void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if (canvas != null && image != null) {
        canvas.drawBitmap(image, null, paint);
    } else {
        Log.d(TAG, "Canvas is NULL");
    }
}

@Override
public boolean onTouch(View view, MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_MOVE: {
            sX = event.getX();
            sY = event.getY();

            break;
        }

    }
    return super.onTouchEvent(event);
}

public void loadImageBitmap(String fileName) {
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inPreferredConfig = Bitmap.Config.ARGB_8888;

    image = BitmapFactory.decodeFile(fileName, options);
    if (image == null) {
        throw new NullPointerException("The image can't be decoded.");
    }

    scaleFactor = 1;

    // center image on the screen
    int width = getWidth();
    int height = getHeight();
    if ((width != 0) || (height != 0)) {
        int scrollX = (image.getWidth() < width ? -(width - image.getWidth()) / 2 :    image.getWidth() / 2);
        int scrollY = (image.getHeight() < height ? -(height - image.getHeight()) / 2 : image.getHeight() / 2);
        scrollTo(scrollX, scrollY);
    }
    invalidate();
}

public void loadImageDrawable(int resourceId) {
    Resources resources = getResources();
    Drawable drawable = resources.getDrawable(resourceId);
    image = BitmapUtils.drawableToBitmap(drawable);
    invalidate();
}
}

Then, i've tried to see result in UI Designer in Idea:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    xmlns:android="http://schemas.android.com/apk/res/android">

<ru.lookmyway.customview.ImageOverlayView
    android:id="@+id/imageOverlayView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

</LinearLayout>

And idea gives me NPE:

java.lang.NullPointerException
at ru.lookmyway.customview.ImageOverlayView.onDraw(ImageOverlayView.java:65)
at android.view.View.draw(View.java:13712)
at android.view.View.draw(View.java:13596)
at android.view.ViewGroup.drawChild(ViewGroup.java:2928)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2797)
at android.view.View.draw(View.java:13594)
at android.view.ViewGroup.drawChild(ViewGroup.java:2928)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2797)
at android.view.View.draw(View.java:13594)
at android.view.ViewGroup.drawChild(ViewGroup.java:2928)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2797)
at android.view.View.draw(View.java:13715)
at android.view.View.draw(View.java:13596)
at android.view.ViewGroup.drawChild(ViewGroup.java:2928)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2797)
at android.view.View.draw(View.java:13715)
at com.android.layoutlib.bridge.impl.RenderSessionImpl.render(RenderSessionImpl.java:570)
at com.android.layoutlib.bridge.Bridge.createSession(Bridge.java:334)
at com.android.ide.common.rendering.LayoutLibrary.createSession(LayoutLibrary.java:325)
at org.jetbrains.android.uipreview.RenderService.createRenderSession(RenderService.java:127)
at org.jetbrains.android.uipreview.RenderUtil.renderLayout(RenderUtil.java:154)
at com.intellij.android.designer.designSurface.AndroidDesignerEditorPanel$8.run(AndroidDesignerEditorPanel.java:346)
at com.intellij.util.ui.update.MergingUpdateQueue.execute(MergingUpdateQueue.java:320)
at com.intellij.util.ui.update.MergingUpdateQueue.execute(MergingUpdateQueue.java:310)
at com.intellij.util.ui.update.MergingUpdateQueue$2.run(MergingUpdateQueue.java:254)
at com.intellij.util.ui.update.MergingUpdateQueue.flush(MergingUpdateQueue.java:269)
at com.intellij.util.ui.update.MergingUpdateQueue.flush(MergingUpdateQueue.java:227)
at com.intellij.util.ui.update.MergingUpdateQueue.run(MergingUpdateQueue.java:217)
at com.intellij.util.Alarm$Request$1.run(Alarm.java:289)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)

But at the same time in Eclipse (JUNO) everything is OK!

Than, i decided develop using Eclipse. I installed it and try to build my project. But Eclipse said me that i'm using java 1.7, and Android wants 5.0 or 6.0. Some google search says that i can not use jdk 1.7 cause there are no support it yet in Android, but Idea works fine with android and jdk 1.7!!

Some questions:

  1. Why my custom view working fine in Eclipse, but Idea gives me NPE?
  2. Why Eclipse could not work with jdk 1.7, but Idea works fine with jdk 1.7?
  3. What i have to do? :D
  4. Which IDE i have to choose?

UPDATED ANSWER: Because i've got small reputation, i can not answer my self, so answer in question: My custom view was in package com.example.customview.ImageCustomView. When i try use it in other project, i placed it in com.example and it work, than i refactored this view to name ImageCustomView, moved it ot com.example and again it work fine. I've tried to repeat my bug - but unsuccess, in all packages, with different names it works. Thanks!


UPDATED UPDATED: I repeat my bug. I add Geasture listener, remove constructor with AttributeSet and i got NPE again. But when i discard all my changes - NPE wont dissapear. So i dont know now what's wrong, so i need some versions or answer. I fix it again: i move my custom view class in other package.


MORE INFORMATION: NPE appear when i removed on of constructor:

    public ImageCustomView(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray a = context.obtainStyledAttributes(R.styleable.ImageCustomView);
    a.recycle();

    }

And it even if i add it back - NPE wont disappear, but after refactor name of this class - it works. So, my version this is after refactor Idea refresh pre-compiled classes, coz pre-compile files it is one of the feature Intellij Idea.

After some expirements i've got new NPE:

java.lang.NullPointerException
at android.graphics.Canvas.throwIfRecycled(Canvas.java:1025)
at android.graphics.Canvas.drawBitmap(Canvas.java:1065)
at ru.lookmyway.ImageCustomView.onDraw(ImageCustomView.java:63)
at android.view.View.draw(View.java:13712)
at android.view.View.draw(View.java:13596)
at android.view.ViewGroup.drawChild(ViewGroup.java:2928)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2797)
at android.view.View.draw(View.java:13594)
at android.view.ViewGroup.drawChild(ViewGroup.java:2928)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2797)
at android.view.View.draw(View.java:13594)
at android.view.ViewGroup.drawChild(ViewGroup.java:2928)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2797)
at android.view.View.draw(View.java:13715)
at android.view.View.draw(View.java:13596)
at android.view.ViewGroup.drawChild(ViewGroup.java:2928)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2797)
at android.view.View.draw(View.java:13715)
at com.android.layoutlib.bridge.impl.RenderSessionImpl.render(RenderSessionImpl.java:570)
at com.android.layoutlib.bridge.Bridge.createSession(Bridge.java:334)
at com.android.ide.common.rendering.LayoutLibrary.createSession(LayoutLibrary.java:325)
at org.jetbrains.android.uipreview.RenderService.createRenderSession(RenderService.java:127)
at org.jetbrains.android.uipreview.RenderUtil.renderLayout(RenderUtil.java:154)
at com.intellij.android.designer.designSurface.AndroidDesignerEditorPanel$8.run(AndroidDesignerEditorPanel.java:346)
at com.intellij.util.ui.update.MergingUpdateQueue.execute(MergingUpdateQueue.java:320)
at com.intellij.util.ui.update.MergingUpdateQueue.execute(MergingUpdateQueue.java:310)
at com.intellij.util.ui.update.MergingUpdateQueue$2.run(MergingUpdateQueue.java:254)
at com.intellij.util.ui.update.MergingUpdateQueue.flush(MergingUpdateQueue.java:269)
at com.intellij.util.ui.update.MergingUpdateQueue.flush(MergingUpdateQueue.java:227)
at com.intellij.util.ui.update.MergingUpdateQueue.run(MergingUpdateQueue.java:217)
at com.intellij.util.Alarm$Request$1.run(Alarm.java:289)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)

Updated custom view:

public class ImageCustomView extends View implements View.OnTouchListener {

private static final String TAG = "ImageCustomView";
private Bitmap image;

private float x, y, sX, sY;

private final Paint paint = new Paint();
private float scaleFactor;
private GestureDetector gestureDetector;

private int getScaledWidth()
{
    return (int)(image.getWidth() * scaleFactor);
}

private int getScaledHeight()
{
    return (int)(image.getHeight() * scaleFactor);
}

public ImageCustomView(Context context) {
    super(context);
    this.setOnTouchListener(this);
    paint.setFilterBitmap(true);
    paint.setDither(false);
    gestureDetector = new GestureDetector(context, new MyGestureListener());
}

public void setImage(Bitmap bm) {
    image = bm;
    invalidate();
}

public void setDrawable(Drawable drawable) {
    image = BitmapUtils.drawableToBitmap(drawable);
    invalidate();
}

@Override
public void onDraw(Canvas canvas) {
    canvas.drawBitmap(image, 0, 0, paint);
}

@Override
public boolean onTouch(View view, MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_MOVE: {
            sX = event.getX();
            sY = event.getY();
            Log.d(TAG, "x: " + sX + " y: " + sY);
            break;
        }

    }
    return super.onTouchEvent(event);
}

private class MyGestureListener extends GestureDetector.SimpleOnGestureListener
{
    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
    {
        scrollBy((int)distanceX, (int)distanceY);
        return true;
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
    {
        int fixedScrollX = 0, fixedScrollY = 0;
        int maxScrollX = getScaledWidth(), maxScrollY = getScaledHeight();

        if (getScaledWidth() < getWidth())
        {
            fixedScrollX = -(getWidth() - getScaledWidth()) / 2;
            maxScrollX = fixedScrollX + getScaledWidth();
        }

        if (getScaledHeight() < getHeight())
        {
            fixedScrollY = -(getHeight() - getScaledHeight()) / 2;
            maxScrollY = fixedScrollY + getScaledHeight();
        }

        boolean scrollBeyondImage = (fixedScrollX < 0) || (fixedScrollX > maxScrollX) || (fixedScrollY < 0) || (fixedScrollY > maxScrollY);
        return !scrollBeyondImage;

    }
}

public void loadImageBitmap(String fileName) {
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inPreferredConfig = Bitmap.Config.ARGB_8888;

    image = BitmapFactory.decodeFile(fileName, options);
    if (image == null) {
        throw new NullPointerException("The image can't be decoded.");
    }

    scaleFactor = 1;

    // center image on the screen
    int width = getWidth();
    int height = getHeight();
    if ((width != 0) || (height != 0)) {
        int scrollX = (image.getWidth() < width ? -(width - image.getWidth()) / 2 : image.getWidth() / 2);
        int scrollY = (image.getHeight() < height ? -(height - image.getHeight()) / 2 : image.getHeight() / 2);
        scrollTo(scrollX, scrollY);
    }
    invalidate();
}

public void loadImageDrawable(int resourceId) {
    Resources resources = getResources();
    Drawable drawable = resources.getDrawable(resourceId);
    image = BitmapUtils.drawableToBitmap(drawable);
    invalidate();
}

}

I removed second construcor - got NPE, refactor name of class - got works, added some changes - got NPE (about canvas, second NPE) do refactor name(or place) of class - got works... i dont know... One more detail - this view has no reactions on Touch my image, breakpoint wont go in method onTouch... may be it is key information. My target it is move image on screen and redraw image where i place image by my finger.

Your code is working fine for me(IntelliJ IDEA aka Android Studio). Double check your project setup.

Android Studio save my ass. It shows me errors. So, about Eclipse and JDK 1.7 i have no answer, but about Custom view the answer is:

  • Custom View requires two default constructors:
    public CustomView(Context context) {
         super(context);
    }

    public CustomView(Context context, AttributeSet attrs) {
         super(context, attrs);
    }
  • onDraw method have to contain check entire data for null:

     if (bitmap == null) { paint.setStyle(Paint.Style.FILL); paint.setColor(Color.CYAN); canvas.drawRect(mImagePosition, paint); return; } Rect rect = new Rect(0, 0, this.getWidth(), this.getHeight()); canvas.drawBitmap(bitmap, rect, mImagePosition, null); 
  • There are no need make:

     super.onDraw(canvas); 

    in onDraw method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM