简体   繁体   中英

How do I access views in nested layouts programmatically?

I'm trying to use an ImageView in my java code that is inside the second RelativeLayout node in the XML. However, I can't get references to the ImageViews as seen by the setVisibility method that does not make the images invisible.

[DOUBLE EDIT] Here is my revised Activity Class:

package com.scopelyapplication.tictactoe;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;

public class TicTacToeActivity extends ActionBarActivity {

private static final String LOGTAG = "TicTacToeActivity";
private ModelComputerGameHelper comHelp;

boolean humanIsX;

RelativeLayout layout;
ImageView blueX;
ImageView greyX;
ImageView blueO;
ImageView greyO;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    layout = (RelativeLayout)findViewById(R.id.mainLayout);

    Log.d(LOGTAG, "onCreate");

    //Set up action bar
    ActionBar actionBar = getSupportActionBar();
    actionBar.setDisplayUseLogoEnabled(false);
    actionBar.setDisplayHomeAsUpEnabled(true);
    Log.d(LOGTAG, "set action bar");

    //Initialize X's and O's
    blueX = (ImageView)findViewById(R.id.blueXTopLeft);
    greyX = (ImageView)findViewById(R.id.greyXTopLeft);
    blueO = (ImageView)findViewById(R.id.blueOTopLeft);
    greyO = (ImageView)findViewById(R.id.greyOTopLeft);
    Log.d(LOGTAG, "X's and O's initialized");

    //Turn off their visibility until one is clicked.
    blueX.setVisibility(View.INVISIBLE); //where the NPE occurs
    greyX.setVisibility(View.INVISIBLE);
    blueO.setVisibility(View.INVISIBLE);
    greyO.setVisibility(View.INVISIBLE);

    Bundle extras = getIntent().getExtras();
    boolean gameIsPVP = extras.getBoolean("gameIsPVP");
    humanIsX = extras.getBoolean("humanIsX");

    if (gameIsPVP) {
        ; //in progress
    } else {
        startComputerGame(humanIsX);
    }
}

public void squareOneClick(View imageView) {

    char humanPlayer = ' ';
    if (humanIsX) {
        humanPlayer = 'X';
    } else {
        humanPlayer = 'O';
    }
    comHelp.makeMove(humanPlayer, 0);
    if (humanPlayer == 'X') {
        blueX.setVisibility(View.VISIBLE);
    } else {
        blueO.setVisibility(View.VISIBLE);
    }

    updateBoard();
}
public void squareTwoClick(View imageView) {

    char humanPlayer = ' ';
    if (humanIsX) {
        humanPlayer = 'X';
    }
    else {
        humanPlayer = 'O';
    }
    comHelp.makeMove(humanPlayer, 1);
    updateBoard();
}
public void squareThreeClick(View imageView) {

    char humanPlayer = ' ';
    if (humanIsX) {
        humanPlayer = 'X';
    }
    else {
        humanPlayer = 'O';
    }
    comHelp.makeMove(humanPlayer, 2);
    updateBoard();
}
public void squareFourClick(View imageView) {

    char humanPlayer = ' ';
    if (humanIsX) {
        humanPlayer = 'X';
    }
    else {
        humanPlayer = 'O';
    }
    comHelp.makeMove(humanPlayer, 3);
    updateBoard();
}
public void squareFiveClick(View imageView) {

    char humanPlayer = ' ';
    if (humanIsX) {
        humanPlayer = 'X';
    }
    else {
        humanPlayer = 'O';
    }
    comHelp.makeMove(humanPlayer, 4);
    updateBoard();
}
public void squareSixClick(View imageView) {

    char humanPlayer = ' ';
    if (humanIsX) {
        humanPlayer = 'X';
    }
    else {
        humanPlayer = 'O';
    }
    comHelp.makeMove(humanPlayer, 5);
    updateBoard();
}
public void squareSevenClick(View imageView) {

    char humanPlayer = ' ';
    if (humanIsX) {
        humanPlayer = 'X';
    }
    else {
        humanPlayer = 'O';
    }
    comHelp.makeMove(humanPlayer, 6);
    updateBoard();
}
public void squareEightClick(View imageView) {

    char humanPlayer = ' ';
    if (humanIsX) {
        humanPlayer = 'X';
    }
    else {
        humanPlayer = 'O';
    }
    comHelp.makeMove(humanPlayer, 7);
    updateBoard();
}
public void squareNineClick(View imageView) {

    char humanPlayer = ' ';
    if (humanIsX) {
        humanPlayer = 'X';
    }
    else {
        humanPlayer = 'O';
    }
    comHelp.makeMove(humanPlayer, 8);
    updateBoard();
}


@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == android.R.id.home) {
        finish();
        startActivity(new Intent(this, PickerActivity.class));
    }
    return super.onOptionsItemSelected(item);
}

public void startComputerGame(boolean isHumanX) {
    Log.d(LOGTAG, "startComputerGame");
    comHelp = new ModelComputerGameHelper(isHumanX);
    updateBoard();
}

public void updateBoard() {
    //in progress. connects startComputerGame and Clicks with Visuals.

}

}

And here is some of my XML from activity_main :

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="20dp"
android:minWidth="20dp" >

<ImageView
    android:id="@+id/gameBoard"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentTop="true"
    android:contentDescription="@string/gameboard"
    android:src="@drawable/gameboard" />

<RelativeLayout
    android:id="@+id/squareOneLayout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginBottom="290dp"
    android:layout_marginRight="220dp"
    android:layout_marginTop="70dp" >

    <ImageButton
        android:id="@+id/squareOne"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_marginBottom="288dp"
        android:layout_marginRight="219dp"
        android:layout_marginTop="71dp"
        android:background="@android:color/transparent"
        android:contentDescription="@string/top_left"
        android:onClick="squareOneClick"
        android:src="@drawable/blank_button" />

    <!-- Top-left images -->

    <ImageView
        android:id="@+id/blueOTopLeft"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/greyOTopLeft"
        android:layout_centerVertical="true"
        android:src="@drawable/piece_o" />

    <ImageView
        android:id="@+id/greyOTopLeft"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:src="@drawable/piece_o_grey" />

    <ImageView
        android:id="@+id/greyXTopLeft"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/blueOTopLeft"
        android:layout_centerVertical="true"
        android:src="@drawable/piece_x_grey" />

    <ImageView
        android:id="@+id/blueXTopLeft"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/blueOTopLeft"
        android:layout_centerVertical="true"
        android:src="@drawable/piece_x" />
</RelativeLayout>

... <!-- rest of xml -->

</RelativeLayout>

And here is my logcat, sorry for forgetting!

02-23 03:27:26.984: D/AndroidRuntime(1125): Shutting down VM
02-23 03:27:26.984: E/AndroidRuntime(1125): FATAL EXCEPTION: main
02-23 03:27:26.984: E/AndroidRuntime(1125): Process: com.scopelyapplication.tictactoe, PID: 1125
02-23 03:27:26.984: E/AndroidRuntime(1125): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.scopelyapplication.tictactoe/com.scopelyapplication.tictactoe.TicTacToeActivity}: java.lang.NullPointerException
02-23 03:27:26.984: E/AndroidRuntime(1125):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195)
02-23 03:27:26.984: E/AndroidRuntime(1125):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
02-23 03:27:26.984: E/AndroidRuntime(1125):     at android.app.ActivityThread.access$800(ActivityThread.java:135)
02-23 03:27:26.984: E/AndroidRuntime(1125):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
02-23 03:27:26.984: E/AndroidRuntime(1125):     at android.os.Handler.dispatchMessage(Handler.java:102)
02-23 03:27:26.984: E/AndroidRuntime(1125):     at android.os.Looper.loop(Looper.java:136)
02-23 03:27:26.984: E/AndroidRuntime(1125):     at android.app.ActivityThread.main(ActivityThread.java:5017)
02-23 03:27:26.984: E/AndroidRuntime(1125):     at java.lang.reflect.Method.invokeNative(Native Method)
02-23 03:27:26.984: E/AndroidRuntime(1125):     at java.lang.reflect.Method.invoke(Method.java:515)
02-23 03:27:26.984: E/AndroidRuntime(1125):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
02-23 03:27:26.984: E/AndroidRuntime(1125):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
02-23 03:27:26.984: E/AndroidRuntime(1125):     at dalvik.system.NativeStart.main(Native Method)
02-23 03:27:26.984: E/AndroidRuntime(1125): Caused by: java.lang.NullPointerException
02-23 03:27:26.984: E/AndroidRuntime(1125):     at com.scopelyapplication.tictactoe.TicTacToeActivity.onCreate(TicTacToeActivity.java:54)
02-23 03:27:26.984: E/AndroidRuntime(1125):     at android.app.Activity.performCreate(Activity.java:5231)
02-23 03:27:26.984: E/AndroidRuntime(1125):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
02-23 03:27:26.984: E/AndroidRuntime(1125):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159)
02-23 03:27:26.984: E/AndroidRuntime(1125):     ... 11 more

Thank You!

Just access it directly with its ID.
Change the line to:

blueX = (ImageView) findViewById(R.id.blueXTopLeft);

and do the similar thing with other related variables and it will then work.

I think your issue lies within your layout XML. See the documentation for RelativeLayout which states:

Note that you cannot have a circular dependency between the size of the RelativeLayout and the position of its children. For example, you cannot have a RelativeLayout whose height is set to WRAP_CONTENT and a child set to ALIGN_PARENT_BOTTOM.

You need to correct the circular dependency in squareOneLayout (and possibly elsewhere as well).

A RelativeLayout cannot size itself based on the size of its children, if you want the children to be positioned relative to the parent RelativeLayout.

To put it another way, the parent (RelativeLayout) cannot size itself based on the size and overall layout of its children (ImageViews) if the children are positioned relative to the size of the parent (RelativeLayout). The result is a circular dependency which cannot be resolved.

You'll either need to change how the RelativeLayout is sized, or position the ImageViews relative to a sibling view (eg one of the ImageViews) instead of being positioned relative to the parent RelativeLayout.

As previously stated, have you tried doing a clean on your project? your R.java could be a little messed up. Project>Clean.

Try this...

activity_main:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="20dp"
android:minWidth="20dp" >

<ImageView
  android:id="@+id/gameBoard"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_alignParentBottom="true"
  android:layout_alignParentLeft="true"
  android:layout_alignParentRight="true"
  android:layout_alignParentTop="true"
  android:contentDescription="@string/gameboard"
  android:src="@drawable/gameboard" />

<RelativeLayout
  android:id="@+id/squareOneLayout"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_marginBottom="290dp"
  android:layout_marginRight="220dp"
  android:layout_marginTop="70dp" >

  <ImageButton
    android:id="@+id/squareOne"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentTop="true"
    android:layout_marginBottom="288dp"
    android:layout_marginRight="219dp"
    android:layout_marginTop="71dp"
    android:background="@android:color/transparent"
    android:contentDescription="@string/top_left"
    android:onClick="squareOneClick"
    android:src="@drawable/blank_button" />

<!-- Top-left images -->

<ImageView
    android:id="@+id/blueOTopLeft"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/greyOTopLeft"
    android:layout_centerVertical="true"
    android:src="@drawable/piece_o" 
    android:visibility="invisible"/>

<ImageView
    android:id="@+id/greyOTopLeft"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:src="@drawable/piece_o_grey" 
    android:visibility="invisible"/>

<ImageView
    android:id="@+id/greyXTopLeft"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/blueOTopLeft"
    android:layout_centerVertical="true"
    android:src="@drawable/piece_x_grey" 
    android:visibility="invisible"
   />

<ImageView
    android:id="@+id/blueXTopLeft"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/blueOTopLeft"
    android:layout_centerVertical="true"
    android:src="@drawable/piece_x" 
    android:visibility="invisible"/>
  </RelativeLayout>

  ... <!-- rest of xml -->

  </RelativeLayout>

MainActivity.java

package com.scopelyapplication.tictactoe;

 import android.content.Intent;
 import android.os.Bundle;
 import android.support.v7.app.ActionBar;
 import android.support.v7.app.ActionBarActivity;
 import android.util.Log;
 import android.view.MenuItem;
 import android.view.View;
 import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.RelativeLayout;

    public class TicTacToeActivity extends ActionBarActivity {

    private static final String LOGTAG = "TicTacToeActivity";
    private ModelComputerGameHelper comHelp;

    boolean humanIsX;

    RelativeLayout layout;
    ImageView blueX, greyX, blueO, greyO;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

layout = (RelativeLayout)findViewById(R.id.mainLayout);

Log.d(LOGTAG, "onCreate");

//Set up action bar
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayUseLogoEnabled(false);
actionBar.setDisplayHomeAsUpEnabled(true);
Log.d(LOGTAG, "set action bar");

//Initialize X's and O's
blueX = (ImageView)findViewById(R.id.blueXTopLeft);
greyX = (ImageView)findViewById(R.id.greyXTopLeft);
blueO = (ImageView)findViewById(R.id.blueOTopLeft);
greyO = (ImageView)findViewById(R.id.greyOTopLeft);
Log.d(LOGTAG, "X's and O's initialized");



Bundle extras = getIntent().getExtras();
boolean gameIsPVP = extras.getBoolean("gameIsPVP");
humanIsX = extras.getBoolean("humanIsX");

if (gameIsPVP) {
    ; //in progress
} else {
    startComputerGame(humanIsX);
}
}

public void squareOneClick(View imageView) {

char humanPlayer = ' ';
if (humanIsX) {
    humanPlayer = 'X';
} else {
    humanPlayer = 'O';
}
comHelp.makeMove(humanPlayer, 0);
if (humanPlayer == 'X') {
    blueX.setVisibility(View.VISIBLE);
} else {
    blueO.setVisibility(View.VISIBLE);
}

 updateBoard();
 }
 public void squareTwoClick(View imageView) {

char humanPlayer = ' ';
if (humanIsX) {
    humanPlayer = 'X';
}
else {
    humanPlayer = 'O';
}
comHelp.makeMove(humanPlayer, 1);
updateBoard();
}
public void squareThreeClick(View imageView) {

char humanPlayer = ' ';
if (humanIsX) {
    humanPlayer = 'X';
}
else {
    humanPlayer = 'O';
}
comHelp.makeMove(humanPlayer, 2);
updateBoard();
}
public void squareFourClick(View imageView) {

char humanPlayer = ' ';
if (humanIsX) {
    humanPlayer = 'X';
}
else {
    humanPlayer = 'O';
}
comHelp.makeMove(humanPlayer, 3);
updateBoard();
}
public void squareFiveClick(View imageView) {

char humanPlayer = ' ';
if (humanIsX) {
    humanPlayer = 'X';
}
else {
    humanPlayer = 'O';
}
comHelp.makeMove(humanPlayer, 4);
updateBoard();
}
public void squareSixClick(View imageView) {

char humanPlayer = ' ';
if (humanIsX) {
    humanPlayer = 'X';
}
else {
    humanPlayer = 'O';
}
 comHelp.makeMove(humanPlayer, 5);
 updateBoard();
 }
public void squareSevenClick(View imageView) {

char humanPlayer = ' ';
if (humanIsX) {
    humanPlayer = 'X';
}
else {
    humanPlayer = 'O';
}
comHelp.makeMove(humanPlayer, 6);
updateBoard();
}
public void squareEightClick(View imageView) {

char humanPlayer = ' ';
if (humanIsX) {
    humanPlayer = 'X';
}
else {
    humanPlayer = 'O';
}
comHelp.makeMove(humanPlayer, 7);
updateBoard();
}
public void squareNineClick(View imageView) {

char humanPlayer = ' ';
if (humanIsX) {
    humanPlayer = 'X';
}
else {
    humanPlayer = 'O';
}
comHelp.makeMove(humanPlayer, 8);
 updateBoard();
}


@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
    finish();
    startActivity(new Intent(this, PickerActivity.class));
}
return super.onOptionsItemSelected(item);
}

public void startComputerGame(boolean isHumanX) {
Log.d(LOGTAG, "startComputerGame");
comHelp = new ModelComputerGameHelper(isHumanX);
 updateBoard();
 }

public void updateBoard() {
//in progress. connects startComputerGame and Clicks with Visuals.

}

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM