【问题标题】:surfaceview + buttons findviewbyid returns null [closed]surfaceview +按钮findviewbyid返回null [关闭]
【发布时间】:2012-11-18 17:10:29
【问题描述】:

我的代码没问题,但不幸的是我的代码给了我空指针异常。我知道通过在 findviewbyid 之前编写 setcontentview 它不会发生,但是这样做我的表面不会更新。我尝试了很多关于这个的搜索,但我无法得到正确的答案,请帮助我。我的 mainctivity 代码:-

package com.example.snakes;

public class MainActivity extends Activity implements View.OnClickListener{

MySurfaceClass sc;
Button up,down,left,right;
//View v1,v2;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    sc = new MySurfaceClass(this);
    //setContentView(R.layout.activity_main);

    up = (Button) findViewById(R.id.button1);
    down = (Button) findViewById(R.id.button2);
    left = (Button) findViewById(R.id.button3);
    right = (Button) findViewById(R.id.button4);

    up.setOnClickListener(this);
    down.setOnClickListener(this);
    left.setOnClickListener(this);
    right.setOnClickListener(this);
    setContentView(R.layout.activity_main);

    // Toast.makeText(this, "done", Toast.LENGTH_SHORT).show();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

public void onClick(View v) {
    switch(v.getId()){
    case R.id.button1:
        sc.posY = sc.posY - 50 ;
        Toast.makeText(this, "up", Toast.LENGTH_SHORT).show();
    //   sc = new MySurfaceClass(this);
      //   setContentView(R.layout.activity_main);
        break;

    case R.id.button2:
        sc.posY = sc.posY + 50 ;
        Toast.makeText(this, "down", Toast.LENGTH_SHORT).show();
        // sc = new MySurfaceClass(this);
         //setContentView(R.layout.activity_main);
        break;

    case R.id.button3:
        sc.posX = sc.posX - 50 ;
        Toast.makeText(this, "left", Toast.LENGTH_SHORT).show();
        //sc = new MySurfaceClass(this);
        //setContentView(R.layout.activity_main);
        break;

    case R.id.button4:
        sc.posX = sc.posX + 10 ;
        Toast.makeText(this, "right", Toast.LENGTH_SHORT).show();
        //setContentView(R.layout.activity_main);
        break;
    }
}
}

而表面活动的代码:-

package com.example.snakes;


public class MySurfaceClass extends SurfaceView implements Runnable {

private SurfaceHolder sh;
private Thread t = null;
private boolean isRunning;
private Bitmap b;
protected int posX, posY;

public MySurfaceClass(Context context) {
    super(context);
    init();
}

public MySurfaceClass(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}

public MySurfaceClass(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init();
}

void init() {
    isRunning = true;
    b = BitmapFactory.decodeResource(getResources(), R.drawable.face);
    posX = 0;
    posY = 0;
    sh = this.getHolder();
    t = new Thread(this);
    t.start();
};

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawRect(100, 100, 100, 100, null);
}

public void run() {
    while (isRunning) {
        if (!sh.getSurface().isValid())
            continue;

        Canvas c = sh.lockCanvas();
        c.drawRGB(5, 150, 10);
        c.drawBitmap(b, posX, posY, null);
        sh.unlockCanvasAndPost(c);
    }
}
  }

和 xml :-

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >



<LinearLayout
    android:id="@+id/view1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/grey"
    android:weightSum="100" >

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="up" 
        android:layout_weight="25"/>

    <Button
        android:id="@+id/button2"
        android:layout_weight="25"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="down" />

    <Button
        android:id="@+id/button3"
        android:layout_weight="25"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="left" />

    <Button
        android:id="@+id/button4"
        android:layout_weight="25"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="right" />
</LinearLayout>

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.example.snakes.MySurfaceClass
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/surfaceView"
        />
</FrameLayout>

【问题讨论】:

  • “我的代码没问题,但不幸的是我的代码给了我空指针异常”——那么这意味着你的代码不正确,不是吗? :)
  • 好吧,很抱歉,但那是因为如果我在此之前编写 setcontentview,它不会给出错误,这就是原因
  • 所以修复你的 SurfaceView 类,因为你显然有问题。
  • 但我不知道怎么做?

标签: android surfaceview findviewbyid


【解决方案1】:

setContentView 方法必须在使用 findViewById 获取对小部件的任何引用之前调用,否则在将单击侦听器设置为按钮时,您将得到 NullPointerExceptions。

我会先让按钮工作,然后再考虑表面视图。

【讨论】:

  • 但按钮可以正常工作,但如果我在 findviewbyid 之前设置了 setcontentview,则视图不会更新
  • 是的,这就是重点。您必须在获取按钮引用之前调用 setContentView,否则您将获得 NPE。关于 SurfaceView,看起来您不是使用 findViewById 从内容视图获取它,但实际上是在实例化一个新视图。
  • 是的,所以一旦我实例化它,线程就会启动,当我改变位置值时,surfaceview 应该得到更新,但我不知道为什么会这样?
  • 嗯,你应该在活动的 onResume 方法上开始你的线程,而不是在实例化时。特别是,因为如果您使用自定义表面视图对布局进行膨胀,布局膨胀器将实例化所有视图,这意味着您无法控制它。这样做,删除实例化行。使用 findViewById 方法获取 sc 引用。将 SurfaceView 开始代码移动到不同的方法。从活动 onResume 调用 start 方法
  • 但是surfaceclass没有onResume方法我应该在主要活动类中使用它吗?
【解决方案2】:

您的代码已损坏。你必须setContentView() 否则没有附加视图。

【讨论】:

  • 但是我已经设置了内容视图
  • 不。你把这个注释掉了 -> //setContentView(R.layout.activity_main);
  • 好的,如果我之前写 setContentView 然后应用程序运行但表面没有更新
猜你喜欢
  • 1970-01-01
  • 2011-03-16
  • 1970-01-01
  • 1970-01-01
  • 2013-08-02
相关资源
最近更新 更多