How is view state saved/restored in Android? - android

I have this class
public class MainActivity extends Activity {
int mClicks = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView clicksText = (TextView) findViewById(R.id.clicksText);
final Button myButton = (Button) findViewById(R.id.myButton);
myButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mClicks++;
clicksText.setText(mClicks + " clicks");
}
});
}
}
Isn't it supposed to save view state at onSaveInstanceState and restore it at onCreate? I click the button a couple times and rotate the device to find the UI in the exact same state as the view XML defines. I don't expect mClicks to be restored as that is my job, not the framework's but the TextView should hold the previous X clicks! value. Am i wrong here?

You can try using freezesText
http://developer.android.com/reference/android/widget/TextView.html#attr_android:freezesText

The default onSaveInstanceState saves the EditText text (what the user writes) but does not save TextView text because it is supposed that it won't change by default. If you want to save that, you need to explicity do it in you onSaveInstanceState method

Related

Android view isDirty inside onClick

I want to check if the text in some EditText is changed, after user clicks some Button. But View#isDirty seems not to return the correct state of the EditText if called inside onClick. For instance, I wrote something like this:
public class MainActivity extends Activity {
EditText editText;
Button button;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button = (Button) findViewById(R.id.f);
editText = (EditText) findViewById(R.id.e);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
System.out.println((editText.isDirty() ? "is dirty" : "is clean"));
}
});
}
}
before i make any change to the editText, it outputs is clean, as expected. But the same is clean is printed even after I write something in editText.
When will isDirty be called? And is it the correct way to do this at all?
Update:
I also want to check if some Switch and Spinner values are changed. Is isDirty() the correct way to do this?
By the time you click your button edittext is no longer dirty - text is already updated and view redrawn. Maybe if you change your onclick handler you will understand better what is going on.
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
editText = (EditText) findViewById(R.id.e);
System.out.println((editText.isDirty() ? "is dirty" : "is clean"));
}
});
isDirty will return true only as long as view has not been redrawn. This happens quite quickly and basically you do not have (and dont need) any control over this.
I think you need to use some other methods to achieve what you want.
I would suggest to use:
https://stackoverflow.com/a/9459848/5684335
The comment from Okas is a good explanation why.

FindViewById returning null EditText

I have common problem with findViewById() function, it returns null:
<EditText
android:id="#+id/nameText"
/>
<Button
android:text="Save"
android:onClick="buttonClick1"
/>
</TableRow
android:onClick="buttonClick1"
/>
Activity1.java:
public class Activity1 extends ActionBarActivity {
public void buttonClick1(View view) {
setContentView(view);
EditText nameText = (EditText) view.findViewById(R.id.nameText);
EditText lastNameText = (EditText) view.findViewById(R.id.lastNameText);
EditText indexNumberText = (EditText) view.findViewById(R.id.indexNumberText);
Log.d(">>>> ", nameText.getText().toString());
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_activity1);
}
}
}
In buttonClick1() findViewById() returns null. Please explain why?
Remove setContentView(view); from buttonClick1 method
and initialise all your textview in this manner by removing view.
EditText nameText = (EditText) findViewById(R.id.nameText);
EditText lastNameText = (EditText) findViewById(R.id.lastNameText);
EditText indexNumberText = (EditText) findViewById(R.id.indexNumberText);
Also initialize the controls in the xml properly by giving height and width to controls
Multiple problems unless you're not posting all your code.
1) In your XML you close a TableRow tag, but I don't see you opening it. Might just be lazy copy-pasting.
2) In your onCreate you seem to be missing a listener for your button. There is nothing to indicate that you have a button anywhere. You need to find the view of your button as follows:
Button button = (Button) findViewById(R.id.nameOfButton);
Then you need to set a listener for it like this:
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Here goes whatever should happen when you click the button.
}
});
3) As for your ButtonClick1 method, delete it. It looks like you were trying to create a listener, but it is pretty far from what it should look like.
Try to replace your code by this one :
public class Activity1 extends ActionBarActivity {
#
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_activity1);
EditText nameText = (EditText) findViewById(R.id.nameText);
EditText lastNameText = (EditText) findViewById(R.id.lastNameText);
EditText indexNumberText = (EditText) findViewById(R.id.indexNumberText);
}
public void buttonClick1(View view) {
//Your stuff
Log.d(">>>> ", nameText.getText().toString());
}
}
Since now would be the normal code that have you tried, if you want to set a click on a button you'll have to declare it as :
Button button1 = (Button) findViewById(R.id.button1);
Then you can do the :
public void buttonClick1(View v) {
// Your stuff
}
EDIT
Make sure that you have on your XML all of your EditText and all of your Button for example : or , also make sure that you have an android:id="#+id/yourID in all of your stuff..., by the way instead of using an onClick method in your XML for your Button, you could use this to use an OnClickListener
The point 1 to 3 should go inside of onCreate the point 4 should go outside of onCreate.
1.- Implements View.OnClickListener in your Activity1
public class Activity1 extends ActionBarActivity implements View.OnClickListener {
2.- Declare it
Button button1 = (Button) findViewById(R.id.button1);
3.- Do the setOnClickListener like this :
button1.setOnClickListener(this);
4.- Create an OnClick method :
#Override
public void onClick(View view) {
if (View.equals(button1))
//Your stuff
}

How to change TextView multiple times on multiple Button clicks?

I'm kind of new when it comes to Android Application development and I'm developing an app at the moment. I'm trying to get my TextView change every time the user clicks the Button(NEXT) and when another Button (PREVIOUS) gets clicked on I want it to change back to the original TextView. So basically I'd like to set up a certain amount of TextViews and be able to browse through them with the two Buttons I mentioned.
So far I only know how to make the the TextView change one time on a Button(NEXT) click. I'm using this piece of code for that:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageButton Next = (ImageButton) findViewById(R.id.Next);
Next.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
TextView Text1= (TextView) findViewById(R.id.Text1);
Text1.setText("New Text");
}
});
NOTE: The Button "PREVIOUS" isn't included yet because I didn't know what to do with it yet.
I'm getting the feeling this code is only used when you want the TextView to change one time and you need a whole different method to make it change multiple times.
I hope I provided you with enough information and you are willing to help me out here.
Thanks in advance!
public class MyActivity extends Activity implements View.OnClickListener {
int stringIdList[] = {R.string.text1, R.string.text2, R.string.text3, R.string.text4}
int stringListCounter = 0;
TextView text1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageButton next = (ImageButton) findViewById(R.id.Next);
ImageButton previous = (ImageButton) findViewById(R.id.Previous);
text1 = (TextView) findViewById(R.id.Text1);
Next.setOnClickListener(this);
previous.setOnClickListener(this);
}
#Override
public void onClick(View v) {
int id = v.getId();
if(id == R.id.Next && stringListCounter < stringIdList.length - 1) {
stringListCounter++;
} else if (id == R.id.Previous && counter > 0) {
stringListCounter--;
}
Text1.setText(stringIdList[stringListCounter]);
}
What this does is assigns your Activity to an OnClickListener to handle the click events. If Next was pressed and the counter is within the range of the array list, it will increase the counter. The same for previous. At the end of the click, it will set the text to whatever the ID is. This assumes your strings are in a strings.xml file which is recommended in the Android spec and is static.
I think you can store history as List and have all states of textview in each moment.
Only thing that you have to do is to take previous value from this history stack after pressing previous button.

<ToggleButton> onClickListener - Create/Delete button + add content to button

I have this problem with my ToggleButton.
I want it to create/delete a button upon being toggled, and at the same time add content/functions to the button, like drawable and such.
This is the current code:
public class BillardScoreboardActivity extends Activity {
/** Called when the activity is first created. */
Button minuskegle, minuskugle, pluskugle, pluskegle, plusmidkegle, minusmidkegle, miss;
ToggleButton toggle;
LinearLayout bottomlayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
toggle = (ToggleButton) findViewById(R.id.bRedGreen);
toggle.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
pluskugle = (Button) findViewById(R.id.bBallhole);
minuskugle = (Button) findViewById(R.id.bBallhole);
pluskegle = (Button) findViewById(R.id.bKegle);
minuskegle = (Button) findViewById(R.id.bKegle);
plusmidkegle = (Button) findViewById(R.id.bKeglemid);
minusmidkegle = (Button) findViewById(R.id.bKeglemid);
bottomlayout = (LinearLayout) findViewById(R.id.bottomlayout);
miss = (Button) findViewById(R.id.bMiss);
if(toggle.isChecked())
{
minuskugle.setBackgroundResource(R.drawable.redballinhole);
minuskegle.setBackgroundResource(R.drawable.redkegle);
minusmidkegle.setBackgroundResource(R.drawable.midkegleminus);
miss.setBackgroundResource(R.drawable.missbutton);
miss.setVisibility(View.VISIBLE);
}
else
{
pluskugle.setBackgroundResource(R.drawable.whiteballinhole);
pluskegle.setBackgroundResource(R.drawable.kegleb);
plusmidkegle.setBackgroundResource(R.drawable.midkegleplus);
miss.setVisibility(View.GONE);
}
}
});
}
The current problem is that it can't find the (buttontest) in this part of the code:
else
{
pluskugle.setBackgroundResource(R.drawable.whiteballinhole);
pluskegle.setBackgroundResource(R.drawable.kegleb);
plusmidkegle.setBackgroundResource(R.drawable.midkegleplus);
bottomlayout.removeView(buttontest);
}
And as mentioned earlier, the second problem is to make the button inherit some functions/content.
for bigger version: http://i.imgur.com/KxKvh.png
Btw... Everytime i start up the application, it gives me 2 apps to choose between, whereof only the bottom one works:
I guess the problem is that the togglebutton's initial state is 'checked'. That means when you click it the first time, isChecked() will return false and the else-part of your code will be executed. But at that point, buttontest hasn't been added to bottomlayout yet.
I recommend you to have the button inside the layout by default and call buttontest.setVisibility(View.GONE) when you would like to hide it and buttontest.setVisibility(View.VISIBLE) when it needs to be shown.
As for your second question, just call setBackgroundResource/Drawable to add content (like you're already doing it with the other buttons). If you say you want to add functionality, I assume you intend to do something when the button is clicked? If yes, add a View.OnClickListener.
Hope I could help you.

Android Change onClickListener in external method when implementing onClickListener

I'm developing an application where I need to turn off and on the onClicKListener on some buttons.
I have an external run method where I want to toggle on the onClickListener to the buttons. In my onCreate method I have code like this:
button.setOnClickListener(this);
In a method I call externally (that is a method which isn't onCreate) I have a statement which says button.setOnClickListener(null); when a certain condition is fulfilled.
Now I wonder how, to in the same method if another condition is fulfilled turn the onClickListener back on. It doesn't work with button.setOnClickListener(this);
In my activity I'm implementing onClickListener through extends Activity implements OnClickListener or something.
Thanks in advance!
Instead of setting the onClickListener to null every time you don't want the button to work, why not make use of the enabled property?
private Button myButton;
#Override
public void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myButton = (Button) findViewById(R.id.mynewbutton);
myButton.setOnClickListener(/* your click listener here */);
myButton.setEnabled(false);
}
private void whateverFunction() {
if(true) {
myButton.setEnabled(true);
} else {
myButton.setEnabled(false);
}
}
This way you make it not respond to touches when it is disabled.
private boolean enableClick;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
if(enableClick)
{
// do
}
}
}
);
}
You just need to update the value of enableClick.
You can just implement a flag inside the onClick method which will guard the methods executing inside onClick. No need to set onClickListener to null, just set flag to false and the onClick method will do nothing. Hope this helps.

Categories

Resources