97

I must edit a software that have a custom view, when I try to edit layout xml, Eclipse says me:

Use View.isInEditMode() in your custom views to skip code when shown in Eclipse

But I have no idea about how and where I must use isInEditMode() in the app

My xml file is

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     android:background="#ff000000"
    >
<TextView
     android:id="@+id/result"
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content"
     android:gravity="right"
     android:textSize="32dip"
     android:scrollbars="none"
     android:lines="1"
     android:freezesText="true"
     android:textColor="@color/result"
    />
<EditText
     android:id="@+id/input"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:gravity="left"
     android:textSize="28dip"
     android:scrollbars="none"
     android:singleLine="true"
     android:autoText="false"
     android:imeOptions="flagNoEnterAction|flagNoExtractUi"
     />
<ListView
     android:id="@+id/history"
     android:layout_width="fill_parent"
     android:layout_height="0dip"
     android:layout_weight="1"
     android:cacheColorHint="#ff000000"
     android:choiceMode="singleChoice"
     android:scrollbarStyle="outsideInset"
     android:scrollbars="none"
    />
<calculator.GraphView
     android:id="@+id/graph"
     android:layout_width="fill_parent"
     android:layout_height="0dip"
     android:layout_weight="1"
     android:visibility="gone"
     />
<include layout="@layout/keyboard" />
</LinearLayout>

And my GraphView is

public class GraphView extends View implements Grapher,
        ZoomButtonsController.OnZoomListener,
        TouchHandler.TouchHandlerInterface {
    private int width, height;
    private Matrix matrix = new Matrix();
    private Paint paint = new Paint();
    private Paint textPaint = new Paint();
    private ArrayList<Function> funcs = new ArrayList<Function>();
    private Data next = new Data(), endGraph = new Data();
    private Data graphs[] = { new Data(), new Data(), new Data(), new Data(),
            new Data() };
    private static final int GRAPHS_SIZE = 5;
    private float gwidth = 8;
    private float currentX, currentY;
    private float lastMinX;
    private Scroller scroller;
    private float boundMinY, boundMaxY;
    protected ZoomButtonsController zoomController = new ZoomButtonsController(
            this);
    private ZoomTracker zoomTracker = new ZoomTracker();
    private TouchHandler touchHandler;
    private float lastTouchX, lastTouchY;

    private static final int COL_AXIS = 0xff00a000, COL_GRID = 0xff004000,
            COL_TEXT = 0xff00ff00;

    private static final int COL_GRAPH[] = { 0xffffffff, 0xff00ffff,
            0xffffff00, 0xffff00ff, 0xff80ff80 };

    public GraphView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public GraphView(Context context) {
        super(context);
        touchHandler = new TouchHandler(this);
        init(context);
    }

    private void init(Context context) {
        zoomController.setOnZoomListener(this);
        scroller = new Scroller(context);
        paint.setAntiAlias(false);
        textPaint.setAntiAlias(true);
    }

    @SuppressLint("WrongCall")
    public String captureScreenshot() {
        Bitmap bitmap = Bitmap.createBitmap(width, height,
                Bitmap.Config.RGB_565);
        Canvas canvas = new Canvas(bitmap);
        onDraw(canvas);
        return Util.saveBitmap(bitmap, Grapher.SCREENSHOT_DIR, "calculator");
    }

    private void clearAllGraph() {
        for (int i = 0; i < GRAPHS_SIZE; ++i) {
            graphs[i].clear();
        }
    }

    public void setFunctions(ArrayList<Function> fs) {
        funcs.clear();
        for (Function f : fs) {
            int arity = f.arity();
            if (arity == 0 || arity == 1) {
                funcs.add(f);
            }
        }
        clearAllGraph();
        invalidate();
    }

    public void setFunction(Function f) {
        funcs.clear();
        if (f != null) {
            funcs.add(f);
        }
        clearAllGraph();
        invalidate();
    }

    public void onVisibilityChanged(boolean visible) {
    }

    public void onZoom(boolean zoomIn) {
        if (zoomIn) {
            if (canZoomIn()) {
                gwidth /= 2;
                invalidateGraphs();
            }
        } else {
            if (canZoomOut()) {
                gwidth *= 2;
                invalidateGraphs();
            }
        }
        zoomController.setZoomInEnabled(canZoomIn());
        zoomController.setZoomOutEnabled(canZoomOut());
    }

    public void onResume() {
    }

    public void onPause() {
    }

    public void onDetachedFromWindow() {
        zoomController.setVisible(false);
        super.onDetachedFromWindow();
    }

    protected void onSizeChanged(int w, int h, int ow, int oh) {
        width = w;
        height = h;
        clearAllGraph();
    }

    protected void onDraw(Canvas canvas) {
        if (funcs.size() == 0) {
            return;
        }
        if (scroller.computeScrollOffset()) {
            final float scale = gwidth / width;
            currentX = scroller.getCurrX() * scale;
            currentY = scroller.getCurrY() * scale;
            if (!scroller.isFinished()) {
                invalidate();
            }
        }
        drawGraph(canvas);
    }

    private float eval(Function f, float x) {
        float v = (float) f.eval(x);

        if (v < -10000f) {
            return -10000f;
        }
        if (v > 10000f) {
            return 10000f;
        }
        return v;
    }

    private float distance2(float x1, float y1, float x2, float y2, float y) {
        final float dx = x2 - x1;
        final float dy = y2 - y1;
        final float up = dx * (y1 + y2 - y - y);
        return up * up / (dx * dx + dy * dy);
    }

    private void computeGraph(Function f, float minX, float maxX, float minY,
            float maxY, Data graph) {
        if (f.arity() == 0) {
            float v = (float) f.eval();
            if (v < -10000f) {
                v = -10000f;
            }
            if (v > 10000f) {
                v = 10000f;
            }
            graph.clear();
            graph.push(minX, v);
            graph.push(maxX, v);
            return;
        }

        final float scale = width / gwidth;
        final float maxStep = 15.8976f / scale;
        final float minStep = .05f / scale;
        float ythresh = 1 / scale;
        ythresh = ythresh * ythresh;
        if (!graph.empty()) {
            if (minX >= lastMinX) {
                graph.eraseBefore(minX);
            } else {
                graph.eraseAfter(maxX);
                maxX = Math.min(maxX, graph.firstX());
                graph.swap(endGraph);
            }
        }
        if (graph.empty()) {
            graph.push(minX, eval(f, minX));
        }
        float leftX, leftY;
        float rightX = graph.topX(), rightY = graph.topY();
        int nEval = 1;
        while (true) {
            leftX = rightX;
            leftY = rightY;
            if (leftX > maxX) {
                break;
            }
            if (next.empty()) {
                float x = leftX + maxStep;
                next.push(x, eval(f, x));
                ++nEval;
            }
            rightX = next.topX();
            rightY = next.topY();
            next.pop();

            if (leftY != leftY && rightY != rightY) { // NaN
                continue;
            }

            float dx = rightX - leftX;
            float middleX = (leftX + rightX) / 2;
            float middleY = eval(f, middleX);
            ++nEval;
            boolean middleIsOutside = (middleY < leftY && middleY < rightY)
                    || (leftY < middleY && rightY < middleY);
            if (dx < minStep) {
                if (middleIsOutside) {
                    graph.push(rightX, Float.NaN);
                }
                graph.push(rightX, rightY);
                continue;
            }
            if (middleIsOutside
                    && ((leftY < minY && rightY > maxY) || (leftY > maxY && rightY < minY))) {
                graph.push(rightX, Float.NaN);
                graph.push(rightX, rightY);
                continue;
            }

            if (!middleIsOutside) {

                if (distance2(leftX, leftY, rightX, rightY, middleY) < ythresh) {
                    graph.push(rightX, rightY);
                    continue;
                }
            }
            next.push(rightX, rightY);
            next.push(middleX, middleY);
            rightX = leftX;
            rightY = leftY;
        }
        if (!endGraph.empty()) {
            graph.append(endGraph);
        }
        long t2 = System.currentTimeMillis();

        next.clear();
        endGraph.clear();
    }

    private static Path path = new Path();

    private Path graphToPath(Data graph) {
        boolean first = true;
        int size = graph.size;
        float[] xs = graph.xs;
        float[] ys = graph.ys;
        path.rewind();
        for (int i = 0; i < size; ++i) {
            float y = ys[i];
            float x = xs[i];
            // Calculator.log("path " + x + ' ' + y);
            if (y == y) { // !NaN
                if (first) {
                    path.moveTo(x, y);
                    first = false;
                } else {
                    path.lineTo(x, y);
                }
            } else {
                first = true;
            }
        }
        return path;
    }

    private static final float NTICKS = 15;

    private static float stepFactor(float w) {
        float f = 1;
        while (w / f > NTICKS) {
            f *= 10;
        }
        while (w / f < NTICKS / 10) {
            f /= 10;
        }
        float r = w / f;
        if (r < NTICKS / 5) {
            return f / 5;
        } else if (r < NTICKS / 2) {
            return f / 2;
        } else {
            return f;
        }
    }

    private static StringBuilder b = new StringBuilder();
    private static char[] buf = new char[20];

    private static StringBuilder format(float fv) {
        int pos = 0;
        boolean addDot = false;
        int v = Math.round(fv * 100);
        boolean isNeg = v < 0;
        v = isNeg ? -v : v;
        for (int i = 0; i < 2; ++i) {
            int digit = v % 10;
            v /= 10;
            if (digit != 0 || addDot) {
                buf[pos++] = (char) ('0' + digit);
                addDot = true;
            }
        }
        if (addDot) {
            buf[pos++] = '.';
        }
        if (v == 0) {
            buf[pos++] = '0';
        }
        while (v != 0) {
            buf[pos++] = (char) ('0' + (v % 10));
            v /= 10;
        }
        if (isNeg) {
            buf[pos++] = '-';
        }
        b.setLength(0);
        b.append(buf, 0, pos);
        b.reverse();
        return b;
    }

    private void drawGraph(Canvas canvas) {
        long t1 = System.currentTimeMillis();
        float minX = currentX - gwidth / 2;
        float maxX = minX + gwidth;
        float ywidth = gwidth * height / width;
        float minY = currentY - ywidth / 2;
        float maxY = minY + ywidth;
        if (minY < boundMinY || maxY > boundMaxY) {
            float halfw = ywidth / 2;
            boundMinY = minY - halfw;
            boundMaxY = maxY + halfw;
            clearAllGraph();
        }

        canvas.drawColor(0xff000000);

        paint.setStrokeWidth(0);
        paint.setAntiAlias(false);
        paint.setStyle(Paint.Style.STROKE);

        final float h2 = height / 2f;
        final float scale = width / gwidth;

        float x0 = -minX * scale;
        boolean drawYAxis = true;
        if (x0 < 25) {
            x0 = 25;
            // drawYAxis = false;
        } else if (x0 > width - 3) {
            x0 = width - 3;
            // drawYAxis = false;
        }
        float y0 = maxY * scale;
        if (y0 < 3) {
            y0 = 3;
        } else if (y0 > height - 15) {
            y0 = height - 15;
        }

        final float tickSize = 3;
        final float y2 = y0 + tickSize;
        paint.setColor(COL_GRID);
        float step = stepFactor(gwidth);
        float v = ((int) (minX / step)) * step;
        textPaint.setColor(COL_TEXT);
        textPaint.setTextSize(12);
        textPaint.setTextAlign(Paint.Align.CENTER);
        float stepScale = step * scale;
        for (float x = (v - minX) * scale; x <= width; x += stepScale, v += step) {
            canvas.drawLine(x, 0, x, height, paint);
            if (!(-.001f < v && v < .001f)) {
                StringBuilder b = format(v);
                canvas.drawText(b, 0, b.length(), x, y2 + 10, textPaint);
            }
        }

        final float x1 = x0 - tickSize;
        v = ((int) (minY / step)) * step;
        textPaint.setTextAlign(Paint.Align.RIGHT);
        for (float y = height - (v - minY) * scale; y >= 0; y -= stepScale, v += step) {
            canvas.drawLine(0, y, width, y, paint);
            if (!(-.001f < v && v < .001f)) {
                StringBuilder b = format(v);
                canvas.drawText(b, 0, b.length(), x1, y + 4, textPaint);
            }
        }

        paint.setColor(COL_AXIS);
        if (drawYAxis) {
            canvas.drawLine(x0, 0, x0, height, paint);
        }
        canvas.drawLine(0, y0, width, y0, paint);

        matrix.reset();
        matrix.preTranslate(-currentX, -currentY);
        matrix.postScale(scale, -scale);
        matrix.postTranslate(width / 2, height / 2);

        paint.setStrokeWidth(0);
        paint.setAntiAlias(false);

        int n = Math.min(funcs.size(), GRAPHS_SIZE);
        for (int i = 0; i < n; ++i) {
            computeGraph(funcs.get(i), minX, maxX, boundMinY, boundMaxY,
                    graphs[i]);
            Path path = graphToPath(graphs[i]);
            path.transform(matrix);
            paint.setColor(COL_GRAPH[i]);
            canvas.drawPath(path, paint);
        }
        lastMinX = minX;
    }

    private boolean canZoomIn() {
        return gwidth > 1f;
    }

    private boolean canZoomOut() {
        return gwidth < 50;
    }

    private void invalidateGraphs() {
        clearAllGraph();
        boundMinY = boundMaxY = 0;
        invalidate();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return touchHandler != null ? touchHandler.onTouchEvent(event) : super
                .onTouchEvent(event);
    }

    public void onTouchDown(float x, float y) {
        zoomController.setVisible(true);
        if (!scroller.isFinished()) {
            scroller.abortAnimation();
        }
        lastTouchX = x;
        lastTouchY = y;
    }

    public void onTouchMove(float x, float y) {
        float deltaX = x - lastTouchX;
        float deltaY = y - lastTouchY;
        if (deltaX < -1 || deltaX > 1 || deltaY < -1 || deltaY > 1) {
            scroll(-deltaX, deltaY);
            lastTouchX = x;
            lastTouchY = y;
            invalidate();
        }
    }

    public void onTouchUp(float x, float y) {
        final float scale = width / gwidth;
        float sx = -touchHandler.velocityTracker.getXVelocity();
        float sy = touchHandler.velocityTracker.getYVelocity();
        final float asx = Math.abs(sx);
        final float asy = Math.abs(sy);
        if (asx < asy / 3) {
            sx = 0;
        } else if (asy < asx / 3) {
            sy = 0;
        }
        scroller.fling(Math.round(currentX * scale),
                Math.round(currentY * scale), Math.round(sx), Math.round(sy),
                -10000, 10000, -10000, 10000);
        invalidate();
    }

    public void onTouchZoomDown(float x1, float y1, float x2, float y2) {
        zoomTracker.start(gwidth, x1, y1, x2, y2);
    }

    public void onTouchZoomMove(float x1, float y1, float x2, float y2) {
        if (!zoomTracker.update(x1, y1, x2, y2)) {
            return;
        }
        float targetGwidth = zoomTracker.value;
        if (targetGwidth > .25f && targetGwidth < 200) {
            gwidth = targetGwidth;
        }
        invalidateGraphs();
    }

    private void scroll(float deltaX, float deltaY) {
        final float scale = gwidth / width;
        float dx = deltaX * scale;
        float dy = deltaY * scale;
        final float adx = Math.abs(dx);
        final float ady = Math.abs(dy);
        if (adx < ady / 3) {
            dx = 0;
        } else if (ady < adx / 3) {
            dy = 0;
        }
        currentX += dx;
        currentY += dy;
    }
}

The error Log of the XML editor

java.lang.NullPointerException
    at android.widget.ZoomButtonsController.createContainer(ZoomButtonsController.java:266)
    at android.widget.ZoomButtonsController.<init>(ZoomButtonsController.java:212)
    at calculator.GraphView.<init>(GraphView.java:43)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(    at sun.reflect.NativeConstructorAccessorImpl.newInstance(    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(    at java.lang.reflect.Constructor.newInstance(    at com.android.ide.eclipse.adt.internal.editors.layout.ProjectCallback.instantiateClass(ProjectCallback.java:422)
    at com.android.ide.eclipse.adt.internal.editors.layout.ProjectCallback.loadView(ProjectCallback.java:179)
    at android.view.BridgeInflater.loadCustomView(BridgeInflater.java:207)
    at android.view.BridgeInflater.createViewFromTag(BridgeInflater.java:135)
    at android.view.LayoutInflater.rInflate_Original(LayoutInflater.java:746)
    at android.view.LayoutInflater_Delegate.rInflate(LayoutInflater_Delegate.java:64)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:718)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:372)
AndreaF
  • 11,975
  • 27
  • 102
  • 168
  • 1
    See if [this](http://stackoverflow.com/questions/10743030/custom-android-views-in-eclipse-visual-editor) helps. The `new TouchHandler()` and `init()` should probably be inside the `if` statement. – A--C Mar 15 '13 at 01:31
  • I have tried this but doesn't works.... same error – AndreaF Mar 15 '13 at 14:23
  • mind posting the *full* GraphView class? – A--C Mar 15 '13 at 14:37
  • @A--C I have edited my question adding the full GraphView class – AndreaF Mar 15 '13 at 15:43
  • Lots of code, with too much custom implementation. I can only recommend looking at the Error Log (`Window -> Show View -> Error Log`) which should tell you why the View isn't being instantiated in the editor. You can also start with a blank View, then add to it piece by piece and see how the Visual Editor reacts. – A--C Mar 15 '13 at 15:51
  • I have added also the error log – AndreaF Mar 15 '13 at 16:21
  • I would recommend doing all the initialization of the global variables in `init()` and putting `init()` in the `if(!isInEditMode()){` statement. – A--C Mar 15 '13 at 16:24
  • android studio just throws a bunch of null pointer errors, its not even friendly enough to tell you to use `isInEditMode`, which I just learned of from this question, that totally saves me, thank you – chiliNUT Apr 30 '15 at 07:08

4 Answers4

186

isInEditMode()should be used inside the Custom View constructor. Try the following code:

     public class GraphView extends View implements Grapher
        {

         public GraphView(Context context, AttributeSet attrs) {
                super(context, attrs);
                if(!isInEditMode())
                 init(context);
            }

            public GraphView(Context context) {
                super(context);
               if(!isInEditMode()){
                touchHandler = new TouchHandler(this);
                init(context);
              }
            }
JiTHiN
  • 6,548
  • 5
  • 43
  • 69
  • 3
    still its not working for me, even after rebuild, as i am using a coverflow which extends gallery, and it is giving me this error : java.lang.NoClassDefFoundError: Could not initialize class android.view.GestureDetector at android.widget.Gallery.(Gallery.java:202) at android.widget.Gallery.(Gallery.java:196) at com.winit.centurion.coverflow.CoverFlow.(CoverFlow.java:45) at sun.reflect.NativeConstructorAccessorImpl.newInstance0( at sun.reflect.NativeConstructorAccessorImpl.newInstance( at sun.reflect.DelegatingConstructorAccessorImpl.newInstance( ... – Sri Krishna Dec 10 '13 at 18:58
8
public class CustomTextView extends TextView {

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

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

    if (!isInEditMode()) {
        createTypeface(context, attrs); //whatever added functionality you are trying to add to Widget, call that inside this condition. 
    }

}

public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}


//Typeface I wan to set to my Custom TextView It can be any other functionality of your choice

private void createTypeface(Context context, AttributeSet attrs) {

    TypedArray styledAttrs = context.obtainStyledAttributes(attrs,
            R.styleable.CustomTextView);
    String fontName = styledAttrs
            .getString(R.styleable.CustomTextView_Typeface);
    styledAttrs.recycle();

    if (fontName != null) {
        Typeface typeface = Typeface.createFromAsset(context.getAssets(),
                "fonts/" + fontName);

        setTypeface(typeface);
        styledAttrs.recycle();
    }
}

}
DeltaCap019
  • 6,532
  • 3
  • 48
  • 70
0

The following classes could not be instantiated: - com.google.android.gms.ads.AdView (Open Class, Show Exception, Clear Cache)

Tip: Use View.isInEditMode() in your custom views to skip code or show sample data when shown in the IDE. If this is an unexpected error you can also try to build the project, then manually refresh the layout.

Exception Details java.lang.NoClassDefFoundError: 
    com/google/android/gms/ads/R$styleable   at 
    com.google.android.gms.internal.ads.zzuq.<init>(com.google.android.gms:play-services-ads-lite@@18.3.0:45)   at com.google.android.gms.internal.ads.zzxl.<init>(com.google.android.gms:play-services-ads-lite@@18.3.0:30)   at com.google.android.gms.internal.ads.zzxl.<init>(com.google.android.gms:play-services-ads-lite@@18.3.0:52)   at com.google.android.gms.internal.ads.zzxl.

<init>(com.google.android.gms:play-services-ads-lite@@18.3.0:17)   at com.google.android.gms.ads.BaseAdView.<init>(com.google.android.gms:play-services-ads-lite@@18.3.0:5)   at com.google.android.gms.ads.AdView.<init>(com.google.android.gms:play-services-ads-lite@@18.3.0:4)   at java.lang.reflect.Constructor.newInstance(Constructor.java:423)   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)   at android.view.LayoutInflater.rInflate_Original(LayoutInflater.java:863)   at android.view.LayoutInflater_Delegate.rInflate(LayoutInflater_Delegate.java:72)   at android.view.LayoutInflater.rInflate(LayoutInflater.java:837)   at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)   at android.view.LayoutInflater.inflate(LayoutInflater.java:515)   at android.view.LayoutInflater.inflate(LayoutInflater.java:394) Copy stack to clipboard

Community
  • 1
  • 1
gogo go
  • 1
  • 1
-25

Try this it work for me

public class MyOwnTextView extends TextView {

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

    public MyOwnTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
        isInEditMode();
    }
    public MyOwnTextView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
        isInEditMode();
    }

    public void setTypeface(Typeface tf, int style) {
        if(!this.isInEditMode()){
        Typeface normalTypeface = Typeface.createFromAsset(getContext().getAssets(), "font/Roboto-Light.ttf");
        Typeface boldTypeface = Typeface.createFromAsset(getContext().getAssets(), "font/Roboto-Light.ttf");

        if (style == Typeface.BOLD) {
            super.setTypeface(boldTypeface/*, -1*/);
        } else {
            super.setTypeface(normalTypeface/*, -1*/);
        }
        }

    }   

}

then at the xml

<com.xxxxx.appname.MyOwnTextView

          android:layout_width="fill_parent"
          android:layout_height="fill_parent"

        />
joe1327
  • 119
  • 6
  • 10
    this seems to be wrong. "isInEditMode()" returns true/false and should be used to not set up functionality not useful during editing. in your example you just call it and dont act on the return value. – phlebotinum May 19 '14 at 14:09