mikepenz / Android-Iconics

Android-Iconics - Use any icon font, or vector (.svg) as drawable in your application.
https://mikepenz.dev
Apache License 2.0
5.2k stars 615 forks source link

Issue while previewing the layout xml in Android Studio #107

Closed thekalinga closed 8 years ago

thekalinga commented 8 years ago

I have added the image to the custom component using

new IconicsDrawable(context)
                    .icon(GoogleMaterial.Icon.gmd_keyboard)
                    .color(getResources().getColor(R.color.button_default))
                    .sizeDp(R.dimen.default_icon_size)

Tho, I am able to see the icon in the actual application, the Android Studio previewer complains that the font/material-design-iconic-font-v2.2.0.ttf could not be found. So I added the font material-design-iconic-font-v2.2.0.ttf explicitly to my assets/fonts, along with the gradle dependency. After this change, I get the following exception in the Studio previewer

java.awt.geom.IllegalPathStateException: missing initial moveto in path definition
    at java.awt.geom.Path2D$Float.needRoom(Path2D.java:323)
    at java.awt.geom.Path2D.closePath(Path2D.java:1876)
    at android.graphics.Path_Delegate.close(Path_Delegate.java:782)
    at android.graphics.Path_Delegate.native_close(Path_Delegate.java:318)
    at android.graphics.Path.native_close(Path.java)
    at android.graphics.Path.close(Path.java:480)
    at com.mikepenz.iconics.IconicsDrawable.draw(IconicsDrawable.java:749)
    at android.view.View.drawBackground(View.java:16370)
    at android.view.View.draw(View.java:16169)
    at android.view.View.draw(View.java:16090)
    at android.view.ViewGroup.drawChild_Original(ViewGroup.java:3609)
    at android.view.ViewGroup_Delegate.drawChild(ViewGroup_Delegate.java:61)
    at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
    at android.view.View.draw(View.java:16088)
    at android.view.ViewGroup.drawChild_Original(ViewGroup.java:3609)
    at android.view.ViewGroup_Delegate.drawChild(ViewGroup_Delegate.java:61)
    at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
    at android.view.View.draw(View.java:16088)
    at android.view.ViewGroup.drawChild_Original(ViewGroup.java:3609)
    at android.view.ViewGroup_Delegate.drawChild(ViewGroup_Delegate.java:61)
    at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
    at android.view.View.draw(View.java:16181)
    at android.view.View.draw(View.java:16090)
    at android.view.ViewGroup.drawChild_Original(ViewGroup.java:3609)
    at android.view.ViewGroup_Delegate.drawChild(ViewGroup_Delegate.java:61)
    at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
    at android.view.View.draw(View.java:16088)
    at android.view.ViewGroup.drawChild_Original(ViewGroup.java:3609)
    at android.view.ViewGroup_Delegate.drawChild(ViewGroup_Delegate.java:61)
    at android.view.ViewGroup.drawChild(ViewGroup.java:3609)
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399)
    at android.view.View.draw(View.java:16181)
    at com.android.layoutlib.bridge.impl.RenderSessionImpl.render(RenderSessionImpl.java:431)
    at com.android.layoutlib.bridge.Bridge.createSession(Bridge.java:428)
    at com.android.ide.common.rendering.LayoutLibrary.createSession(LayoutLibrary.java:350)
    at com.android.tools.idea.rendering.RenderTask$2.compute(RenderTask.java:510)
    at com.android.tools.idea.rendering.RenderTask$2.compute(RenderTask.java:498)
    at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:888)
    at com.android.tools.idea.rendering.RenderTask.createRenderSession(RenderTask.java:498)
    at com.android.tools.idea.rendering.RenderTask.access$600(RenderTask.java:72)
    at com.android.tools.idea.rendering.RenderTask$3.call(RenderTask.java:610)
    at com.android.tools.idea.rendering.RenderTask$3.call(RenderTask.java:607)
    at com.android.tools.idea.rendering.RenderService.runRenderAction(RenderService.java:366)
    at com.android.tools.idea.rendering.RenderTask.render(RenderTask.java:607)
    at com.android.tools.idea.rendering.RenderTask.render(RenderTask.java:629)
    at org.jetbrains.android.uipreview.AndroidLayoutPreviewToolWindowManager.doRender(AndroidLayoutPreviewToolWindowManager.java:652)
    at org.jetbrains.android.uipreview.AndroidLayoutPreviewToolWindowManager.access$1700(AndroidLayoutPreviewToolWindowManager.java:80)
    at org.jetbrains.android.uipreview.AndroidLayoutPreviewToolWindowManager$7$1.run(AndroidLayoutPreviewToolWindowManager.java:594)
    at com.intellij.openapi.progress.impl.CoreProgressManager$2.run(CoreProgressManager.java:152)
    at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:452)
    at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:402)
    at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:54)
    at com.intellij.openapi.progress.impl.CoreProgressManager.runProcess(CoreProgressManager.java:137)
    at org.jetbrains.android.uipreview.AndroidLayoutPreviewToolWindowManager$7.run(AndroidLayoutPreviewToolWindowManager.java:589)
    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.concurrency.QueueProcessor.runSafely(QueueProcessor.java:238)
    at com.intellij.util.Alarm$Request$1.run(Alarm.java:351)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

Here is my gradle configuration

compile 'com.mikepenz:iconics-core:2.2.0@aar'
compile 'com.mikepenz:google-material-typeface:2.2.0.1@aar'
compile 'com.mikepenz:fontawesome-typeface:4.4.0.1@aar'
compile('com.mikepenz:materialdrawer:4.5.1@aar') {
    transitive = true
    exclude group: 'com.mikepenz', module: 'iconics-core'
}

and this is how I am plugging the wrapper into activity

@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(CalligraphyContextWrapper.wrap(IconicsContextWrapper.wrap(newBase)));
}

Are there steps that I need to follow to make sure that preview works?

mikepenz commented 8 years ago

@thekalinga you should not have to add the font to your project. that's already inside the project. icon fonts can't be painted from the preview in AS as far as i know, so you should disable adding the icon in the preview by checking:

if (!isInEditMode()) {

as in the IconicsImageView https://github.com/mikepenz/Android-Iconics/blob/develop/library-core/src/main/java/com/mikepenz/iconics/view/IconicsImageView.java#L52

to be fair i never used the AS preview :D i paint those xml's in my head. and now with instant run, running the app on a device is really fast :D

thekalinga commented 8 years ago

This library claims to work with Android Studio. Can you check this once

https://github.com/code-mc/material-icon-lib

Preview

mikepenz commented 8 years ago

@thekalinga because it does not use a Path to draw the icon, but directly uses a canvas. downside of their approach is that they do not offer a contour, etc...

I don't think the preview is really necessary. I will try a few things, perhaps i can get it to work but i can't promise it

thekalinga commented 8 years ago

Sure. Thanks for your prompt response

mikepenz commented 8 years ago

@thekalinga and you are sure it fails for you because of the stacktrace you showed and not because it can't resolve the font? i can't get it to read in the typeface. (changed the silent "null" return to throw the excaption inside the font)

thekalinga commented 8 years ago

I just renamed the font in my assets/fonts/material-design-iconic-font-v2.2.0.ttf to assets/fonts/material-design-iconic-font-v2.2.0.ttf.bak & this is the error I get

Asset not found: fonts/material-design-iconic-font-v2.2.0.ttf

If I rename the file back, I get the same exception trace I mentioned in the description.

I use ubuntu 14.04 & my Android studio details are

Android Studio 1.4.1
Build #AI-141.2343393, built on October 15, 2015
JRE: 1.8.0_66-b17 amd64
JVM: Java HotSpot(TM) 64-Bit Server VM by Oracle Corporation
mtrakal commented 8 years ago

Isn't it possible do it like in this post? http://stackoverflow.com/a/35266586/4024146 it looks like working solution without canvas and uses Path assets.

Maybe with step 0 from this lib: https://github.com/code-mc/material-icon-lib#step-0 ?

Robyer commented 7 years ago

@mikepenz Any news on this? Using isInEditingMode() "everywhere" in client code is not very user friendly. Isn't there any other solution to mute the exception directly in IconicsDrawable?

mikepenz commented 7 years ago

The icon already has isInEditingMode() @Robyer https://github.com/mikepenz/Android-Iconics/blob/develop/iconics-view-library/src/main/java/com/mikepenz/iconics/view/IconicsTextView.java#L48

Robyer commented 7 years ago

@mikepenz Your views are using isInEditingMode(), but I have custom view inside which I programmatically create new instance of IconicsDrawable and in that case preview shows error.

As possible solution I can see adding new method IconicsDrawable.setInEditingMode(boolean), because drawable obviously doesn't have that method itself. So I could set it once during initialization of my custom view, and thus doesn't have to wrap all usages of the drawable in if (isInEditingMode().

mikepenz commented 7 years ago

@Robyer please just add isInEditingMode() to your custom view as usual. Drawables don't have the inEditingMode your view is having the bug in the end.

Robyer commented 7 years ago

@mikepenz I don't think bug is in my view if exception is thrown when calling sizeDp(...) on IconicsDrawable.

This code:

IconicsDrawable drawable = new IconicsDrawable(context, icon); drawable.sizeDp(32);

Causes this exception in preview:

java.awt.geom.IllegalPathStateException: missing initial moveto in path definition at java.awt.geom.Path2D$Double.needRoom(Path2D.java:1192) at java.awt.geom.Path2D.closePath(Path2D.java:1876) at android.graphics.Path_Delegate.close(Path_Delegate.java:810) at android.graphics.Path_Delegate.native_close(Path_Delegate.java:325) at android.graphics.Path.native_close(Path.java) at android.graphics.Path.close(Path.java:495) at com.mikepenz.iconics.IconicsDrawable.onBoundsChange(IconicsDrawable.java:839) at android.graphics.drawable.Drawable.setBounds(Drawable.java:217) at com.mikepenz.iconics.IconicsDrawable.sizePx(IconicsDrawable.java:464) at com.mikepenz.iconics.IconicsDrawable.sizeDp(IconicsDrawable.java:452) (...)

You advises adding isInEditingMode() in my custom view, but that means not using IconicsDrawable at all when isEditingMode() returns true. Which is uncomfortable.

Having something like this IconicsDrawable.setInEditingMode(isInEditingMode()); and ignoring the exceptions internally would be great.

Also I read your comment saying:

because it does not use a Path to draw the icon, but directly uses a canvas. downside of their approach is that they do not offer a contour, etc...

So having ability to force drawing directly to canvas in case of isInEditingMode() to have working Preview, even without contours etc. would be even better. For example IconicsDrawable.useCompatibilityDrawing(isInEditingMode());

mikepenz commented 7 years ago

but that's the point of isInEditingMode disabling all components of your custom view, not working in the editor

mikepenz commented 7 years ago

@Robyer if you want to add something like IconicsDrawable.setInEditingMode(isInEditingMode()); to the library via a PR I am more than glad to merge it.

Robyer commented 6 years ago

@mikepenz I fixed the exception. See https://github.com/mikepenz/Android-Iconics/pull/364