Wednesday, October 13, 2010

Using Intent and Bundle to pass String values to a new Activity.

So it took me three days to figure out how to pass on a string value from an old activity to a new one. This version uses bundle and intent.

I have only used this when starting a new activity with a button , list item , and menu item clicks events, although I'm sure it can be applied to many more types. 

You will need two activities. My example uses a list item click to set up a regular intent. A bundle is created with a string value, and its variables are ("unique.key.name", "The string you want to pass on"). (items[position]) is code that displays the text value of the list item that was selected. Then the bundle is added to the intent.

Page1.java
public void onListItemClick(ListView parent, View view, int position, long id) {
     Intent i = new Intent(Page1.this, Page2.class);
Bundle extras = new Bundle();
extras.putString("my.unique.extras.key", (items[position]) + " Details");
i.putExtras(extras);                
startActivity(i);
    }

Page2 activity needs to have a textview item ready to receive the bundle (this would look like uniquetextview.setText(extras.getString("("my.unique.extras.key")). An alternative is to set the bundle to be the activities title, as in my example below.

Page2.java

  // Adds selected listview item to title
        Bundle extras = this.getIntent().getExtras();
if ( extras != null ) {
 if ( extras.containsKey("my.unique.extras.key") ) {
 this.setTitle(extras.getString("my.unique.extras.key"));
 }
}

Thursday, October 7, 2010

Easy ListView with Anchored Header/Footer and "Custom" Row Layout.

This is the basic listview that has been working great for me.

Disclaimer: While the list item view for this is "custom" it does not allow you to provide more than one view per list item. You can customize that one item (background, font, size, color, etc.) To add more views to a list item please see my entry on custom list adapters.

First is the page layout. I only included a simple textview header, but it could easily be replaced with buttons or checkboxes or anything. The surrounding linear layout but be set to "fill_parent" height and width and also have a vertical orientation. The listview width should be set to "fill_parent" so that the whole list row is clickable and not just the text. layout_weight should be set to 1 which will cause the listview to expand to the height of available space in the window, pushing the header or footer to be docked at the top or bottom.



pageone.xml

xmlns:android="http://schemas.android.com/apk/res/android"

  android:layout_height="fill_parent"
  android:layout_width="fill_parent"
  android:orientation="vertical" >

<TextView android:layout_height="wrap_content"
  android:layout_width="fill_parent"
  android:text="This is the Header"
  android:id="@+id/Header" >
</TextView>

<ListView
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:layout_weight="1"
  android:textFilterEnabled="true"
  android:id="@android:id/list" >
</ListView>
</LinearLayout>


The row layout is important if you want to customize the look of your list (like text size, color, etc). Otherwise, android has some built in layouts that can be used. In my example, I am just using a single textview (easily populated by string values using simpleadapter) with a small font. Add more textviews in a horizontal linear layout for columns, or vertical for two rows of text. Use relative layout to add photos and for even more customization. Remember the id of the textviews that will be populated by simple adapter later on. (EDIT: If you want to use additional text views, image views check boxes or whatever, you need to use a custom adapter!)

list_item.xml

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:padding="10dp"
  android:textSize="16sp"
  android:id="@+id/label">
</TextView>


In the java file, include a String of the items you want to display before the onCreate. Set the list Adapter in onCreate. Set up list item click event handler after onCreate. Right now, it is set up to display a toast message of the list item selected.

PageOne.java

public class StepTherapy extends ListActivity {

String[] items={"lorem", "ipsum", "dolor", "sit", "amet",
"consectetuer", "adipiscing", "elit", "morbi", "vel",
"ligula", "vitae", "arcu", "aliquet", "mollis",
"etiam", "vel", "erat", "placerat", "ante",
"porttitor", "sodales", "pellentesque", "augue",
"purus"};
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.steptherapy);

ListView lv = (ListView)getListView();
        lv.setAdapter(new ArrayAdapter<String>(this, R.layout.list_item, R.id.label, items));
    public void onListItemClick(ListView parent, View v, int position, long id) {
            Toast.makeText(getApplicationContext(), ((TextView) v).getText(), Toast.LENGTH_SHORT).show();
}
}




Monday, October 4, 2010

Easy Tab Layout using separate Activities to fill Tab Content.

This is the working tab layout that I have designed thus far. This project requires three xml layouts, two xml drawables and a three java classes (and two png drawables for tab logos).


The main.xml file should have the following. Elements like buttons or TextViews that are needed to be displayed outside of the tabs or tab window should be placed above or below TabHost. Use the include method to add tab content layout files.


main.xml
<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" 
  android:isScrollContainer="true">

<LinearLayout android:orientation="vertical" 
    android:layout_width="fill_parent" 
     android:layout_height="fill_parent">
<TabWidget android:id="@android:id/tabs" 
  android:layout_width="fill_parent" 
  android:layout_height="wrap_content">
</TabWidget>
<FrameLayout android:id="@android:id/tabcontent" 
  android:layout_width="fill_parent" 
  android:layout_height="fill_parent"><
/FrameLayout>
</LinearLayout>
</TabHost>
I'm only going to include two tabs. You need to have a separate layout.xml file for each tab's content. 


tab1.xml and tab2.xml (they are the same for the sake of this tutorial)




<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/scheduler_dayview" 
  android:layout_height="fill_parent" 
  android:layout_width="fill_parent" 
  android:orientation="vertical">

<TextView android:layout_width="fill_parent" 
  android:text="Tab 1" 
  android:padding="5px" 
  android:id="@+id/TextView01" 
  android:layout_height="wrap_content"
</TextView>

</LinearLayout>
Again, for the sake of this tutorial, the tabs respective activities are the same. 

Tab1.java and Tab2.java




public class Tab1 extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tab1);
        



   }

}

Now for the java class.

TabLayoutExample.Java

public class TabLayoutExample extends TabActivity {

    // Called when the activity is first created. 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        // Tab Stuff
        
Resources res = getResources(); 
        TabHost tabHost = getTabHost();  
        Intent intent;  

        // Create an Intent to launch an Activity for the tab 
        intent = new Intent().setClass(this, Tab1.class);
        // Initialize a TabSpec for each tab and add it to the TabHost
        tabHost.addTab(tabHost.newTabSpec("t1").setIndicator("Tab1",
                          res.getDrawable(R.drawable.tab1))
                      .setContent(intent));

        // Do the same for the other tabs
        intent = new Intent().setClass(this, Tab2.class);
        tabHost.addTab(tabHost.newTabSpec("t2").setIndicator("Tab2",
                          res.getDrawable(R.drawable.tab2))
                      .setContent(intent));

        tabHost.setCurrentTab(0);
    }
}