2011-04-29 7 views
8

Tengo SurfaceView de Android y estoy tratando de agregar botones a esto. En el lienzo de vista de superficie dibujo algo. Y tengo una clase de subprocesos para seguir dibujando.Android: Crash: línea de archivo XML binario: error al inflar la clase (con SurfaceView)

package com.androidsurfaceview; 

import android.app.Activity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.Button; 

public class androidsurfaceview extends Activity { 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     Button buttonShowHide = (Button)findViewById(R.id.showhide); 
     final Button buttonDummy = (Button)findViewById(R.id.dummy); 

     buttonShowHide.setOnClickListener(
       new Button.OnClickListener(){ 

        @Override 
        public void onClick(View arg0) { 
         // TODO Auto-generated method stub 
         if(buttonDummy.getVisibility()==View.VISIBLE){ 
          buttonDummy.setVisibility(View.GONE); 
         } 
         else{ 
          buttonDummy.setVisibility(View.VISIBLE); 
         } 
        } 

       } 
     ); 

La clase hilo

package com.androidsurfaceview; 

import android.graphics.Canvas; 
import android.view.SurfaceHolder; 
public class MySurfaceThread extends Thread { 
    private SurfaceHolder myThreadSurfaceHolder; 
    private com.androidsurfaceview.test.MySurfaceView myThreadSurfaceView; 
    private boolean myThreadRun = false; 

    public MySurfaceThread(SurfaceHolder surfaceHolder, com.androidsurfaceview.test.MySurfaceView surfaceView) { 
     myThreadSurfaceHolder = surfaceHolder; 
     myThreadSurfaceView = surfaceView; 
    } 

    public void setRunning(boolean b) { 
     myThreadRun = b; 
    } 

    @Override 
    public void run() { 
     // TODO Auto-generated method stub 
     while(myThreadRun){ 
      Canvas c = null; 

      try{ 
       c = myThreadSurfaceHolder.lockCanvas(null); 
       synchronized (myThreadSurfaceHolder){ 
        myThreadSurfaceView.onDraw(c); 
       } 
       sleep(100); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
      finally{ 
       // do this in a finally so that if an exception is thrown 
       // during the above, we don't leave the Surface in an 
       // inconsistent state 
       if (c != null) { 
        myThreadSurfaceHolder.unlockCanvasAndPost(c); 
       } 
      } 
     } 
    } 
} 

El SurfaceView & la clase para la elaboración

package com.androidsurfaceview; 

import android.app.Activity; 
import android.content.Context; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.util.AttributeSet; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 

public class test extends Activity{ 

     //  ...... 
     // I do a few things here... with this class test. 

    public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback{ 

     private MySurfaceThread thread; 
     private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); 
     int cx, cy, offx, offy; 

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

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

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

     private void init(){ 
       getHolder().addCallback(this); 
       thread = new MySurfaceThread(getHolder(), this); 

       setFocusable(true); // make sure we get key events 

       paint.setStyle(Paint.Style.STROKE); 
       paint.setStrokeWidth(3); 
       paint.setColor(Color.WHITE); 

       cx = 0; 
       cy = 0; 
       offx = 10; 
       offy = 10; 

      } 

     @Override 
     public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { 
      // TODO Auto-generated method stub 

     } 

     @Override 
     public void surfaceCreated(SurfaceHolder holder) { 
      // TODO Auto-generated method stub 
      thread.setRunning(true); 
      thread.start(); 

     } 

     @Override 
     public void surfaceDestroyed(SurfaceHolder holder) { 
      // TODO Auto-generated method stub 
      boolean retry = true; 
      thread.setRunning(false); 
      while (retry) { 
       try { 
        thread.join(); 
        retry = false; 
       } 
       catch (InterruptedException e) { 
       } 
      } 
     } 
    ////Just a simple graphic of moving circle. 
     @Override 
     protected void onDraw(Canvas canvas) { 
      // TODO Auto-generated method stub 
      canvas.drawRGB(0, 0, 0); 
      canvas.drawCircle(cx, cy, 3, paint); 
      cx += offx; 
      if (cx > getWidth() || (cx < 0)){ 
       offx *= -1; 
       cx += offx; 
      } 

      cy += offy; 
      if (cy > getHeight() || (cy < 0)){ 
       offy *= -1; 
       cy += offy; 
      } 
     } 
    } 
    } 

Aquí es el main.xml

<?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"> 
<Button 
    android:id="@+id/showhide" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Toggle The Another Button Show/Hide" /> 
<Button 
    android:id="@+id/dummy" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="a Button" /> 
<FrameLayout 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"> 

<com.androidsurfaceview.test.MySurfaceView 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"/> 

</FrameLayout> 
</LinearLayout> 

PROBLEMA: El código anterior funciona SOLAMENTE si no tengo el "MySurfaceView" como clase anidada. pero con la clase "prueba" aparece el siguiente error. Si elimino el "prueba de clase" , funciona bien.

error/Crash

04-29 11:43:18.977: ERROR/AndroidRuntime(21832): FATAL EXCEPTION: main 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.androidsurfaceview/com.androidsurfaceview.androidsurfaceview}: **android.view.InflateException: Binary XML file line #20: Error inflating class com.androidsurfaceview.test.MySurfaceView** 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663) 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679) 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at android.app.ActivityThread.access$2300(ActivityThread.java:125) 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033) 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at android.os.Handler.dispatchMessage(Handler.java:99) 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at android.os.Looper.loop(Looper.java:123) 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at android.app.ActivityThread.main(ActivityThread.java:4627) 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at java.lang.reflect.Method.invokeNative(Native Method) 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at java.lang.reflect.Method.invoke(Method.java:521) 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at dalvik.system.NativeStart.main(Native Method) 
**04-29 11:43:18.977: ERROR/AndroidRuntime(21832): Caused by: android.view.InflateException: Binary XML file line #20: Error inflating class com.androidsurfaceview.test.MySurfaceView** 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:576) 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at android.view.LayoutInflater.rInflate(LayoutInflater.java:618) 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at android.view.LayoutInflater.rInflate(LayoutInflater.java:621) 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at android.view.LayoutInflater.inflate(LayoutInflater.java:407) 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at android.view.LayoutInflater.inflate(LayoutInflater.java:320) 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at android.view.LayoutInflater.inflate(LayoutInflater.java:276) 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:200) 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at android.app.Activity.setContentView(Activity.java:1647) 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at com.androidsurfaceview.androidsurfaceview.onCreate(androidsurfaceview.java:13) 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) 
04-29 11:43:18.977: ERROR/AndroidRuntime(21832):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627) 

Cualquier ayuda será muy bueno ... estoy atascado con esto.

+0

Creo que no puede encontrar la clase si tengo "MySurfaceView" como clase anidada/interna. Algunas ideas ! – m4n07

+0

¿De verdad tienes esa clase en ese paquete? ¡porque sigues nombrando tus clases después de la convención de nomenclatura del paquete, y en tu núcleo compartido no hay ninguna declaración de paquete! Si está utilizando el paquete predeterminado, intente ' rekaszeru

+0

Lo siento, olvidé de agregar. Actualizado con detalles del paquete. – m4n07

Respuesta

11

En primer lugar, debe declarar su punto de vista como un tipo static, para poder ser inflado incluso cuando no hay instancia de la clase de retención está disponible:

public static class MySurfaceView extends SurfaceView 
    implements SurfaceHolder.Callback 

La línea

<com.androidsurfaceview.test.MySurfaceView 

en su diseño, xml sugiere que la clase MySurfaceView está dentro del paquete com.androidsurfaceview.test e intenta inflarla desde allí, lo cual es incorrecto.

En su diseño debe seguir el package.class $ innerclass forma de declaración.

PERO ya que el "$" es de carácter ilegal, no se puede escribir

<com.androidsurfaceview.test$MySurfaceView 

lo que debe especificar su punto de vista en el xml diseño de la siguiente manera:

<view class="com.androidsurfaceview.test$MySurfaceView" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"/> 

Esta manera de que funcione.

+0

Muchas gracias! Funcionó. También intenté hacer la clase estática inicialmente.Pero no sabía que tenía que darle con clase de vista y $. ¿Recomiendas algún tutorial o libro donde pueda aprender? – m4n07

+1

He aprendido mucho leyendo los [temas interesantes de los Desarrolladores de Android] (http://developer.android.com/guide/topics/ui/index.html), pero hay muchos tutoriales y muestras. Mis favoritos son los trucos de @Renaun Ericksson y los ejemplos de @CommonsWare. – rekaszeru

+0

Muchas gracias! Trataré de revisarlos. – m4n07

Cuestiones relacionadas