【问题标题】:SurfaceView Custom Class xml?SurfaceView 自定义类 xml?
【发布时间】:2015-06-14 03:37:47
【问题描述】:

我对 Android 还很陌生,但我最近决定让自己熟悉动画。我很快发现我需要实现一个 SurfaceView 类。

现在,我的 ContentView 已设置为自定义 surfaceView 视图 (v)。我想将 surfaceView 放入主 xml 文件 (activity_surface_view_example.xml) 中的自定义布局中。

这是我的 Surface 类代码:

        package rdc.com.surfacegame;

/**
 * Created by Spenser on 15-04-09.
 */

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class Surface extends SurfaceView implements Runnable{
main m;
    Thread t;
    SurfaceHolder holder;
    boolean okQuestion = false;
    int a, b;    int x;



    public Surface(Context context, main m) {
        super(context);
        holder = getHolder();
        this.m=m;

    }

    @Override
    public void run() {


        while(okQuestion == true) {
            if (!holder.getSurface().isValid()) {
                continue;
            }

            Canvas c = holder.lockCanvas();
            c.drawColor(Color.GREEN);
            c.drawBitmap(m.ball, m.x, m.y, null);
            holder.unlockCanvasAndPost(c);
            m.x+=m.xSpeed;
            m.y+=10;


            if (m.x > 950){m.goBack = true;m.y+=100;}
            if (m.x==0){m.goBack = false; m.y+=100;}

            if(m.goBack ==true){m.x -= m.xSpeed*2;}
            if(m.y==1700){m.y=0;}

        }
    }

    public void pause(){
        okQuestion = false;
        while(true){
            try{t.join();}catch(InterruptedException e){e.printStackTrace();}
            break;
        }
        t = null;
    }


    public void resume(){
        okQuestion = true;
        t = new Thread(this);
        t.start();
    }



}

我的主课代码:

    package rdc.com.surfacegame;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;

public class main extends Activity implements View.OnTouchListener {

    public Surface surfer;
    public Bitmap ball;
    public float x, y;
    public int xSpeed = 45;
    public boolean goBack;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //surfer = (Surface)findViewById(R.id.preview_view);

        surfer = new Surface(this, this);
        ball = BitmapFactory.decodeResource(getResources(), R.drawable.blueball);
        x = y = 0;
        setContentView(surfer);

    }

    @Override
    protected void onPause() {
        super.onPause();
        surfer.pause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        surfer.resume();
    }

    @Override
    public boolean onTouch(View v, MotionEvent me) {
        return false;
    }

}

和 XML:

<RelativeLayout 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:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".main">


<LinearLayout
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_marginBottom="200dp">


    <rdc.com.surfacegame.main.Surface
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/preview_view" />
</LinearLayout>
</RelativeLayout>

LogCat 详细信息:

04-08 23:23:36.294    3587-3587/rdc.com.surfacegame I/art﹕ Not late-enabling -Xcheck:jni (already on)
04-08 23:23:36.338    3587-3587/rdc.com.surfacegame D/AndroidRuntime﹕ Shutting down VM
04-08 23:23:36.339    3587-3587/rdc.com.surfacegame E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: rdc.com.surfacegame, PID: 3587
    java.lang.RuntimeException: Unable to start activity ComponentInfo{rdc.com.surfacegame/rdc.com.surfacegame.main}: android.view.InflateException: Binary XML file line #16: Error inflating class rdc.com.surfacegame.main.Surface
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
            at android.app.ActivityThread.access$800(ActivityThread.java:144)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
     Caused by: android.view.InflateException: Binary XML file line #16: Error inflating class rdc.com.surfacegame.main.Surface
            at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:757)
            at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
            at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
            at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:377)
            at android.app.Activity.setContentView(Activity.java:2144)
            at rdc.com.surfacegame.main.onCreate(main.java:30)
            at android.app.Activity.performCreate(Activity.java:5933)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
            at android.app.ActivityThread.access$800(ActivityThread.java:144)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
     Caused by: java.lang.ClassNotFoundException: Didn't find class "rdc.com.surfacegame.main.Surface" on path: DexPathList[[zip file "/data/app/rdc.com.surfacegame-1/base.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
            at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
            at android.view.LayoutInflater.createView(LayoutInflater.java:571)
            at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:743)
            at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
            at android.view.LayoutInflater.rInflate(LayoutInflater.java:809)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
            at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:377)
            at android.app.Activity.setContentView(Activity.java:2144)
            at rdc.com.surfacegame.main.onCreate(main.java:30)
            at android.app.Activity.performCreate(Activity.java:5933)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
            at android.app.ActivityThread.access$800(ActivityThread.java:144)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
    Suppressed: java.lang.ClassNotFoundException: rdc.com.surfacegame.main.Surface
            at java.lang.Class.classForName(Native Method)
            at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
            at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
            ... 24 more
     Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available

【问题讨论】:

    标签: android xml eclipse animation android-studio


    【解决方案1】:

    如果您在 XML 中使用 LinearLayout,您只需添加以下内容:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="fill_parent"
              >
    
    <rdc.com.surfaceview.Surface android:id="@+id/preview_view"
                 android:layout_width="fill_parent"
                 android:layout_height="fill_parent"/>
    
    </LinearLayout>
    

    要设置绿色背景,您需要注释掉 d.drawColor(Color.GREEN) 在我们的 run() 方法中添加 一个 Paint 变量并覆盖 Surface 类的 onDraw 方法。

    在你的 Surface 类构造函数中:

    public Surface(Context context, main m)   
    {
      super(context);
      this.m=m;
      Initialise();
    }
    public Surface(Context context)
    {
      super(context);
      Initialise();
    }
    public Surface(Context context, AttributeSet attrs)
    {
      super(context, attrs);
      Initialise();
    }
    public void Initialise()
    {
      holder = getHolder();
      greenPaint = new Paint();
      greenPaint.setAntiAlias(true);
      greenPaint.setStyle(Paint.Style.FILL);
      greenPaint.setStrokeWidth(6.0f);
      greenPaint.setColor(Color.argb(255, 0, 198, 0));
    }
    public void SetActivity(main m)
    {
      this.m = m;
    }
    

    重写 Surface 类中的 onDraw 方法

    @Override
    protected void onDraw(Canvas canvas)
    {
      super.onDraw(canvas);
      int width = this.getWidth();
      int height = this.getHeight();
      int radius = width > height ? height/2 : width/2;
      int center_x = width/2;
      int center_y = height/2;
    
      canvas.drawRect(center_x - radius, center_y - radius, center_x + radius, center_y + radius, greenPaint);
    }
    

    表面 run() 方法

    @Override
    public void run()
    {
      while (okQuestion == true)
      {
        if  (!holder.getSurface().isValid())
        {
          continue;
        }
    
      Canvas c = holder.lockCanvas();
      c.drawColor(Color.GREEN);
      c.drawBitmap(m.ball, m.x, m.y, null);
      holder.unlockCanvasAndPost(c);
      m.x+=m.xSpeed;
      m.y+=10;
    
    
      if (m.x > 950)
      {
        m.goBack = true;m.y+=100;
      }
    
      if (m.x==0)
      {
        m.goBack = false; m.y+=100;
      }
    
      if(m.goBack ==true)
      {
        m.x -= m.xSpeed*2;
        int width = this.getWidth();
        int height = this.getHeight();
        int radius = width > height ? height/2 : width/2;
        int center_x = width/2;
        int center_y = height/2;
        c.drawRect(center_x - radius, center_y - radius, center_x + radius, center_y + radius, greenPaint);
      }
      if(m.y==1700){m.y=0;}
    
    }
    

    }

    main的onCreate函数

    @Override
    protected void onCreate(Bundle savedInstace)
    {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      surfer = (Surface)findViewById(R.id.preview_view);
      surfer.SetActivity(this);
    }
    

    【讨论】:

      猜你喜欢
      • 2013-05-30
      • 1970-01-01
      • 1970-01-01
      • 2013-01-31
      • 2016-03-30
      • 2012-12-20
      • 1970-01-01
      • 1970-01-01
      • 2011-10-05
      相关资源
      最近更新 更多