App crashes after clicking button to load Tab layout
[Edit] When I try Sumant's suggestion of switching out "v.getContext()" with "this" in the Intent constructor Eclipse says it can't build the app. When the onClick() method is called isn't the current View passed to it?
[Edit 2] I may have figured out the problem. It could have been that I was using a layout meant for Android 3.0 when I was using an Android 2.3.3 emulator. It was either that, or my just using a string array rather than an integer array.
In my Android app when a user clicks on a button to take them to a tabbed activity the emulator I'm running (using Android 2.3.3) forces my app closed. Here's the initial activity.
DungeonsDragonsAppActivity.java file
package com.androidGuy.DnDApp;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import android.util.Log;
public class DungeonsDragonsAppActivity extends Activity {
/* Use this for debugging. */
private static final String DEBUG_TAG = "DnDAppDebugLogging";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
/* The main buttons... Yeah. */
final Button create_character_button = (Button) findViewById(R.id.createCharacterButton);
final Button open_character_button = (Button) findViewById(R.id.openCharacterButton);
final Button retrieve_character_button = (Button) findViewById(R.id.RetrieveCharacterButton);
/* The button for actually creating the character.. */
create_character_button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
Intent intent = new Intent(v.getContext(),
CreateCharacterTabsActivity.class);
startActivityForResult(intent, 0);
} catch (Exception e) {
Log.e(DEBUG_TAG, "Click failed", e);
}
}
});
/* The button for opening a pre-existing character. */
open_character_button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Toast.makeText(DungeonsDragonsAppActivity.this,
"You will be able to open a character... Eventually.",
Toast.LENGTH_SHORT).show();
}
});
/* The button for importing from D & D insider. */
retrieve_character_button
.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Toast.makeText(
DungeonsDragonsAppActivity.this,
"You will be able to import characters... Hopefully.",
Toast.LENGTH_SHORT).show();
}
}
);
}
}
When the user clicks on the button to create a new character it should load up this activity:
CreateCharacterTabsActivity.java
package com.androidGuy.DnDApp;
import android.app.TabActivity;
import android.os.Bundle;
import android.widget.TabHost;
import android.content.Intent;
public class CreateCharacterTabsActivity extends TabActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TabHost tabHost = getTabHost();
TabHost.TabSpec spec;
Intent intent;
// Initialize a TabSpec for each tab and add it to the TabHost.
spec = tabHost.newTabSpec("scores");
spec.setContent(new Intent().setClass(this,
CharacterAbilityScoresActivity.class));
spec.setIndicator("Scores");
tabHost.addTab(spec);
intent = new Intent().setClass(this, CharacterClassActivity.class);
spec = tabHost.newTabSpec("classes");
spec.setContent(intent);
spec.setIndicator("Classes");
tabHost.addTab(spec);
tabHost.setCurrentTab(0);
}
}
It uses this XML file to render the tabs (I took it from one of Android dev tutorials).
tabs.xml
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="5dp">
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:layout_weight="1">
</FrameLayout>
<TabWidget
android:id="@android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0">
</TabWidget>
</LinearLayout>
</TabHost>
Once that activity loads it should also load these activities into the tabs.
CharacterAbilityScoresActivity.java
package com.androidGuy.DnDApp;
import android.app.Activity;
import android.os.Bundle;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.Toast;
import android.view.View;
public class CharacterAbilityScoresActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ability_score_spinners); // Set the scene.
ArrayAdapter adapter = ArrayAdapter.createFromResource(this, R.array.ability_scores, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
/* The ability score spinners */
Spinner strengthSpinner = (Spinner) findViewById(R.id.StrengthSpinner);
strengthSpinner.setAdapter(adapter);
strengthSpinner
.setOnItemSelectedListener(new abilityScoreListSelectedListener());
Spinner constitutionSpinner = (Spinner) findViewById(R.id.ConstitutionSpinner);
constitutionSpinner.setAdapter(adapter);
constitutionSpinner
.setOnItemSelectedListener(new abilityScoreListSelectedListener());
}
/* Now let's see what the user selects. */
class abilityScoreListSelectedListener implements OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent, View view, int pos,
long id) {
Toast.makeText(parent.getContext(),
"You selected an ability score. Way to go.",
Toast.LENGTH_LONG).show();
}
public void onNothingSelected(AdapterView parent) {
// Do nothing... For now.
}
}
}
ability_score_spinners.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:id="@+id/linearLayout1" android:layout_width="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="match_parent">
<TableLayout android:layout_height="match_parent" android:id="@+id/tableLayout1" android:layout_width="wrap_content">
<TableRow android:id="@+id/tableRow1" android:layout_width="wrap_content" android:layout_height="match_parent">
<Spinner android:layout_height="wrap_content" android:minWidth="10dip" android:layout_width="wrap_content" android:layout_gravity="left" android:layout_weight="1" android:id="@+id/StrengthSpinner" android:entries="@array/ability_scores" android:prompt="@string/ability_score_prompt"></Spinner>
</TableRow>
<TableRow android:id="@+id/tableRow2" android:layout_width="wrap_content" android:layout_height="wrap_content">
<Spinner android:layout_height="wrap_content" android:layout_weight="1" android:layout_width="wrap_content" android:id="@+id/ConstitutionSpinner" android:entries="@array/ability_scores" android:prompt="@string/ability_score_prompt"></Spinner>
</TableRow>
<TableRow android:id="@+id/tableRow4" android:layout_width="wrap_content" android:layout_height="wrap_content"></TableRow>
<TableRow android:layout_height="wrap_content" android:id="@+id/tableRow3" android:layout_width="wrap_content">
</TableRow>
</TableLayout>
<TableLayout android:layout_height="match_parent" android:id="@+id/tableLayout2" android:layout_width="match_parent">
<TableRow android:id="@+id/tableRow5" android:layout_width="wrap_content" android:layout_height="wrap_content">
<TextView android:text="@string/strengthText" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:id="@+id/StrengthText"></TextView>
</TableRow>
<TableRow android:id="@+id/tableRow6" android:layout_width="wrap_content" android:layout_height="wrap_content">
<TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:id="@+id/textView1" android:text="@string/constitionText"></TextView>
</TableRow>
<TableRow android:id="@+id/tableRow7" android:layout_width="wrap_content" android:layout_height="wrap_content"></TableRow>
<TableRow android:id="@+id/tableRow8" android:layout_width="wrap_content" android:layout_height="wrap_content">
</TableRow>
</TableLayout>
</LinearLayout>
CharacterClassesActivity.java
package com.androidGuy.DnDApp;
import android.app.Activity;
import android.os.Bundle;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
public class CharacterClassActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.cha_classes);
final RadioGroup classesButtons = (RadioGroup) findViewById(R.id.radioGroup1);
classesButtons
.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
public void onCheckedChanged(RadioGroup group, int checkedId) {
TextView leTextView = (TextView) findViewById(R.id.chooseClassTextView);
if (checkedId != -1) {
RadioButton rb = (RadioButton) findViewById(checkedId);
if (rb != null) {
leTextView.setText("You chose: " + rb.getText());
}
} else {
leTextView.setText("Choose your class");
}
}
});
}
}
cha_classes.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:id="@+id/linearLayout1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="Choose your class" android:id="@+id/chooseClassTextView"></TextView>
<RadioGroup android:id="@+id/radioGroup1" andr开发者_如何学编程oid:layout_width="wrap_content" android:layout_height="wrap_content">
<RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/ClericClassButton" android:text="Cleric"></RadioButton>
<RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/FighterClassButton" android:text="Fighter"></RadioButton>
<RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/PaladinClassButton" android:text="Paladin"></RadioButton>
<RadioButton android:layout_width="wrap_content" android:text="Ranger" android:layout_height="wrap_content" android:id="@+id/RangerClassButton"></RadioButton>
<RadioButton android:layout_width="wrap_content" android:text="Rogue" android:layout_height="wrap_content" android:id="@+id/RogueClassButton"></RadioButton>
<RadioButton android:layout_width="wrap_content" android:text="Warlock" android:layout_height="wrap_content" android:id="@+id/WarlockClassButton"></RadioButton>
<RadioButton android:layout_width="wrap_content" android:text="Warlord" android:layout_height="wrap_content" android:id="@+id/WarlordClassButton"></RadioButton>
<RadioButton android:layout_width="wrap_content" android:text="Wizard" android:layout_height="wrap_content" android:id="@+id/WizardClassButton"></RadioButton>
</RadioGroup>
</LinearLayout>
The ability scores should be in the first tab and the character classes in the second tab. I have written an integer array in the res/values/ directory and have tried using that in the spinner used with the ability scores.
At first I thought that it was tab layout and how it was handled. All it should do is set up the tab and filled it with the proper activity. I also thought that I was missing a setContentView() method in the CreateCharacterTabsActivity. But it appears that is not the case. I also thought that it was due to my manifest missing some activity entries, but that was incorrect, too.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0" package="com.androidGuy.DnDApp">
<uses-sdk android:minSdkVersion="10" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".DungeonsDragonsAppActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".CreateCharacterTabsActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.category.LAUNCHER"></action>
</intent-filter>
</activity>
<activity android:name=".CharacterAbilityScoresActivity"></activity>
<activity android:name=".CharacterClassActivity"></activity>
</application>
</manifest>
It seems, then, the error may be with how I handle the integer data for the spinners. I have created an ArrayAdapter to accept the integer data, and set the data in the spinners. Still, when I run the emulator it still crashes.
Here's the LogCat stack trace for when it crashes.
ERROR/AndroidRuntime(363): FATAL EXCEPTION: main
ERROR/AndroidRuntime(363): java.lang.NullPointerException
ERROR/AndroidRuntime(363): at android.widget.ArrayAdapter.createViewFromResource(ArrayAdapter.java:355)
ERROR/AndroidRuntime(363): at android.widget.ArrayAdapter.getView(ArrayAdapter.java:323)
ERROR/AndroidRuntime(363): at android.widget.AbsSpinner.onMeasure(AbsSpinner.java:192)
ERROR/AndroidRuntime(363): at android.view.View.measure(View.java:8313)
ERROR/AndroidRuntime(363): at android.widget.TableRow.getColumnsWidths(TableRow.java:308)
ERROR/AndroidRuntime(363): at android.widget.TableLayout.findLargestCells(TableLayout.java:500)
ERROR/AndroidRuntime(363): at android.widget.TableLayout.measureVertical(TableLayout.java:465)
ERROR/AndroidRuntime(363): at android.widget.TableLayout.onMeasure(TableLayout.java:431)
ERROR/AndroidRuntime(363): at android.view.View.measure(View.java:8313)
ERROR/AndroidRuntime(363): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138)
ERROR/AndroidRuntime(363): at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1017)
ERROR/AndroidRuntime(363): at android.widget.LinearLayout.measureHorizontal(LinearLayout.java:701)
ERROR/AndroidRuntime(363): at android.widget.LinearLayout.onMeasure(LinearLayout.java:311)
ERROR/AndroidRuntime(363): at android.view.View.measure(View.java:8313)
ERROR/AndroidRuntime(363): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138)
ERROR/AndroidRuntime(363): at android.widget.FrameLayout.onMeasure(FrameLayout.java:250)
ERROR/AndroidRuntime(363): at android.view.View.measure(View.java:8313)
ERROR/AndroidRuntime(363): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138)
ERROR/AndroidRuntime(363): at android.widget.FrameLayout.onMeasure(FrameLayout.java:250)
ERROR/AndroidRuntime(363): at android.view.View.measure(View.java:8313)
ERROR/AndroidRuntime(363): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138)
ERROR/AndroidRuntime(363): at android.widget.FrameLayout.onMeasure(FrameLayout.java:250)
ERROR/AndroidRuntime(363): at android.view.View.measure(View.java:8313)
ERROR/AndroidRuntime(363): at android.widget.LinearLayout.measureVertical(LinearLayout.java:531)
ERROR/AndroidRuntime(363): at android.widget.LinearLayout.onMeasure(LinearLayout.java:309)
ERROR/AndroidRuntime(363): at android.view.View.measure(View.java:8313)
ERROR/AndroidRuntime(363): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138)
ERROR/AndroidRuntime(363): at android.widget.FrameLayout.onMeasure(FrameLayout.java:250)
ERROR/AndroidRuntime(363): at android.view.View.measure(View.java:8313)
ERROR/AndroidRuntime(363): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138)
ERROR/AndroidRuntime(363): at android.widget.FrameLayout.onMeasure(FrameLayout.java:250)
ERROR/AndroidRuntime(363): at android.view.View.measure(View.java:8313)
ERROR/AndroidRuntime(363): at android.widget.LinearLayout.measureVertical(LinearLayout.java:531)
ERROR/AndroidRuntime(363): at android.widget.LinearLayout.onMeasure(LinearLayout.java:309)
ERROR/AndroidRuntime(363): at android.view.View.measure(View.java:8313)
ERROR/AndroidRuntime(363): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138)
ERROR/AndroidRuntime(363): at android.widget.FrameLayout.onMeasure(FrameLayout.java:250)
ERROR/AndroidRuntime(363): at android.view.View.measure(View.java:8313)
ERROR/AndroidRuntime(363): at android.view.ViewRoot.performTraversals(ViewRoot.java:839)
ERROR/AndroidRuntime(363): at android.view.ViewRoot.handleMessage(ViewRoot.java:1859)
ERROR/AndroidRuntime(363): at android.os.Handler.dispatchMessage(Handler.java:99)
ERROR/AndroidRuntime(363): at android.os.Looper.loop(Looper.java:123)
ERROR/AndroidRuntime(363): at android.app.ActivityThread.main(ActivityThread.java:3683)
ERROR/AndroidRuntime(363): at java.lang.reflect.Method.invokeNative(Native Method)
ERROR/AndroidRuntime(363): at java.lang.reflect.Method.invoke(Method.java:507)
ERROR/AndroidRuntime(363): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
ERROR/AndroidRuntime(363): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
ERROR/AndroidRuntime(363): at dalvik.system.NativeStart.main(Native Method)
Thank you for any insight you may lend.
You appear to have two launcher activities defined in your manifest:
...
<activity android:name=".DungeonsDragonsAppActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".CreateCharacterTabsActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.category.LAUNCHER"></action>
</intent-filter>
</activity>
...
This would likely cause the TabManager to crash.
Be careful using this
inside of Inner Classes! I make this mistake regularly, and usually in relation to passing a Context
to something!
Make sure you use the correct syntax to get to the "outer" this
, e.g.MyOuterClass.this
.
精彩评论