In short, I set up a tabhost, and since I want the tab's content to have dynamic TextView's (among other things), I try initializing the text and it crashes. I am unsure of why, but commenting out the code that sets the text in the TextView's stopped the crashing.
One reference towards fixing this mentioned using intents to set activities for the tab's content, but apparently this didn't actually fix the crashing, it somehow changed it and then that lead died out without him ever saying how he fixed it, and my attempt at it also failed.
package com.example.main;
//removed imports
#SuppressWarnings("deprecation")
public class MainActivity extends TabActivity {
private boolean atMainMenu;
TextView warframeText;
TextView primaryText;
TextView secondaryText;
TextView meleeText;
TextView sentinelText;
TextView sentinelWeaponText;
Warframe warframe;
PrimaryWeapon primary;
SecondaryWeapon secondary;
MeleeWeapon melee;
Sentinel sentinel;
Weapon sentinelWeapon;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
TabHost mTabHost = getTabHost();
//TabHost
mTabHost.addTab(mTabHost.newTabSpec("tab1").setIndicator("Build").setContent(R.id.build));
mTabHost.addTab(mTabHost.newTabSpec("tab2").setIndicator("Stats").setContent(R.id.stats));
TextView title1 = (TextView)mTabHost.getTabWidget().getChildAt(0).findViewById(android.R.id.title);
title1.setTextColor(Color.parseColor("#30A0F0"));
TextView title2 = (TextView)mTabHost.getTabWidget().getChildAt(1).findViewById(android.R.id.title);
title2.setTextColor(Color.parseColor("#30A0F0"));
mTabHost.setCurrentTab(0);
warframeText = (TextView)findViewById(R.id.warframe);
primaryText = (TextView)findViewById(R.id.primary);
secondaryText = (TextView)findViewById(R.id.secondary);
meleeText = (TextView)findViewById(R.id.melee);
sentinelText = (TextView)findViewById(R.id.sentinel);
sentinelWeaponText = (TextView)findViewById(R.id.sentinelWeapon);
//Change To First Time Setup
warframe = new Excalibur();
primary = new BratonMk1();
secondary = new Lato();
melee = new Skana();
setBuild(); //<--removing this fixed the crashing, the method is included after onCreate, it sets the TextView's text
atMainMenu = true;
}
public void setBuild() {
warframeText.setText(warframe.getName());
primaryText.setText(primary.getName());
secondaryText.setText(secondary.getName());
meleeText.setText(melee.getName());
sentinelText.setText(sentinel.getName());
sentinelWeaponText.setText(sentinelWeapon.getName());
}
}
So what I would like to know, if anyone has the answer, why does editing the Textviews contained in a tab layout cause the app to crash and how can I fix this? :/
(also the code I provided is quite shortened, but I believe it contains all the relevant parts to the problem)
You did not initialize sentinel and sentinelWeapon but you are trying to get name from that
sentinelText.setText(sentinel.getName());
sentinelWeaponText.setText(sentinelWeapon.getName());
It May be a cause to your app get crashed
Related
I am dynamically adding views to Android and am seeing a really weird result which makes little to no sense. Here is the code that shows the bug:
private static int count = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
count++;
// Allow 'up' action for actionBar
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle("TEST");
setContentView(R.layout.test);
LinearLayout testLinear = (LinearLayout)findViewById(R.id.testLinear);
LayoutInflater inflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.job_step_text, null, false);
TextView title = (TextView) view.findViewById(R.id.jobStepTextTextView);
final EditText editText = (EditText)view.findViewById(R.id.jobStepEditText);
title.setText("Field 1");
editText.setText("Value 1");
testLinear.addView(view);
if(count == 1) {
View view2 = inflater.inflate(R.layout.job_step_text, null, false);
TextView title2 = (TextView) view2.findViewById(R.id.jobStepTextTextView);
final EditText editText2 = (EditText)view2.findViewById(R.id.jobStepEditText);
title2.setText("Field 2");
editText2.setText("Value 2");
testLinear.addView(view2);
}
}
First time round the Activity is as follows:
Field 1: [ Value 1 ]
Field 2: [ Value 2 ]
Then when the device rotates the following is shown:
Field 1: [ Value 2 ]
Can anyone help? It seems that after the first time round the line:
final EditText editText = (EditText)view.findViewById(R.id.jobStepEditText);
is fetching an old reference and not calling setText()? When the screen rotates the line of code which sets the text field to 'Value 2' isn't even called and yet that's the result in the Field 1 text box.
Can anyone help?
By the way - a way to fix this is to give each EditText a unique ID before adding it to the view... but that makes no sense... Surely the inflated View has no knowledge of any other views (past or present) until testLinear.addView(view); is added?
Thanks in advance.
The onSaveInstanceState in the Activity (your super class) captures information about the attached content view and reloads it for you during onCreate() So when the Activity gets recreated after the device rotates, values are put into views found by ID as soon as you call setContentView(). This can produce surprising results if you are changing your layout on-the-fly.
One approach I have used is to call findViewById to see if the child view is already present, before adding it "by hand".
Another approach would be to inflate the layout first, make your adjustments to it, then call setContentView.
[I don't quite understand Android's reason for doing this -- maybe to allow super-simple applications to skip the onSaveInstanceState/reload from bundle process??)
Trying to get started with Android development, and doing some basic work with TextViews..
For some reason TextView's setText() method is causing huge problems for me.. here's a simplified version of my code to show what I mean:
package com.example.testapp;
import android.os.Bundle;
import android.app.Activity;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView text;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
text = (TextView) findViewById(R.id.text1);
setContentView(R.layout.activity_main);
text.setText("literally anything");
}
}
This will cause a crash, and I don't understand why.. if I create the TextView within the onCreate it works just fine, but if I create it outside of it, it doesn't.. why is that? Has the line "TextView text;" not been executed yet or something?
Thanks!
You need to call setContentView() before initializing the TextView so that your Activity has access to all the layout components.
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.text1);
text.setText("literally anything");
switch these 2 lines
text = (TextView) findViewById(R.id.text1);
setContentView(R.layout.activity_main);
you need to set the content first
From docs:
onCreate(Bundle) is where you initialize your activity. Most
importantly, here you will usually call setContentView(int) with a
layout resource defining your UI, and using findViewById(int) to
retrieve the widgets in that UI that you need to interact with
programmatically.
So this means that if you will reference your views in the layout, you must first set the content view and already then call findViewById method to reference child views of the layout resource defining your activity's UI
text = (TextView) findViewById(R.id.text1);
setContentView(R.layout.activity_main);
text.setText("literally anything");
If "literally anything" is a variable, which often may be the case, be sure that it isn't throwing a NullPointerException. I kept having that problem myself. I fixed it to be:
text = (TextView) findViewById(R.id.text1);
setContentView(R.layout.activity_main);
try {
text.setText("literally anything");
} catch (NullPointerException e) {
// Do something
}
Exceptions can be really useful, so if you're a beginning programmer, I suggest you put exception handling on your list of things to learn soon.
After a click on button1, another layout and another class gets called.
Now I want to change the text of textView out of class 2 which results in an app crash with java.lang.NullPointerException
important parts of Class 1
public static TextView A;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
[button stuff in class 1]
setContentView(R.layout.raten);
final TextView A = (TextView) findViewById(R.id.A); //the textview I wanna chage
max = 10;
Easy easy = new Easy(); // the other class
easy.e();
[now the method in class 1 that should change the text]
public static void Tx(int i)
{
A.setText("adsfasdf");
}
[important parts of Class 2 ("Easy")]
public void e(){
System.out.println("called class easy");
int max = MainActivity.max;
System.out.println(max);
for (int i= 0; i<max; i++){
System.out.println("runde"+i);
MainActivity.Tx(i);
}
I know, some people already asked such questions but I didn't find a working solution. I already understood, that you can't access the UI things outside the UI thread and that the nullpointerexception appears, because he uses the "empty" public static TextView A; and not the final TextView A = (TextView) findViewById(R.id.A).
But how I can make it visible for the other methods?
Sorry if the post looks messed up but I didn't konw how to explain my situation in a better way
Rather than defining a new local variable A, just assign to the static.
change
final TextView A = (TextView) findViewById(R.id.A); //the textview I wanna chage
to
A = (TextView) findViewById(R.id.A); //the textview I wanna chage
remove static from both A and Tx
(of course your MainActivity must be created by the time you call easy.e())
I'm new to android, so maybe I'm doing something horribly wrong. I want to have a particular Activity that shows details about an instance of a "Creature" class for a game. Name, damage taken, that sort of thing.
I'm having a problem getting the creature data to be properly shown in the GUI objects. Both at initial creation (where it should copy the creature's name into the name field) and when a damage mark is added (where it doesn't update to show the proper image).
Here's my mini-example of what I have:
public class CreatureDetailActivity2 extends Activity
{
Creature creature;
public void addMark(View v)
{
// connected to the button via android:onClick="addMark" in the XML
creature.getTrack().addDamage(DamageType.Normal, 1);
refreshDisplay();
new AlertDialog.Builder(this).setTitle(creature.getName())
.setMessage(creature.getTrack().toString()).show();
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_creature_detail);
creature = new Creature("Example");
refreshDisplay();
}
public void refreshDisplay()
{
final View creatureDetailView = this.getLayoutInflater().inflate(
R.layout.activity_creature_detail, null);
final EditText nameField = (EditText) (creatureDetailView
.findViewById(R.id.textbox_creature_name));
nameField.setText(creature.getName());
final ImageView damageBox0 = (ImageView) (creatureDetailView.findViewById(R.id.damageBox0));
damageBox0.setImageResource(R.drawable.__n);
// in the full program this does the same for 0 through 9, but this is a sample
// also, in the full program, this is a dynamic lookup for the correct pic
// but again, this is just a sample version.
}
}
Now the problem is that the app will load up and start, but then none of the widgets will update properly. You can click the button, and it'll show the AlertDialog, and the text of the AlertDialog will change, but the textfield in the activity won't be changed, and the ImageView doesn't change at any point from what it starts as to the one it's supposed to change to.
So I'm very stumped. I can post more about the project's setup if I'm leaving out something important, but I'm not even sure what the problem going on is so I'm not sure what else to include in my question.
final View creatureDetailView = this.getLayoutInflater().inflate(
R.layout.activity_creature_detail, null);
Inflates your Activity's layout into basically nothing, just returning the View it inflated. setContentView is what actually inflates your layout into the Activity's View hierarchy.
Once you inflate your layout you don't need to do it again. Just use findViewById without the reference to a dangling unattached View.
Change your refreshDisplay method to this:
public void refreshDisplay()
{
final EditText nameField = (EditText) findViewById(R.id.textbox_creature_name);
nameField.setText(creature.getName());
final ImageView damageBox0 = (ImageView) findViewById(R.id.damageBox0);
damageBox0.setImageResource(R.drawable.__n);
// in the full program this does the same for 0 through 9, but this is a sample
// also, in the full program, this is a dynamic lookup for the correct pic
// but again, this is just a sample version.
}
Nothing changes because You do it completely wrong.
If You wish to update any view element of current activity You do it like this
View v = findViewById(R.id.element);
v.setText("text");
this is just simple example.
You would need to cast a returned element to correct type like to be able to access all available methods.
What You do wrong is trying to inflate a layout again.
Guys I want the user to change the background image of all the activities in my app on user selection.
I am able to change the background image of the Activity from where am changing the image
but if I try to change the image of other Activity, I get a NullPointerException!
Yes, I have checked that the id of other activity's Layout !
this is the code.
public class setting extends Activity {
TextView tv;
CheckBox cbS, theme1, theme2;
RelativeLayout rel;
OnClickListener checkBoxListener;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.setting);
cbS = (CheckBox) findViewById(R.id.cb);
theme1 = (CheckBox) findViewById(R.id.theme1);
theme2 = (CheckBox) findViewById(R.id.theme2);
// cbW=(CheckBox)findViewById(R.id.cbWordPress);
checkBoxListener = new OnClickListener() {
public void onClick(View v) {
if (cbS.isChecked()) {
// anything
}
if (theme2.isChecked()) {
RelativeLayout rel = (RelativeLayout) findViewById(R.id.rel);
Resources res = getResources();
Drawable drawable = res.getDrawable(R.drawable.back_image1);
rel.setBackgroundDrawable(drawable);
// findViewById(R.id.rel).setBackgroundResource(R.drawable.back_image1);
}
}
};
cbS.setOnClickListener(checkBoxListener);
theme2.setOnClickListener(checkBoxListener);
// cbW.setOnClickListener(checkBoxListener);
}
}
you cannot access the UI components which are not yet instantiated. Use Intents to pass information across activities (user's choice, or some custom flags or Strings) and use this "extra" information in the launched activity to change the background accordingly.
Read more about intents in the documentation for better understanding and examples.
You cannot do this.. When you refer a layout file using findViewById(), the android system looks for this in your current ContentView only. (i.e the view which you have set using setContentView() for the current activity). So obvioulsy the sytem will not be able find the resource you are specifying and hence you will get the NullPointerExeption only.
You have to maintain the reference to the backgrounds separately and use it in your other Activity when you actually pass on there.