如何在布局xml中使用自定义视图

时间:2011-10-17 14:13:08

标签: android xml layout custom-view

我创建了一个自定义布局来显示gif动画图像。  这是代码:

public class GIFView extends View{        
private Movie movie;  
private InputStream is;  
private long moviestart;  
private long duration;

public GIFView(Context context) {  
    super(context);
    is=getResources().openRawResource(R.drawable.anim_cerca);  
    movie=Movie.decodeStream(is);
    duration = movie.duration();
}  

public GIFView(Context context,AttributeSet set){
    super(context,set);
    is=getResources().openRawResource(R.drawable.anim_cerca);  
    movie=Movie.decodeStream(is);
    duration = movie.duration();
}

public GIFView(Context context,AttributeSet set,int def){
    super(context,set,def);
    is=getResources().openRawResource(R.drawable.anim_cerca);  
    movie=Movie.decodeStream(is);
    duration = movie.duration();
}

@Override  
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    long now=android.os.SystemClock.uptimeMillis();
    Paint p = new Paint();
    p.setAntiAlias(true);
    if (moviestart == 0) 
        moviestart = now;

    int relTime = (int)((now - moviestart) % duration);

    movie.setTime(relTime);
    movie.draw(canvas,0,0);


    this.invalidate();
}                         
}  

这是我放置此对象的xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent" android:background="@drawable/sfondo">
<LinearLayout android:id="@+id/linearLayout2"
    android:layout_height="wrap_content" android:layout_width="match_parent"
    android:orientation="vertical">
    <LinearLayout android:id="@+id/linearLayout1"
        android:layout_height="fill_parent" android:weightSum="1"
        android:layout_width="fill_parent" android:orientation="horizontal">
        <ImageView android:layout_height="73dp" android:id="@+id/imageView1"
            android:layout_weight="0.25" android:src="@drawable/trovachiavi"
            android:layout_width="256dip"></ImageView>
        <ImageButton android:id="@+id/infoButton"
            android:background="@null" android:layout_height="47dp"
            android:layout_marginLeft="10dip" android:layout_weight="0.25"
            android:layout_marginTop="15dip" android:src="@drawable/info_mini"
            android:layout_width="47dp"></ImageButton>
    </LinearLayout>
</LinearLayout>
<LinearLayout android:id="@+id/layoutGIF"
    android:layout_height="wrap_content" android:layout_width="wrap_content"
    android:orientation="vertical">
    <com.digit.GIFView android:id="@+id/gIFView1"
        android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:layout_gravity="center"></com.digit.GIFView>
</LinearLayout>
<ImageButton android:id="@+id/avvia_cerca"
    android:layout_height="wrap_content" android:layout_width="wrap_content"
    android:layout_marginTop="10dp" android:layout_gravity="center|bottom"
    android:background="@null"></ImageButton>
</LinearLayout>

当我进入xml的图形布局区域时,出现错误:

The following classes could not be instantiated:
-  (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.NullPointerException
at com.digit.GIFView.<init>(GIFView.java:27)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at com.android.ide.eclipse.adt.internal.editors.layout.ProjectCallback.instantiateClass(ProjectCallback.java:396)
at com.android.ide.eclipse.adt.internal.editors.layout.ProjectCallback.loadView(ProjectCallback.java:164)
at com.android.layoutlib.bridge.android.BridgeInflater.loadCustomView(BridgeInflater.java:205)
at com.android.layoutlib.bridge.android.BridgeInflater.createViewFromTag(BridgeInflater.java:133)
at android.view.LayoutInflater_Delegate.rInflate(LayoutInflater_Delegate.java:83)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:702)
at android.view.LayoutInflater_Delegate.rInflate(LayoutInflater_Delegate.java:86)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:702)
at android.view.LayoutInflater.inflate(LayoutInflater.java:479)
at android.view.LayoutInflater.inflate(LayoutInflater.java:367)
at com.android.layoutlib.bridge.impl.RenderSessionImpl.inflate(RenderSessionImpl.java:324)
at com.android.layoutlib.bridge.Bridge.createSession(Bridge.java:321)
at com.android.ide.common.rendering.LayoutLibrary.createSession(LayoutLibrary.java:325)
at com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderService.createRenderSession(RenderService.java:380)
at com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart.renderWithBridge(GraphicalEditorPart.java:1310)
at com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart.recomputeLayout(GraphicalEditorPart.java:1075)
at com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart.activated(GraphicalEditorPart.java:901)
at com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditor.partActivated(LayoutEditor.java:416)
at com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditor.partBroughtToTop(LayoutEditor.java:425)
at org.eclipse.ui.internal.PartListenerList$2.run(PartListenerList.java:87)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.core.runtime.Platform.run(Platform.java:888)
at org.eclipse.ui.internal.PartListenerList.fireEvent(PartListenerList.java:57)
at org.eclipse.ui.internal.PartListenerList.firePartBroughtToTop(PartListenerList.java:85)
at org.eclipse.ui.internal.PartService.firePartBroughtToTop(PartService.java:208)
at org.eclipse.ui.internal.WorkbenchPagePartList.firePartBroughtToTop(WorkbenchPagePartList.java:76)
at org.eclipse.ui.internal.WorkbenchPagePartList.fireActiveEditorChanged(WorkbenchPagePartList.java:52)
at org.eclipse.ui.internal.PartList.setActiveEditor(PartList.java:162)
at org.eclipse.ui.internal.WorkbenchPage.makeActiveEditor(WorkbenchPage.java:1281)
at org.eclipse.ui.internal.WorkbenchPage.setActivePart(WorkbenchPage.java:3530)
at org.eclipse.ui.internal.WorkbenchPage.requestActivation(WorkbenchPage.java:3077)
at org.eclipse.ui.internal.PartPane.requestActivation(PartPane.java:279)
at org.eclipse.ui.internal.EditorPane.requestActivation(EditorPane.java:98)
at org.eclipse.ui.internal.PartPane.setFocus(PartPane.java:325)
at org.eclipse.ui.internal.EditorPane.setFocus(EditorPane.java:127)
at org.eclipse.ui.internal.PartStack.presentationSelectionChanged(PartStack.java:844)
at org.eclipse.ui.internal.PartStack.access$1(PartStack.java:827)
at org.eclipse.ui.internal.PartStack$1.selectPart(PartStack.java:137)
at org.eclipse.ui.internal.presentations.util.TabbedStackPresentation$1.handleEvent(TabbedStackPresentation.java:133)
at org.eclipse.ui.internal.presentations.util.AbstractTabFolder.fireEvent(AbstractTabFolder.java:269)
at org.eclipse.ui.internal.presentations.util.AbstractTabFolder.fireEvent(AbstractTabFolder.java:278)
at org.eclipse.ui.internal.presentations.defaultpresentation.DefaultTabFolder.access$1(DefaultTabFolder.java:1)
at org.eclipse.ui.internal.presentations.defaultpresentation.DefaultTabFolder$2.handleEvent(DefaultTabFolder.java:88)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Display.sendEvent(Display.java:3783)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1375)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1398)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1383)
at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:1195)
at org.eclipse.swt.custom.CTabFolder.setSelection(CTabFolder.java:2743)
at org.eclipse.swt.custom.CTabFolder.onMouse(CTabFolder.java:1429)
at org.eclipse.swt.custom.CTabFolder$1.handleEvent(CTabFolder.java:257)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Display.sendEvent(Display.java:3783)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1375)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1398)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1383)
at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:1195)
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3629)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3284)
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2640)
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2604)
at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2438)
at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:671)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:664)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:115)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:369)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:620)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:575)
at org.eclipse.equinox.launcher.Main.run(Main.java:1408)

我该怎么办?错误在哪里诞生? 我的自定义视图下的元素不会显示!

5 个答案:

答案 0 :(得分:3)

你的一个构造函数中有一个NullPointerException。我无法准确地告诉哪一个,正如StackTrace所说的第27行,这是你发布的代码中的空行。

您应该重新运行代码,检查代码中堆栈跟踪的第一行。我猜这就是这条线:

duration = movie.duration();

并且movie对象为空。

答案 1 :(得分:2)

问题不在于您的代码,而是在图形布局中显示自定义视图。绘图视图依赖于设备功能。要正确查看自定义视图,您必须使用isInEditMode()方法 在您的自定义视图实现中。基于该方法,您必须实现替代初始化和绘图。

答案 2 :(得分:1)

我认为你希望你的xml文件对象是这样的:

<com.spazio.digitale.GIFView android:id="@+id/gIFView1"
    android:layout_width="wrap_content" android:layout_height="wrap_content"
    android:layout_gravity="center" />

假设您的软件包是com.spazio.digitale,我对您发布的内容并不完全确定。

答案 3 :(得分:0)

试试这个对我有用

public class MyOwnTextView extends TextView {

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

    }

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

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

    }

    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*/);
        }
        }

    }   

}

然后在xml

<com.xxxxx.appname.MyOwnTextView

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

        />

答案 4 :(得分:0)

我的问题是ttf字体被放置在assets文件夹下的自定义“fonts”文件夹中。 显示xml布局时出错:

The following classes could not be instantiated:
----
Tip: Use View.isInEditMode() in your custom views to skip code when shown...

然后,我将字体放在根资产文件夹下,重建了项目,神奇地说,所有的工作和xml布局都显示正常。

然后,我再次通过ide,重建项目将字体拖到“fonts”文件夹中,xml布局仍然显示正常。

我不知道为什么这个操作有效,但是如果它可以帮助任何人,那么。