摘要:在 eclipse 中 Android 工程的自定义 View 中的一些代码在 Graphical Layout 中无法显示的原因是:当前部分代码的所处的 Graphical Layout 预览模式下是无法提供其运行的环境,所以导致自定义 View 无法在 Graphical Layout 上面显示。
OS: Windows 8.1
IDE: ADT Bundle v22.6.2
Device: Nexus 5 / Android 4.4.4
在 eclipse 中调试 Android 项目,出现自定义 View 在 Graphical Layout 中无法显示,错误提示如下:
The graphics preview in the layout editor may not be accurate: Typeface.createFromAsset() is not supported. (Ignore for this session) The following classes could not be instantiated: - com.ifeegoo.debug.customviews.CustomFontFangZhengXiHeiTextView (Open Class, Show Error Log) See the Error Log (Window > Show View) for more details. Tip: Use View.isInEditMode() in your custom views to skip code when shown in Eclipse java.lang.RuntimeException: native typeface cannot be made at android.graphics.Typeface.<init>(Typeface.java:175) at android.graphics.Typeface.createFromAsset(Typeface.java:149) at com.ifeegoo.debug.customviews.CustomFontFangZhengXiHeiTextView.<init>(CustomFontFangZhengXiHeiTextView.java:28) at sun.reflect.GeneratedConstructorAccessor34.newInstance( at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:408) at com.android.ide.eclipse.adt.internal.editors.layout.ProjectCallback.instantiateClass(ProjectCallback.java:437) at com.android.ide.eclipse.adt.internal.editors.layout.ProjectCallback.loadView(ProjectCallback.java:189) at android.view.BridgeInflater.loadCustomView(BridgeInflater.java:207) at android.view.BridgeInflater.createViewFromTag(BridgeInflater.java:135) at android.view.LayoutInflater.rInflate_Original(LayoutInflater.java:755) at android.view.LayoutInflater_Delegate.rInflate(LayoutInflater_Delegate.java:64) at android.view.LayoutInflater.rInflate(LayoutInflater.java:727) at android.view.LayoutInflater.inflate(LayoutInflater.java:492) at android.view.LayoutInflater.inflate(LayoutInflater.java:373)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.ifeegoo.debug.activities.MainActivity" > <com.ifeegoo.debug.customviews.CustomFontFangZhengXiHeiTextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center" android:textSize="50dp" android:text="ifeegoo" /> </LinearLayout>
我们找到报错的代码:
/** * * @author ifeegoo www.ifeegoo.com * */ public class CustomFontFangZhengXiHeiTextView extends TextView { public CustomFontFangZhengXiHeiTextView(Context context) { super(context); } public CustomFontFangZhengXiHeiTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.setTypeface(Typeface.createFromAsset(context.getAssets(), "font/fang_zheng_xi_hei.ttf")); } public CustomFontFangZhengXiHeiTextView(Context context, AttributeSet attrs) { super(context, attrs); this.setTypeface(Typeface.createFromAsset(context.getAssets(), "font/Cuisine.ttf")); } }
我们再来看看提示的这个 View.isInEditMode() 这个方法:
/** * Indicates whether this View is currently in edit mode. A View is usually * in edit mode when displayed within a developer tool. For instance, if * this View is being drawn by a visual user interface builder, this method * should return true. * * Subclasses should check the return value of this method to provide * different behaviors if their normal behavior might interfere with the * host environment. For instance: the class spawns a thread in its * constructor, the drawing code relies on device-specific features, etc. * * This method is usually checked in the drawing code of custom widgets. * * @return True if this View is in edit mode, false otherwise. */ public boolean isInEditMode() { return false; }
以上方法的说明如下:
1.表示当前 View 是否处于编辑模式。一般来说,在开发者工具中显示时,这个 View 就是处于编辑模式。例如,如果这个 View 是通过可视的用户接口生成器绘制的话,这个方法应当返回 true。
2.如果说 View 的一般状态可能受到宿主环境的干扰,那么子类就应当校验这个方法的返回值以提供不同的状态。例如,在子类的构造器中创建一个线程, 或者绘制代码依赖于设备指定特性等。
3.通常这个方法在自定义控件绘制代码中被校验。
4.return True 如果当前 View 处于编辑模式, false 当前 View 处于非编辑模式。
以上内容大概的意思就是:在 eclipse 中 Android 工程的自定义 View 中的一些代码在 Graphical Layout 中无法显示的原因是:当前部分代码的所处的 Graphical Layout 预览模式下是无法提供其运行的环境,所以导致自定义 View 无法在 Graphical Layout 上面显示,事实也证明了这一点,我们在真机 Nexus 5 / Android 4.4.4 上显示没有问题:
然后 Graphical Layout 提供的意见是通过判断当前代码的运行环境是否处于编辑模式,来禁止编译由于运行环境的不支持导致的编译不通过,从而影响当前自定义 View 在 Graphical Layout 中的预览。代码如下:
/** * * @author ifeegoo www.ifeegoo.com * */ public class CustomFontFangZhengXiHeiTextView extends TextView { public CustomFontFangZhengXiHeiTextView(Context context) { super(context); } public CustomFontFangZhengXiHeiTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); if (!this.isInEditMode()) { this.setTypeface(Typeface.createFromAsset(context.getAssets(), "font/fang_zheng_xi_hei.ttf")); } } public CustomFontFangZhengXiHeiTextView(Context context, AttributeSet attrs) { super(context, attrs); if (!this.isInEditMode()) { this.setTypeface(Typeface.createFromAsset(context.getAssets(), "font/Cuisine.ttf")); } } }
然后 Graphical Layout 中的预览效果如下图,显然是没有将自定义字体效果展示出来,但是这样也就解决了在不需要预览实际自定义字体效果的前提下的不能预览自定义 View 的问题,同时也不会对其它控件的显示有干扰。
我们在真机 Nexus 5 / Android 4.4.4 上显示的效果依然一样: