Android SetText Null pointer Exception - android

I've just begin Android development and I'm sure you can help with this (I'm sorry about my bad English)
I have a main activity, and at a certain moment i want to call another activity, in wich a want to change a textview with some message. At this moment I get a Null pointer Exception if I dont put
setContentView(R.layout.register);
But when I put that line, I see for a milisecond correctly the Register activiy with my new text "Android2" and then jump again to a register activity with no text. I mean I draw it twice.
I hope I have explained enough.
The question is Where do I have to put setcontentview and with what layaout.
Thank you very much, Daniel
I show you some code:
My main activity has this method:
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (requestCode == REQUEST_CODE && resultCode == RESULT_OK)
{
Intent i = new Intent(this, register.class);
startActivity(i);
setContentView(R.layout.register);
TextView text = (TextView) findViewById(R.id.texto);
try {
text.setText("Android2");
}catch(Exception e) {
Log.i("Log", e.getMessage()+"Error!"); // LogCat message
}
}
//super.onActivityResult(requestCode, resultCode, data);
}
My second activity class called register:
public class register extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.register);
}
}
The register Interface is register.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/about_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="#string/register" />
<TextView
android:id="#+id/texto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="#+id/continue_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#string/save" />
<Button
android:id="#+id/new_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#string/repeat" />
</LinearLayout>
</LinearLayout>

What you basically do is the following:
you prepare an intent to start another activity
you start the activity you prepared the intent for
you set the current activity's content to R.layout.register
you get the textView (on the current activity)
you set the text of the textView to Android2
And, at this moment the new activity appears on the screen. Please note that your code is not correct, since you manipulate UI elements in the current activity and you expect changes on the newly started activity.
Move this code
TextView text = (TextView) findViewById(R.id.texto);
try {
text.setText("Android2");
}catch(Exception e) {
Log.i("Log", e.getMessage()+"Error!"); // LogCat message
}
to the register activity's onCreate() method.
BTW, usually, when you create a class, it's name should begin with a capital letter according to the standards.

You have two different activities. One of them is using the register.xml view, and the second one is trying to access the register view. The view only exists in your "register" activity. The other activity seems to have no view? That's probably why you're getting NULL.
You should merge those two classes together, since it looks like you're trying to access texto from the same view.
So, to summarise, findViewById should be called from within the activity that calls setContentView.

Remove this line and it should work
startActivity(i);
Not sure why you are calling that as an external activity.
Otherwise move below code to your register class
setContentView(R.layout.register);
TextView text = (TextView) findViewById(R.id.texto);
try {
text.setText("Android2");
}catch(Exception e) {
Log.i("Log", e.getMessage()+"Error!"); // LogCat message
}
}

Related

In android, How to resume previous activity , on button click from second activity

I have a form to be filled by user and next button "Next" in Activity1.
When user clicks "Next" button second activity Activity2 is started.
In Activity2 i have previous button "Previous".(* not device back button)
So when user clicks " Previous" button, Activity1 should be opened with the entered details in the form.
Activity1 should not be refreshed.
Seached alot on stackoverflow but no luck..!!!
Why don't you use startActivityForResults and then in the started activity finish()
In the started activity you have access to your intent in the onCreate method getIntent(); then you can use setResult(Activity.RESULT_OK, result); or setResult(Activity.RESULT_OK); (For canceled Activity.RESULT_CANCELED) to return result code and data and after you set the result you call finish and then return (code doesn't exit the methods if I remember correctly).
Then in the first activity you get the result and handle what to do with it in:
onActivityResult(int requestCode, int resultCode, Intent data)
Another option:
You could also use the logic for back button pressed calling the method from your code: super.onBackPressed();
Edit
As I promised here's an Example
Two activities - first one have two TextViews and a button next that launches the second activity -> in the second activity two EditTexts in which you enter some data which is then returned to the first activity when you press previous button. If you press back button instead of previous button, you enter in the canceled logic which is not doing anything in the example there is only a comment.
MainActivity
TextView textViewFirstName;
TextView textViewFamilyName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textViewFirstName = (TextView)findViewById(R.id.first_name_edit_text);
textViewFamilyName = (TextView)findViewById(R.id.family_name_edit_text);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
//requestCode here is 12345 that we passed when we started SecondActivity
if(resultCode == Activity.RESULT_OK){
String resultFirstName = data.getStringExtra("firstName");
String resultFamilyName = data.getStringExtra("familyName");
textViewFirstName.setText(resultFirstName);
textViewFamilyName.setText(resultFamilyName);
}
if (resultCode == Activity.RESULT_CANCELED) {
//Canceled logic
}
}
public void nextButtonClick(View view) {
Intent i = new Intent(view.getContext(), SecondActivity.class);
//If you want you could pass some additional data, like which action to take
//if you're reusing the second activity for more than one use case
i.putExtra("someAdditionalData", "Some string that you want to pass");
//12345 is int that you pass and will be returned as requestCode in onActivityResult
startActivityForResult(i, 12345);
}
SecondActivity
EditText editTextFirstName;
EditText editTextFamilyName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
editTextFirstName = (EditText)findViewById(R.id.first_name_edit_text);
editTextFamilyName = (EditText)findViewById(R.id.family_name_edit_text);
Bundle bundle = getIntent().getExtras();
String someAdditionalData = bundle.getString("someAdditionalData");
}
public void previousButtonClick(View view) {
Intent returnIntent = new Intent();
returnIntent.putExtra("firstName", editTextFirstName.getText().toString());
returnIntent.putExtra("familyName", editTextFamilyName.getText().toString());
setResult(RESULT_OK, returnIntent);
finish();
}
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:text="Main"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:hint="First name"
android:id="#+id/first_name_edit_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<TextView
android:hint="Family name"
android:id="#+id/family_name_edit_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<Button
android:onClick="nextButtonClick"
android:text="Next"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
second_activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".SecondActivity">
<TextView
android:text="Second"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<EditText
android:hint="First name"
android:id="#+id/first_name_edit_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<EditText
android:hint="Family name"
android:id="#+id/family_name_edit_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<Button
android:onClick="previousButtonClick"
android:text="Previous"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
On previousButton onClickListener you can call finish();
This will close the current activity and reload the previous one from the stack. This is a quick hack.
Try overriding onBackPressed method inside second activity and call it on click event of previous button
Inside Activity 2
#Override
public void onBackPressed()
{
super.onBackPressed();
}
And call this on previous button click event
buttonPrevious.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
onBackPressed();
}
});
I would refrain from using finish(); cuz it kills the activity from where it's called. Try to use:
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
instead of finish();

Passing data from an Activity to a Layout in Android

I have an Android Activity as below.
public class DummyActivity extends android.support.v7.app.ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dummy_layout);
Intent intent = getIntent();
int dots = intent.getExtras().getInt("dots");
}
}
This activity gets the value of dots from another activity without any problem.
Now I want to pass dots to the layout dummy_layout which is given below.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<com.test.DummyView
android:id="#+id/dummyView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
/>
</LinearLayout>
I tried creating a hidden field in 'dummy_layout' but could not get it working. Is there any straight forward way I can do this ?. I need to access the value of 'dots' in the init method of 'dummyView' which is the class handling 'dummy_layout' as seen in the layout xml.
Why don't you just do
((DummyView) findViewById(R.id.dummyView)).setDots(dots)
in your onCreate?

oncreate function doesnt start

Trying to launch another activity from my main activity using a button i placed on my main activity, now when the button is clicked it prints "call activity" and so it works fine, but when the second activity is launched it seems like it doesn't execute oncreate method, as it doesn't print "start" and doesn't call GetCar(); method. The only thing it does is to show the xml.
button that launches second activity (print "call activity" is working fine)
public void allCars(View v){
setContentView(R.layout.activity_cars_menu);
System.out.println("call activity");
}
second activity code (doesn't print "start" or call GetCar().)
public class CarsMenu extends Activity {
Button btn;
public static String[] carId;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cars_menu);
System.out.println("start");
GetCar();
}
}
second activity xml (can't see viewlist probably because i can't set text (doesn't call GetCar()) .
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
all of my activity is on the manifest and i'm not getting any errors on logcat.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${packageName}.${activityClass}" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:onClick="btnCarClick"
android:text="Refresh" />
<ListView
android:id="#+id/MlistView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/button1"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true">
</ListView>
</RelativeLayout>
You might want to start your Activity:
Intent myIntent = new Intent(CurrentActivity.this, NextActivity.class);
startActivity(myIntent);
Just setting the content view is not enough
Your starting your second Activity in the wrong way, and you only change your view in your first Activity.
In order to change activity you need to call
startActivity (Intent intent)
for more info you can read on
http://developer.android.com/training/basics/firstapp/starting-activity.html
Actually you are just changing the content UI of current activity. As
setContentView(R.layout.activity_cars_menu);
does only that. In real your 2nd activity is never started even. For starting second activity you should do
Intent i = new Intent (Activity1.this, CarsMenu.class);
startActivity (i);
Make sure you have added CarsMenu activity to your Android Manifest.

Android toggle button display wrong value after orientation change

Here is my problem.
I've got a simple activity which set a layout, and add rows in a table-layout(itself in a scroll view).
Those table-rows have a custom layout with a text-field and a toggle button.
Each toggle button has a value taken from a database, and when I first create the activity, the values are OK. But when I turn the device and then change the orientation, all the toggles-button take "false" value. I printed the values that I set in the Logcat, and the values are the good ones (those in the database).
I thought something like the layout I want is hidden behind another layout, but I made some tests and the text-fields change with new values, so I really don't understand why the toggle buttons don't work.
Here is the code :
TableRow layout :
<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<RelativeLayout
android:id="#+id/relativelayout_row_parametres"
android:layout_width="fill_parent"
android:layout_height="50dp"
android:layout_weight="1.0">
<TextView
android:id="#+id/textview_row_parametres"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#android:color/black"
android:textStyle="bold"
android:textSize="20sp"
android:layout_marginLeft="2dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
/>
<ToggleButton
android:id="#+id/togglebutton_row_parametres"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="2dp"
android:textOn="#string/togglebutton_on"
android:textOff="#string/togglebutton_off" />
</RelativeLayout>
</TableRow>
Activity Layout :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ImageView style="#style/header" />
<LinearLayout
android:layout_width="fill_parent" android:layout_height="0dp"
android:layout_weight="0.8"
android:background="#drawable/gradient_bg"
android:padding="10dip"
android:orientation="vertical">
<ScrollView
android:layout_width="fill_parent" android:layout_height="0dp"
android:layout_weight="0.85"
android:fillViewport="true"
android:padding="10dip"
android:layout_gravity="center">
<TableLayout
android:id="#+id/tablelayout_parametres"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/cornered_bg"
android:paddingTop="5dip"
android:paddingBottom="5dip">
</TableLayout>
</ScrollView>
<Button
android:id="#+id/button_parametres_accept"
android:gravity="center"
android:text="#string/accept_changes"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="0.15"
android:layout_gravity="center_horizontal" />
</LinearLayout>
</LinearLayout>
And the activity code:
public class Parameters extends Activity {
#Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Map<String, Boolean> changes = new HashMap<String, Boolean>();
final Context ctx = getApplicationContext();
LanguageManager.updateConfig(this);
setContentView(R.layout.parametres);
CountryDB[] countries = Database.instance(getApplicationContext()).getCountries();
TableLayout tabLayout = (TableLayout) findViewById(R.id.tablelayout_parametres);
for(int i =0; i<countries.length; i++){
TableRow newRow = (TableRow) getLayoutInflater().inflate(R.layout.row_parametres, null);
TextView textView = (TextView) newRow.findViewById(R.id.textview_row_parametres);
ToggleButton toggleButton = (ToggleButton) newRow.findViewById(R.id.togglebutton_row_parametres);
toggleButton.setChecked(countries[i].isToSynchronize());
toggleButton.setTag(countries[i]);
Log.e("setChecked",""+toggleButton.getId()+"/"+countries[i].isToSynchronize());
textView.setText(countries[i].getLabel());
toggleButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
CountryDB countryTemp = (CountryDB) v.getTag();
changes.put(countryTemp.getLabel(), ((ToggleButton)v).isChecked());
}
});
tabLayout.addView(newRow);
TableRow rowDivider = (TableRow) getLayoutInflater().inflate(R.layout.row_divider, null);
tabLayout.addView(rowDivider);
}
Button buttonValidation = (Button) findViewById(R.id.button_parameters_accept);
buttonValidation.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Iterator<String> iterator = changes.keySet().iterator();
while(iterator.hasNext()){
String stringTemp = iterator.next();
Database.instance(ctx).updateCountry(stringTemp, changes.get(stringTemp));
}
Intent intent = new Intent(ctx, Splash.class);
String result = "restart";
String from = "parameters";
Intent returnIntent = new Intent();
returnIntent.putExtra("result", result);
returnIntent.putExtra("from", from);
setResult(RESULT_OK, returnIntent);
startActivity(intent);
}
});
}
}
In the Log.e, I print the values, and they are good, the display on togglebuttons is wrong, they are just all "false".
Thanks for your help.
Between onCreate() and onResume() , Android tries to restore the old state of the toggle Buttons. Since they don't have unique ID's , Android wont succeed and everything is false again. Try to move your setChecked() calls into onResume() ( maybe onStart() works too).
Here is a pretty good answer to the same Question:
ToggleButton change state on orientation changed
you have to save data before Orientation.
Android have method onSaveImstamceState(Bundle outState) and onRestoreInstanceState(BundleInstaceState)
override these method in Activity.
There's a simpler solution: you only need to add configChanges property to your activity declaration, like stated here. This way you can prevent Activity restart when orientation changes. So in your manifest you should have something like
<activity android:name=".Parameters"
android:configChanges="orientation|keyboardHidden">
or if your buildTarget>=13
<activity android:name=".Parameters"
android:configChanges="orientation|keyboardHidden|screenSize">
Edit: Like reported on comments below, this is not an optimal solution. The main drawback is reported in a note of the document linked above:
Note: Handling the configuration change yourself can make it much more difficult to use alternative resources, because the system does not automatically apply them for you. This technique should be considered a last resort when you must avoid restarts due to a configuration change and is not recommended for most applications.

Coupling Android layout to its logic outside of the owner Activity

I'm facing some complexities when developing a medium-complex Android application. I'm searching for information about the possibility of using code-behind-like techniques for easier maintanability of Android software.
Currently (please highlight anything wrong), I have found that in order to make a multi-step wizard with extra dialogs (eg. dialogs that are not part of the main sequence) I need to code a single XML layout file with a single ViewFlipper containing each subview as child node. Today I discovered how to navigate across views more than forward/backward (viewFlipper.setDisplayedChild(i)), giving access to extra views.
Now all the Java code is contained within the main Activity class, which is beginning to look bad. As an experienced .NET developer I have learned how to use custom controls to wrap both layout and business logic inside modules.
I know that in Android I can define a view programmatically as an independent class and add it to the main layout programmatically, however I want to know if it's possible in Android to define a layout by XML (for easier WYSIWYG creation/editing) and define all the code within a dedicated class, with initialization logic, button callbacks, async tasks, etc.
I'm not sure if it's feasible or there is a good compromise that can be achieved.
I have read this question without clearing my doubts.
Thank you.
Code examples:
An extract of the layout file (I expect 4 wizard steps, a help view and an EULA view)
<?xml version="1.0" encoding="utf-8"?>
<ViewFlipper xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/view_phone"
style="#android:style/Theme.Light.NoTitleBar"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<!-- First screen/welcome -->
<LinearLayout
android:id="#+id/view_phone_screen1"
style="#android:style/Theme.Light.NoTitleBar"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:weightSum="100" >
<TextView
android:id="#+id/view_phone_screen1_lblChooseProvider"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal"
android:text="#string/view_phone_lblChooseProvider_1ststep"
android:textAppearance="?android:attr/textAppearanceLarge" />
<ImageButton
android:id="#+id/view_phone_btnFrecciarossa"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:contentDescription="#string/provider_FRECCIAROSSA"
android:gravity="center_vertical|clip_vertical"
android:padding="10dp"
android:src="#drawable/logo_frecciarossa"
android:tag="#+id/provider_FRECCIAROSSA" />
<ImageButton
android:id="#+id/view_phone_btnItalo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:contentDescription="#string/provider_ITALO"
android:gravity="center_vertical|clip_vertical"
android:padding="10dp"
android:src="#drawable/logo_italo"
android:tag="#+id/provider_ITALO" />
</LinearLayout>
<!-- Second screen - will need to do some asynchronous task -->
<RelativeLayout
android:id="#+id/view_phone_screen2"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:id="#+id/view_phone_screen2_lblConnectingToWifi"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal"
android:text="#string/view_phone_lblConnectToWifi_2ndstep"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/view_phone_step2_lblConnectedToWifi"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/imageView1"
android:layout_centerHorizontal="true"
android:layout_marginTop="58dp"
android:text="#string/view_phone_step2_connectingToWifi"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/view_phone_step2_lblPhoneNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/editText1"
android:layout_below="#+id/view_phone_step2_lblConnectedToWifi"
android:layout_marginTop="51dp"
android:text="#string/view_phone_step2_msgInputPhoneNumber"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/view_phone_step2_lblUnableDetectPhoneNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="#string/view_phone_step2_msgUnableDetectPhoneNumber"
android:textAppearance="?android:attr/textAppearanceSmall"
android:visibility="invisible" />
<Button
android:id="#+id/view_phone_screen2_backward"
style="#style/buttonBackward" />
<Button
android:id="#+id/view_phone_screen2_forward"
style="#style/buttonForward_disabled"
android:enabled="false" />
<EditText
android:id="#+id/view_phone_step2_txtPhoneNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignRight="#+id/view_phone_step2_lblPhoneNumber"
android:layout_below="#+id/view_phone_step2_lblPhoneNumber"
android:inputType="phone"
android:singleLine="true" >
<requestFocus />
</EditText>
</RelativeLayout>
</ViewFlipper>
Code example from Activity (expect to implement ALL the logic of 4+2 step wizard)
public class MyActivity extends Activity {
/** Called when the activity is first created. */
private final static String LOG_TAG = "LOG_TAG";
private int stepNumber;
#Override
public void onCreate(Bundle savedInstanceState) {
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
super.onCreate(savedInstanceState);
this.stepNumber=1;
setContentView(R.layout.view_phone);
//This class wraps the click for the two buttons
ProviderSelectionListener providerSelectionListener = new ProviderSelectionListener(this);
this.findViewById(R.id.view_phone_btnFrecciarossa).setOnClickListener(providerSelectionListener);
this.findViewById(R.id.view_phone_btnItalo).setOnClickListener(providerSelectionListener);
}
#Override
protected void onPause() {
super.onPause();
try {
if (MyApplication.getPlatformManager() != null)
MyApplication.getPlatformManager().onApplicationPause();
} catch (MyCustomException e) {
// WTF (Worse Than Failure!)
Log.e(LOG_TAG, super.getString(R.string.zf_error_unknown_error_pauseactivity), e);
e.printStackTrace();
}
}
#Override
protected void onResume() {
super.onResume();
try {
if (MyApplication.getPlatformManager() != null)
MyApplication.getPlatformManager().onApplicationResume();
} catch (MyCustomException e) {
// WTF (Worse Than Failure!)
Log.e(LOG_TAG, super.getString(R.string.zf_error_unknown_error_pauseactivity), e);
e.printStackTrace();
}
}
/*
* SLIDE INIZIO
*/
protected void slideNext() {
ViewFlipper vf = (ViewFlipper) findViewById(R.id.view_phone);
vf.setOutAnimation(getApplicationContext(), R.anim.slide_out_left);
vf.setInAnimation(getApplicationContext(), R.anim.slide_in_right);
vf.showNext();
}
protected void slidePrevious() {
ViewFlipper vf = (ViewFlipper) findViewById(R.id.view_phone);
vf.setOutAnimation(getApplicationContext(), R.anim.slide_out_right);
vf.setInAnimation(getApplicationContext(), R.anim.slide_in_left);
vf.showPrevious();
}
/*
* SLIDE FINE
*/
/*
* STEP 1 INIZIO
*/
public void completeStep1(ISmsWifiProvider provider) {
if (provider == null) {
Log.e(LOG_TAG, "Provider nullo");
return;
}
MyApplication.setAuthenticationProvider(provider);
slideNext();
initializeStep2();
}
public void returnToStep1() {
MyApplication.setAuthenticationProvider(null);
slidePrevious();
}
/*
* STEP 1 FINE
*/
/*
* STEP 2 INIZIO
*/
private void initializeStep2() {
// Event handler
Button backButton = (Button) findViewById(R.id.view_phone_screen2_backward), fwButton = (Button) findViewById(R.id.view_phone_screen2_forward);
fwButton.setEnabled(false);
backButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
returnToStep1();
}
});
}
/*
* STEP 2 FINE
*/
#Override
public void onBackPressed() {
// This will be called either automatically for you on 2.0
// or later, or by the code above on earlier versions of the
// platform.
return;
}
}
I want to know if it's possible in Android to define a layout by XML (for easier WYSIWYG creation/editing) and define all the code within a dedicated class, with initialization logic, button callbacks, async tasks, etc.
Yes. It is one of the techniques for creating a custom View. For example, I have a custom ColorMixer widget in this project, which can be used directly in an activity, or in a dialog, or in a custom preference.
I agree with your tactical decision to implement a wizard via a ViewFlipper -- see this answer to another StackOverflow question for "Murphy's Theory of the Activity".
I suspect that the right answer, longer term, is for somebody (who might be me) to come up with a Fragment-based wizard pattern, as that gives you the decoupling you desire.

Categories

Resources