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.
Related
I have a MainActivity, which contains ImageView, TextView and 3 clickable Buttons.
After clicking the button, I want to change something in SQlite dtb and according that load different data, but show it again in the same activity.
public void ClickBtn(View v)
{
//insertData(String...
Intent intent = new Intent(MainActivity.this, MainActivity.class);
startActivity(intent);
}
So generally - in Main Activity.js I am getting the data from ID, which was clicked before and show that data. The MainActivity should be used infinity times to show different data.
The layout will be always the same - ImageView, TextView and 3 clickable Buttons, just the text will be different.
The question is, how can I only change content inside the same Activity?
I don't think Intent intent = new Intent(MainActivity.this, MainActivity.class); from the current activity can open the same activity...
You really need to study the basics.
When you are working in android, XML layout files are merely blueprints which ultimately are parsed into a reflection-created anonymous view instance, which contains as children each of the members of the XML layout, with the valid XML tag parameters applied to them. Therefore, you aren't dealing with 'Layouts', but with java/kotlin objects, which can be:
Referenced
Mutated
Replaced
So, if you want to change the contents, the first steps is to keep a reference to each object: ImageView, TextView and Buttons, and move the code in charge of filling them to a new method, so you can call it either when loading the activity (onCreate), or when clicking the button. That way the same activity can perform the same action over and over.
Finally, constant recreation of an activity is a TERRIBLE idea. For every object you generate (and an activity IS an object, like everything else), you need X+Y memory, where X is the sum of all the members of the object's class, and Y is the sum of all the operations necessary for instantiation, so by recreating the activity constantly, you waste the device resources, with the added problem of generating a huge backstack of identical activities.
Take a look at a java book, then a kotlin one. It will make your life easier.
This is how I solved it. Just replacing text without refreshing activity. Tested it hundred times also via Memory monitoring and absolutely no impact on device memory.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//get from dtb
int room = 1; int a1 = 2; int a2 = 3; int a3 =4;
TextView views = findViewById(R.id.text1);
views.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//get from dtb - img, text where room = a1;
TextView vv = findViewById(R.id.textof);
vv.setText("text from dtb");
}
});
TextView view2 = findViewById(R.id.text2);
view2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//get from dtb - img, text where room = a2;
TextView vv = findViewById(R.id.textof);
vv.setText("another text from dtb");
}
});
}
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
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.
I know this is a very basic question, however as a newbie i cant get to work around it.
So, I want to have multiple activities to use same the xml layout(consist for example of 1 imagebutton, and multiple textviews with different IDs). Now, for every activity, I want them to view the same layout but override the views with data unique to every activity. What is the best way to do this? And also, the imagebutton should open different URLs in a video player(youtube links).
And can somebody tell me what is the most practical way to learn android programming?
UPDATE
This is my current code:
public class TemakiActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.contentviewer);
}
}
For example I have a textview with ID "descriptionviewer", and a button with ID "videolink", now, how do you code those in?
You can share the same layout file and the set the attributes for views in the onCreate(..) method of each activity.
If you want a different URL to open for each image button you could set it at runtime as follows
public void onCreate(Bundle b) {
Button button =(Button)findViewById(R.id.button);
button.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
//different action for each activity
}
});
}
Yes you can! I had multiple activities inflate the same layout but they save different shared preferences.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.same_layout);
TextView urlDesc = (TextView)findViewById(R.id.descriptionviewer);
urlDesc.setText("url_1"); //now in other activities-- urlDesc.setText("url_2");
ImageButton aButton = (ImageButton)findViewById(R.id.videolink);
aButton.setOnClickListener(aButtonListener);
}
private OnClickListener aButtonListener = new OnClickListener() {
public void onClick(View v) {
// go open url_1 here. In other activities, open url_x, url_y, url_z
finish();
}
};
Same code just swapping the text you want to set for the TextView and url to open in OnClickListener(). No more to change.
Is it possible to add a button to the right corner of the app title?
e.g., adding a "refresh" button to the title of "Feed: my feeds"?
http://www.android.com/market/apps/feedr-lg-01.jpg
The simplest way to do that, IMHO, is to get rid of the standard title bar (android:theme="#android:style/Theme.NoTitleBar" in the <activity> element in the manifest) and put your own "title bar" at the top of the activity.
Note, though, that the "button in the title bar" style is more iPhone-ish. Android would typically have that in the option menu, so the UI is less cluttered (at the cost of two taps to do the refresh).
Why don't you try this
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final boolean customTitle= requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.main);
if ( customTitle ) {
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, Set your layout for title here and mention your button in this layout);
}
final TextView myTitleText = (TextView) findViewById(R.id.myTitle);
if ( myTitleText != null ) {
myTitleText.setText("NEW TITLE");
myTitleText.setBackgroundColor(Color.BLUE);
}
}
yep this solveed an issue i had... trimmed version is below...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.main);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, Set your layout for title here and mention your button in this layout);
final TextView myTitleText = (TextView) findViewById(R.id.myTitle);
if ( myTitleText != null ) {
/* your code here */
}
}
I think a better approach would be to simply refresh the view if it is active by using a Handler. If your pulling content when the activity is resumed then any time you leave and come back to the view it will refresh. If you are expecting users to sit at the top level of the view and need to update the information then you can handle this with a delayed handler which will call your resume method and periodically refresh the view thus negating the need for a button.
Here is a link to the documentation for the handler class. I would start by looking into the basic use of handler. Then test the sendMessageDelayed method so that at the end of every call you restart the handler. Also be sure to only create a new handler if your activity is the top activity and don't bother refreshing the ui if it is not. Adding a simple isActive flag to on pause and on resume is a decent way to check for this.