【问题标题】:Setting button background drawable in different class在不同的类中设置按钮背景可绘制
【发布时间】:2013-11-26 06:23:28
【问题描述】:

我正在开发一款适用于 Android 的游戏,但在弄清楚这一点时遇到了一些麻烦。

我有一个主要活动,我有一个 GameView (SurfaceView)。我想在 GameView 中执行操作时更改 MainActivity 中按钮的背景图像。

我的 MainActivity 是一个 Activity,但 GameView 不是一个 Activity,它只是在我的 MainActivity 中被调用和显示。

我想过做以下事情:

主要活动:

public void setNumberLivesPicture(final Drawable background){
        MainActivity.this.runOnUiThread(new Runnable() {     
            public void run() {         
                numberLivesPicture.setBackgroundDrawable(background);     
            } 
         });
    }

游戏视图:

public class GameView extends SurfaceView{

    int difficulty =  HomePage.getDifficulty();
    int player = HomePage.getPlayer();
    String direction =  MainActivity.getDirection();
    boolean audio = HomePage.getAudio();
    private Drawable bloodspatterdead;
    Button numberLivesPicture;
    Button numberLivesButton;
    MainActivity mAct;


    public GameView(Context context, AttributeSet attributeSet, MainActivity MActivity, Button NumberLives) {
        super(context, attributeSet);
        gameLoopThread = new GameLoopThread(this);
        if (audio == true){
            backgroundNoise.start();
        }       
        getHolder().addCallback(new SurfaceHolder.Callback()
        {

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                boolean retry = true;
                GameLoopThread.setRunning(false);
                while (retry) {
                    try {
                        gameLoopThread.join();
                        retry = false;
                    } catch (InterruptedException e) {}
                }
            }           

            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                createSprites(difficulty);
                GameLoopThread.setRunning(true);
                gameLoopThread.start();
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format,
                    int width, int height) {
            }
        });
    }


    private void checkForEnemyCollision() {

        int x = playerSprite.getPlayerX();
        int y = playerSprite.getPlayerY();

        Rect playerRect = new Rect(x, y, (x + playerSprite.getPlayerWidth()), (y + playerSprite.getPlayerHeight()));
        for (int i = 0; i<sprites.size(); i++)
        {
            Rect zombieSprite = sprites.get(i).getZombieBounds();
            if(zombieSprite.intersect(playerRect))
            {           
       if (justDied == true){         // if you just died, we'll give you a break
                }

                if (justDied == false){

    if (NumberOfLives <= 1){   // if you do not have any extra lives.. you die!

                        if (shieldsActivated >= 1){
                            shieldsActivated--;
                            if (audio == true){
                                shielddestroyed.start();
                            }
                        }

                        if (shieldsActivated == 0)
                        {           

((MainActivity) getContext()).setTextView("THE ZOMBIES ATE YOUR BRAINS!!");

                        if (audio == true){
                            backgroundNoise.stop();
                            youaredeadmessage.start();              
                            }

                        for (int z = 0; z<playerSprites.size(); z++)
                        {
                        playerSprites.remove(z);
                        }
                        alive = false;

                    }
                    }
                    if (NumberOfLives > 1){

                        if (shieldsActivated >= 1){
                            shieldsActivated--;
                            if (audio == true){
                                shielddestroyed.start();
                            }
                        }

                        else if (shieldsActivated == 1){
                            shieldsActivated=0;
                            if (audio == true)
                            {
                                shielddestroyed.start();
                            }
                        }

else if (shieldsActivated == 0){                        
NumberOfLives = NumberOfLives -1;
justDied = true;

if (NumberOfLives == 4){

//Button numberOfLives2 = (Button) findViewById(R.id.numberLivesPicture);
numberLivesPicture = (Button) findViewById(R.id.numberLivesPicture);

((MainActivity) getContext()).setNumberLivesPicture(R.id.numberLivesPicture);                           numberLivesPicture.setBackgroundResource(R.drawable.numberlives4);
                                }

但这不起作用:(

编辑:

我已经成功地使用它来更改 TextView 内的 TEXT,但我不确定如何使用这样的方法来更改背景:

public void setTextView(final String txt){
        MainActivity.this.runOnUiThread(new Runnable() {     
            public void run() {         
                txv.setText(txt);     
            } 
         });
    }

用于:

((MainActivity) getContext()).setTextView("THE ZOMBIES ATE YOUR BRAINS!!");

任何建议将不胜感激!

【问题讨论】:

  • 您的表面视图是在主要活动上还是在不同活动上。
  • 我的 SurfaceView 不在我的 MainActivity 中,但它本身不是一个活动。我的 MainActivity 调用 SurfaceView 并将其放在里面(这充当我的游戏表面)。因此,您可以将其视为不同的活动
  • 好的,你可以做的是你可以从surfaceview向你的主要活动发送广播,你可以简单地在主要活动中更新你的数据。
  • 我不认为这会起作用,因为我的 MainActivity 是我的游戏本身,所以我必须每秒刷新一次(当可能发生变化时)会有点多。我编辑了评论以显示我如何更改文本,这对我来说效果很好,但不确定如何将它用于背景或图像。
  • 我给你的建议是一个非常笼统的建议。无论如何,我会尝试找出您代码中的问题。

标签: android button android-activity background drawable


【解决方案1】:

我会建议你使用面向对象的方法。将 Button 引用从 Activity 带到 surfaceView 类,然后在任何条件下使用 runUiThread 更新 Button 的背景

public class SurFaceViewClass extends SurfaceView {

Button btnButton;
MainActivity mAct;

public SurFaceViewClass(MainActivity mact, Button btn) {
    super(mact);
    mAct = mact;
    btnButton = btn;
}

@Override
public boolean onTouchEvent(MotionEvent event) {

    // if(yourconnditIOn)
    mAct.runOnUiThread(new Runnable() {

        @Override
        public void run() {
            btnButton.setBackgroundResource(R.drawable.ic_launcher);
        }
    });
    return super.onTouchEvent(event);
}
}

runOnUiThread 是必要的,因为 SurfaceView 在自己的线程中运行。现在看看你将如何在 Activity 中调用它

    SurFaceViewClass msClass=new SurFaceViewClass(this, yourbttn);

【讨论】:

  • 我不完全确定如何在我的活动中调用它以不断检查/更新它?另外 - 它不是触发它的 TouchEvent。
  • 带处理程序不断检查,但您没有按钮实例,因此您可以随时更改背景,这很重要
  • 我已经更新了我的主帖以显示我的部分游戏视图。它会与此结合使用吗?我已经尝试了您的建议,但没有运气。
  • 不,您没有实施我的解决方案。带来 Button 实例并更新它。如果你有一个单一的活动,并带来活动实例就可以了
  • 恐怕不太明白。我要更新的按钮位于我的 MainActivity 中。
【解决方案2】:

有几种可能的方法。您可以根据自己的情况使用广播发送方和接收方。

下面提到的步骤:

第 1 步:在您的主要活动中创建一个广播接收器以接收来自您的表面视图的广播。

BroadcastReceiver 接收器 = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals("update_button")) {
            // UPDATE YOUR BUTTON HERE.
        }
    }
};

第 2 步:在主 Activity 中创建广播接收器后注册接收器。

IntentFilter filter = new IntentFilter("update_button");
registerReceiver(receiver, filter);

第 3 步:从表面视图发送广播到更新按钮。

Intent intent = new Intent("update_button");
// HERE YOU CAN PUT EXTRAS IN  YOUR INTENT
SendBroadcast(intent);

无论您在哪里注册了广播接收器,它都会自动接收广播并在主活动中更新您的按钮。使用上述方法,您可以更新按钮或任何类的任何数据。

【讨论】:

  • 那么在我的 SendBroadcast 中,我将如何告诉它例如将背景更改为 @drawable/image2 ?不完全确定附加功能是如何工作的。
  • 以同样的方式。如果你想在主活动中发送一些数据来更新按钮,你可以 putExtra。如果您可以在主要活动本身中获取数据,那么您可以对其进行更新。只需写 numberLivesPicture.setBackgroundDrawable(background);在 onReceive 中更新您的按钮背景并检查。
  • 你的资源中有你的drawable吗,你也可以试试btn.setBackgroundResource来设置图像。
  • 不使用Receiver,使用我的解决方案
  • 是的,drawable 在我的资源中。 numberOfLives.setBackgroundResource(R.drawable.numberlives4);满足条件时在该行返回 NullPointerException。
猜你喜欢
  • 2020-06-19
  • 2019-12-21
  • 2023-03-02
  • 2015-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-26
  • 1970-01-01
相关资源
最近更新 更多