Android fragments on itemclick (listview) - android

I want to have an activity, where in it's layout I will have a listview with fixed content (array) and on the right side I want dynamic content (so I decided: fragments).
My MainLayout is like this (activity_vizitarea.xml):
<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"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="ro.softwarex.bellaapp.procesarevizita.app.VizitareaActivity">
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true">
<ListView
android:layout_width="20dp"
android:layout_height="wrap_content"
android:id="#id/id_vizita_jobs"
android:layout_weight="1" />
<LinearLayout
android:orientation="vertical"
android:layout_width="400dp"
android:layout_height="fill_parent"
android:id="#id/id_fragment_container"></LinearLayout>
</LinearLayout>
</RelativeLayout>
The last LinearLayout will hold the fragments
My Activity looks like this:
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
public class VizitareaActivity extends Activity {
ListView listView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_vizitarea);
// Get ListView object from xml
listView = (ListView) findViewById(R.id.id_vizita_jobs);
// Defined Array values to show in ListView
String[] values = new String[] { "First category",
"Second category",
"Third category",
"Fourth category",
" and so on",
"Last category"
};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1, values);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
int itemPosition = position;
String itemValue = (String) listView.getItemAtPosition(position);
Toast.makeText(getApplicationContext(),
"Position :" + itemPosition + " ListItem : " + itemValue, Toast.LENGTH_SHORT)
.show();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.vizitarea, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
And a fragment looks like this:
public class FirsCatFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_firstcat_layout, container, false);
}
}
and it's layout is something like this (fragment_firstcat_layout.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ToggleButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New ToggleButton"
android:id="#+id/toggleButton" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New RadioButton"
android:id="#+id/radioButton" />
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New CheckBox"
android:id="#+id/checkBox" />
</LinearLayout>
So my behavior should be: onClick of a category from the listView, a corresponding fragment should be loaded... But I have no idea on how to implement this.
I imagine it to be somewhere in onItemClick, a case or an if statement checking the position of the clicked item, and based on that number, decide which fragment to bring up.
But I do not seem to get how this work. I checked multiple tutorials on the web but I cannot seem to be able to make it work.
The principle of the activity is similar to the Settings page in iOS (only for Android). Like in this image:
I know there is NavigationDrawer but it is not recommended for less than 3 top level elements. I only want 2 levels: master and detail, the category and the details of the category. That is all.
Can you please help me with this?
Thank you

For left side list view you can go for Navigation Drawer and load list view on navigation drawer. and load related fragment on frame layout. Follow this link: http://www.androidhive.info/2013/11/android-sliding-menu-using-navigation-drawer/
check this tutorial: http://android-er.blogspot.in/2013/04/replace-fragment.html
here in main layout having FrameLayout called maincontainer
Inside onitem click of your list view do like this:
MyFragment1 fragment = (MyFragment1)myFragmentManager.findFragmentByTag(TAG_1);
if (fragment == null) {
FragmentTransaction fragmentTransaction = myFragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.maincontainer, myFragment1, TAG_1);
fragmentTransaction.commit();
}else{
fragment.setMsg("MyFragment1 already loaded");
}
}});
Every time maincontainer replacing with new fragments.

Related

Android - OnItemClickListener only *sometimes* not working

I have a ListView in one of my activities that I have bound to an ArrayList using a custom ArrayAdapter. I have set an OnItemClickListener to the ListView which should call a method that starts another activity. However, I find that when I click on the ListView items, it only sometimes works. Sometimes it will start the activity as it should; other times it seems to detect the click (the ripple effect appears on the list item) but does nothing; other times it doesn't even appear to detect the click (the ripple effect doesn't appear).
I've tried all the usual suggestions that I've come across: blocking descendants on the parent view item, setting clickable and focusable to false on all the components of the item views, setting isEnabled to return true in the custom adapter, etc, but the behavior remains the same. Any help appreciated. Here is the relevant code:
Activity containing the ListView:
public class ViewCollectionActivity extends AppCompatActivity {
private final String className = this.getClass().getSimpleName();
private CollectionHandler collectionHandler;
private Context context;
private ArrayList<Game> displayedCollection;
private GameCollectionAdapter collectionAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_collection);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
context = this;
collectionHandler = CollectionHandler.getInstance(this);
TextView view = null;
if (collectionHandler.getDisplayedCollection().size() > 0) {
view = (TextView) findViewById(R.id.no_items_textview);
view.setVisibility(View.GONE);
}
String currentDate = collectionHandler.getDateLastSynchronised();
view = (TextView) findViewById(R.id.last_updated_textview);
view.setText("Last synchronised: " + currentDate + " Total games: " + String.valueOf(collectionHandler.getDisplayedCollection().size()));
collectionAdapter = collectionHandler.getCollectionAdapter();
ListView listView = (ListView) findViewById(R.id.collection_list_view);
listView.setAdapter(collectionAdapter);
AdapterView.OnItemClickListener collectionItemClickListener = new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
launchGameDetailsActivity(position);
}
};
listView.setOnItemClickListener(collectionItemClickListener);
}
public void launchGameDetailsActivity(int position){
Log.d(className,"Starting lauchGameDetailsActivity method");
collectionHandler.setSelectedGame(position);
Intent intent = new Intent(this,ViewGameDetailsActivity.class);
startActivity(intent);
Log.d(className, "Ending lauchGameDetailsActivity method");
}
The XML for the activity:
<?xml version="1.0" encoding="utf-8"?>
<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"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.bleachedlizard.ludome.viewcollection.ViewCollectionActivity">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Synchronise Collection"
android:onClick="synchroniseCollection"/>
<TextView
android:id="#+id/last_updated_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Last synchronised: "
android:textAlignment="center"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Display Collection"
android:visibility="gone"
android:onClick="displayCollection"/>
<ListView
android:id="#+id/collection_list_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</ListView>
<TextView
android:id="#+id/no_items_textview"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="You have no items in your collection."
android:textAlignment="center"
android:textSize="20sp"/>
</LinearLayout>
The XML for the item views:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/collection_item_layout"
android:layout_width="match_parent"
android:layout_height="75dp"
android:orientation="horizontal"
android:clickable="false"
android:descendantFocusability="blocksDescendants"
android:focusable="false"
android:focusableInTouchMode="false">
<ImageView
android:id="#+id/collection_item_image"
android:layout_width="75dp"
android:layout_height="75dp"
android:src="#drawable/testimage"
android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="false"
/>
<TextView
android:id="#+id/collection_item_name"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:padding="16dp"
android:singleLine="false"
android:textColor="#android:color/darker_gray"
android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="false"
android:textIsSelectable="false"/>
<TextView
android:id="#+id/collection_item_plays"
android:layout_width="100dp"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:padding="8dp"
android:textColor="#android:color/darker_gray"
android:text="Plays: 0"
android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="false"
android:textIsSelectable="false"/>
</LinearLayout>
The code for the custom adapter:
public class GameCollectionAdapter extends ArrayAdapter<Game> {
private ArrayList<Game> collection;
public GameCollectionAdapter(Context context, int resource, ArrayList<Game> collection){
super(context, resource, collection);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout gameView = (LinearLayout) convertView;
LayoutInflater mInflater = LayoutInflater.from(getContext());
if (gameView == null) {
gameView = (LinearLayout) mInflater.inflate(R.layout.collection_item_view, null);
}
//Game game = collection.get(position);
Game game = super.getItem(position);
if (game != null) {
// This is how you obtain a reference to the TextViews.
// These TextViews are created in the XML files we defined.
TextView gameTitle = (TextView) gameView.findViewById(R.id.collection_item_name);
TextView numOfPlays = (TextView) gameView.findViewById(R.id.collection_item_plays);
ImageView thumbnail = (ImageView) gameView.findViewById(R.id.collection_item_image);
// check to see if each individual textview is null.
// if not, assign some text!
if (gameTitle != null){
gameTitle.setText(game.getTitle());
}
if (numOfPlays != null){
numOfPlays.setText("Plays: " + String.valueOf(game.getNumOfPlays()));
}
if (thumbnail != null){
thumbnail.setImageBitmap(game.getThumbnail());
}
}
// the view must be returned to our activity
return gameView;
}
#Override
public boolean isEnabled(int position) {
return true;
}
}
I discovered what was causing the problem: the way I had set up the array that backed the ListView meant that it was downloading and storing the Bitmaps for every element in the array all the time. Once I changed the implementation so that it only downloaded the images as the ListView required them, then that seemed to improve performance and the onClickListener started to work fine.
The implementation I used was the exact same one shown here:
http://developer.android.com/training/displaying-bitmaps/process-bitmap.html
I think the issue is due to the position of the item selection whenever you click you have an list position which is passed to your method launchGameDetailActivity(int position) check with log or toast on item click what all the position you are getting do the needful.
Here is my code try this like this if it helps.
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(RecipeClass.this, "Position is" + position, Toast.LENGTH_SHORT).show();
Intent intent = new Intent(RecipeClass.this, RecipeIngredients.class)
intent.putExtra("position", position);
startActivity(intent);
}
Check your arraylist value also whether they are not null.

Android App: MainActivity Can't Find ListView/Crashes on Landscape->Portrait Mode

I'm having two issues with my Android application. I'll start with the relevant code, which I'm 99% certain is locked within my MainActivity class:
package com.simplerssreader;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
public class MainActivity extends FragmentActivity {
private ListView list;
private TextFragment text;
private RssFragment rss;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
// Initializing AddNote fragment
if (getFragmentManager().findFragmentByTag("RSS") == null)
{
rss = new RssFragment();
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, rss, "RSS").commit();
}
}
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)
{
if (getFragmentManager().findFragmentByTag("RSS") == null)
{
rss = new RssFragment();
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, rss, "RSS").commit();
}
if (getFragmentManager().findFragmentByTag("TEXT") == null)
{
text = new TextFragment();
getSupportFragmentManager().beginTransaction()
.add(R.id.text, text, "TEXT").commit();
}
}
//View view = getLayoutInflater().inflate(R.layout.fragment_layout, null);
list = (ListView) this.findViewById(R.id.listView);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id)
{
System.out.println("YES!");
/*RssAdapter adapter = (RssAdapter) parent.getAdapter();
RssItem item = (RssItem) adapter.getItem(position);
TextFragment fragment = new TextFragment();
fragment.setLink(item.getLink());
FragmentManager fragMgr = getSupportFragmentManager();
FragmentTransaction xact = fragMgr.beginTransaction();
xact.replace(R.id.text, fragment, "TEXT");*/
}
});
if (savedInstanceState != null) {
text = (TextFragment) getSupportFragmentManager().findFragmentByTag("TEXT");
rss = (RssFragment) getSupportFragmentManager().findFragmentByTag("RSS");
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("fragment_added", true);
}
}
(Note that I'm not concerned with the code within the onItemSelected at the moment; I'll deal with that later, when I actually have working code.)
So my first problem is with this line:
list = (ListView) this.findViewById(R.id.listView);
What I'm hoping to attain here is the ListView found in the current display (in portrait or landscape mode, the list view will be displayed). I also attempted another method in the commented out line above that, but it also failed. The error here is a NullPointerException.
My second issue is that whenever I go to portrait mode from landscape mode, the application crashes. I can go from portrait to landscape, and boot in either mode, but going back to portrait kills the application. I've made the proper checks for orientation in onCreate so I'm not sure of where I'm going wrong. The error here states that there's no TextView to find in the current view- but that should only be called when I'm in landscape mode, right?
Anyways, any help would be greatly appreciated!
Here are my layouts:
fragment_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="#+id/listView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</ListView>
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
</RelativeLayout>
main.xml (portrait)
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:id="#+id/fragment_container"
android:layout_height="fill_parent"
/>
text_view.xml
<?xml version="1.0" encoding="utf-8"?>
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/text"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
main.xml (landscape)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent" android:layout_height="match_parent"
android:baselineAligned="false">
<FrameLayout android:id="#+id/fragment_container" android:layout_weight="1"
android:layout_width="0px" android:layout_height="match_parent"
android:background="?android:attr/detailsElementBackground" />
<FrameLayout android:id="#+id/text" android:layout_weight="2"
android:layout_width="0px" android:layout_height="match_parent"
android:background="?android:attr/detailsElementBackground" />
</LinearLayout>
First, try moving the code where you get the list view to the fragment.
Also, in
if (savedInstanceState != null) {
text = (TextFragment) getSupportFragmentManager().findFragmentByTag("TEXT");
rss = (RssFragment) getSupportFragmentManager().findFragmentByTag("RSS");
}
you overwrite the text even if there was no TEXT fragment before, in case there's a savedInstance
Finally, you have duplicate ids:
<FrameLayout android:id="#+id/text" android:layout_weight="2"
android:layout_width="0px" android:layout_height="match_parent"
android:background="?android:attr/detailsElementBackground" />
and
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/text"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
Firstly, I don't see your ListView set to an Adapter in your activity. Here is just a simple example, where customtextview is a simple TextView and items a string array:
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.customtextview, items);
listView.setAdapter(adapter);
Then, you have two id with "text" (R.layout.text_view and FrameLayout in R.layout.main landscape). If you use both in one of your Fragment, this will crash. Change one of them..
And, because you have the FrameLayout "text" only in landscape mode, you can do your onCreate method as below (check if this FrameLayout is present or not):
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// in both layout, you add this Fragment in the same FrameLayout
// check the savedInstanceState, if isn't null = orientation has changed
if (savedInstanceState == null)
rss = new RssFragment();
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, rss, "RSS").commit();
} else {
rss = (RssFragment) getSupportFragmentManager().findFragmentByTag("RSS");
}
/*
** check if FrameLayout text is null (true = landscape)
*/
if(findViewById(R.id.text) != null) {
// check the savedInstanceState
if (savedInstanceState == null) {
text = new TextFragment();
getSupportFragmentManager().beginTransaction()
.add(R.id.text, text, "TEXT").commit();
} else {
text = (TextFragment) getSupportFragmentManager().findFragmentByTag("TEXT");
}
}
/*
** else the id isn't exist (false = portrait) // do nothing
*/
}
Then, in your RSS Fragment, set your ListView:
private ListView list;
String[] items = new String[] {
"One",
"Two",
"Three",
"And so on.."
};
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_layout, container, false);
list = (ListView) v.findViewById(R.id.listView);
ArrayAdapter<String> adapt = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, items);
list.setAdapter(adapt);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
System.out.println("YES!");
/* some stuff */
}
});
return v;
}
To save a fragment state on a activity, you can use setRetainInstance(true). There is a great post on it, and a tutorial. For more information about what happens with fragment and orientation changed, you can read this answer.
Let me know if this is helpful.
I searched a bit on the web, and I found these tutorials which might help you a lot:
great: Create Android Dynamic view with Fragments
great: User Interface Design: Working With Fragments
not bad: Fragment example tutorial using WebView
All works with WebView and they mostly use findFragmentById and not tag. Maybe it's the clue..
But you can add directly on the xml the appropriate fragments, as:
- Portrait Mode :
o layout 1 : listview (ex fragment RSS)
o layout 2 : fragment WebView
- Landscape Mode :
o layout 1 :
LinearLayout (id container) : listview (ex fragment RSS) + framelayout
And on your FragmentActivity, you host your list and check the orientation, like the following:
ListView list = (ListView) findViewById(...);
list.setAdapter(...);
LinearLayout container = (LinearLayout) findViewById(R.id.container);
if(container != null) {
// your framelayout is present so set your fragment WebView
// inside it with a fragment transaction and also
// use the item clicked to send info to this fragment
} else {
// call a new activity on item clicked to display the WebView
}
This should work..
I hope these added informations will help you to achieve that.

Android displaying text when ListView is empty

I'm setting a TextView with the id #android:id/empty to display a message when there are no items in the ListView. However, this TextView gets displayed even if there are items in the ListView, right before the items show up.
How can I make it such that it only gets displayed when there are no elements in the ListView?
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#android:id/list"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:dividerHeight="1dp" >
</ListView>
<TextView
android:id="#android:id/empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/empty_list" />
</LinearLayout>
PS: I'm using a Loader and a SimpleCursorAdapter with a ListFragment.
I'm guessing you are using a regular Fragment or Activity with a ListView inside of it. If you are, you must add the empty layout to the ListView manually.
E.g.
ListView lv = (ListView)findViewById(android.R.id.list);
TextView emptyText = (TextView)findViewById(android.R.id.empty);
lv.setEmptyView(emptyText);
Then your ListView will automatically use this view when its adapter is empty
If you are using a ListActivity you do not need to call setEmptyView() on the ListView since the ListActivity automatically manages that for you.
Set a TextView and assign to it whatever you want to display when the ListView is empty:
ProjectListAdapter projectListAdapter = new ProjectListAdapter();
TextView empty=(TextView)findViewById(R.id.empty);
projectsListView.setEmptyView(empty);
And in my xml file we write the below code
<TextView
android:id="#+id/empty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="Your text here"
android:textColor="#FFFFFF" />
I had this problem. You have to set the emptyView explicitly in your code.
Change your TextView:
<TextView
android:id="#+id/emptyResults"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/empty_list" />
Then in the onCreate():
listViewResults = (ListView) findViewById(R.id.list);
listViewResults.setEmptyView((LinearLayout) findViewById(R.id.emptyResults));
This code above assumes your ListView is in a LinearLayout.
I used ListFragment and had the same issue. I tried all variants from this answers, but the problem wasn't solved.
So I found my variant, to override setEmptyText():
public class NewsFragment extends ListFragment{
private TextView emptyText;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//...
emptyText = (TextView)view.findViewById(android.R.id.empty);
//...
}
#Override
public void setEmptyText(CharSequence text) {
emptyText.setText(text);
}
}
Hope it will be helpful for somebody.
I know this is kind of late, but for it to work from XML, you need to put a weight on your ListView and have your TextView match_parent
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#android:id/list"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:dividerHeight="1dp" >
</ListView>
<TextView
android:id="#android:id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="#string/empty_list" />
</LinearLayout>
There's a good example of how to do it which works awesome:
When you want to show a message to the user when the ListView is
empty, you have to keep in mind the following 3 steps:
In the xml where the ListView is declared, create a TextView (the TextView can be inside a LinearLayout if you want) right
below the ListView
Set the TextView’s id as “emptyElement”
And inside the activity, set the setEmptyView() property to the ListView
1- Create an xml which will hold the ListView and name it
“my_activity”
and an activity called “MyActivity”.
Now, in the just created xml “my_activity”, you will have to set the ListView. And right below the ListView, you will have to add
a TextView. This will be used to display the empty message.
Important: The TextView must have as id the following name: “emptyElement”. This name is mandatory. The message won’t be displayed
if you use another name.
This is how “my_activity” xml should look like:
<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"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".MyActivity">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/listView"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/emptyElement"
android:text="The list is empty"
android:textStyle="bold"
android:textSize="15sp"
android:visibility="gone"
android:layout_centerInParent="true"
android:textColor="#android:color/darker_gray"/>
</RelativeLayout>
Create an xml for displaying items (when the list is not empty), and name it “list_item”.
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/list_item_text_view"
android:textSize="20sp"
android:padding="10dp"
android:layout_marginLeft="5dp"/>
Create a new Java class for the custom adapter which will be used by the ListView and name “MyCustomAdapter”. The code for the adapter
is written below:
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.ArrayList;
public class MyCustomAdapter extends BaseAdapter {
private ArrayList<String> mListItems;
private LayoutInflater mLayoutInflater;
public MyCustomAdapter(Context context, ArrayList<String> arrayList){
mListItems = arrayList;
//get the layout inflater
mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
//getCount() represents how many items are in the list
return mListItems.size();
}
#Override
//get the data of an item from a specific position
//i represents the position of the item in the list
public Object getItem(int i) {
return null;
}
#Override
//get the position id of the item from the list
public long getItemId(int i) {
return 0;
}
#Override
public View getView(int position, View view, ViewGroup viewGroup) {
// create a ViewHolder reference
ViewHolder holder;
//check to see if the reused view is null or not, if is not null then reuse it
if (view == null) {
holder = new ViewHolder();
view = mLayoutInflater.inflate(R.layout.list_item, null);
holder.itemName = (TextView) view.findViewById(R.id.list_item_text_view);
// the setTag is used to store the data within this view
view.setTag(holder);
} else {
// the getTag returns the viewHolder object set as a tag to the view
holder = (ViewHolder)view.getTag();
}
//get the string item from the position "position" from array list to put it on the TextView
String stringItem = mListItems.get(position);
if (stringItem != null) {
if (holder.itemName != null) {
//set the item name on the TextView
holder.itemName.setText(stringItem);
}
}
//this method must return the view corresponding to the data at the specified position.
return view;
}
/**
* Static class used to avoid the calling of "findViewById" every time the getView() method is called,
* because this can impact to your application performance when your list is too big. The class is static so it
* cache all the things inside once it's created.
*/
private static class ViewHolder {
protected TextView itemName;
}
}
Now go to MyActivity class and add the code below:
import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.List;
public class MyActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
ListView listView = (ListView) findViewById(R.id.listView);
// Create an empty array list of strings
List<String> items = new ArrayList<String>();
// Set the adapter
MyCustomAdapter adapter = new MyCustomAdapter(items);
listView.setAdapter(adapter);
// Set the emptyView to the ListView
listView.setEmptyView(findViewById(R.id.emptyElement));
}
}
TextView tv=(TextView) view.findViewById(R.id.empty);
tv.setVisibiliy(View.GONE);

Not able to add Title bar for Listview

The requirement for my screen is like having a title bar at the top middle and followed by the list view when am trying to do that am not able to do like i got state name in every list item.I want that only in the top and once. And the screen shot of it is
<?xml version="1.0" encoding="utf-8"?>
<TableLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TableRow>
<TextView
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:background="#000000"
android:text="Select State"
></TextView>
</TableRow>
<TableRow>
<TextView android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:id="#+id/label"
android:textSize="30px"></TextView>
</TableRow>
</TableLayout>
I have tried many ways this is my present layout
and my java code is
import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
public class new21 extends ListActivity {
/** Called when the activity is first created. */
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// Create an array of Strings, that will be put to our ListActivity
String[] names = new String[] { "Andhra Pradesh", "Kerala","Tamilnadu","Karnataka" };
// Use your own layout and point the adapter to the UI elements which
// contains the label
this.setListAdapter(new ArrayAdapter<String>(this, R.layout.new21,
R.id.label, names));
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
// Get the item that was clicked
Object o = this.getListAdapter().getItem(position);
String keyword = o.toString();
if(keyword.equals("Andhra Pradesh"))
{
Intent ima45=new Intent(new21.this,new31.class);
startActivity(ima45);
}
Toast.makeText(this, "You selected: " + keyword, Toast.LENGTH_LONG)
.show();
}
}
Can any one help me.
You can addHeader to the ListView like this,
View header = getLayoutInflater().inflate(R.layout.header, null);
ListView listView = getListView();
listView.addHeaderView(header);
setListAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_single_choice, names));
Where R.layout.header is the layout that contains a TextView with text "Select State"
UPDATED:
public class ListViewProblemActivity extends ListActivity {
ListView listView;
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// Create an array of Strings, that will be put to our ListActivity
String[] names = new String[] { "Andhra Pradesh", "Kerala","Tamilnadu","Karnataka" };
// Use your own layout and point the adapter to the UI elements which
// contains the label
TextView tv = new TextView(getApplicationContext());
tv.setText("Select State");
listView = getListView();
listView.addHeaderView(tv);
this.setListAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_expandable_list_item_1,names));
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
// Get the item that was clicked
if(position != 0){
System.out.println(position - 1);
Object o = this.getListAdapter().getItem(position - 1);
String keyword = o.toString();
Toast.makeText(this, "You selected: " + keyword, Toast.LENGTH_LONG)
.show();
}
}
}
Usey only a ListView in your activity, remove the heading there. Then use ListView.addHeaderViwe(); to add a header to the Listview. This Header is display before the first item.
See the documentaton for further information.
you better use ListView.addHeaderViwe();
but don't forget to remove what u did "extends ListActivity", no need for that,
and also remove title from your "new21.xml"
in your xml, just fix the text item u want to show in every row of the list,
You are doing fully wrong. Just take a LinearLayout with one TextView (for Title bar) and ListView (To display listview), nothing more than these 2 views.
<?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:layout_height="wrap_content"
android:layout_width="fill_parent"
android:background="#000000"
android:text="Select State">
</TextView>
<ListView
android:id="#+id/lviewState"
android:layout_height="wrap_content"
android:layout_width="match_parent">
</ListView>
</LinearLayout>
Now, follow your code to display ListView.

How do I set a new xml layout while using tabs

I am trying to create a tabbed interface which has multiple activities. As part of the tabs I have created and set an xml tabhost file like so:
<?xml version="1.0" encoding="utf-8"?>
<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">
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TabWidget
android:id="#android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="5dp" />
</LinearLayout>
</TabHost>
This is called in my Tabs.class file which looks like this:
package com.system.kenetix;
import android.app.TabActivity;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.widget.TabHost;
public class Tabs extends TabActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tabs);
Resources res = getResources(); // Resource object to get Drawables
TabHost tabHost = getTabHost(); // The activity TabHost
TabHost.TabSpec spec; // Resusable TabSpec for each tab
Intent intent; // Reusable Intent for each tab
// Create an Intent to launch an Activity for the tab (to be reused)
intent = new Intent().setClass(this, Availability.class);
// Initialize a TabSpec for each tab and add it to the TabHost
spec = tabHost.newTabSpec("Availability").setIndicator("Booking",
res.getDrawable(R.drawable.kenetix_tab_available))
.setContent(intent);
tabHost.addTab(spec);
// Do the same for the other tabs
// Create an Intent to launch an Activity for the tab (to be reused)
intent = new Intent().setClass(this, RoomsAvailable.class);
spec = tabHost.newTabSpec("Room").setIndicator("Rooms",
res.getDrawable(R.drawable.kinetix_tab_rooms))
.setContent(intent);
tabHost.addTab(spec);
// Do the same for the other tabs
// Create an Intent to launch an Activity for the tab (to be reused)
intent = new Intent().setClass(this, CustomerDetails.class);
spec = tabHost.newTabSpec("Customer").setIndicator("Customer",
res.getDrawable(R.drawable.kinetix_tab_customer))
.setContent(intent);
tabHost.addTab(spec);
intent = new Intent().setClass(this, Payment.class);
spec = tabHost.newTabSpec("Payment").setIndicator("Payment",
res.getDrawable(R.drawable.kinetix_tab_payment))
.setContent(intent);
tabHost.addTab(spec);
intent = new Intent().setClass(this, Extras.class);
spec = tabHost.newTabSpec("Extras").setIndicator("Extras",
res.getDrawable(R.drawable.kinetix_tab_extras))
.setContent(intent);
tabHost.addTab(spec);
tabHost.setCurrentTab(0);
}
}
I then have individual classes for each of my tabs and an xml file to set the content (Buttons, spinners etc) like so:
package com.system.kenetix;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.Toast;
public class Availability extends Activity {
/** Called when the activity is first created. */
Intent intent = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.availability);
/*Nights Spinner*/
//Create an instance of the Number of Nights spinner
Spinner NumNightsSpinner = (Spinner) findViewById(R.id.NumAdultsSpinner);
//Create an ArrayAdapter for the Number of Nights spinner
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.NumNights_array, android.R.layout.simple_spinner_item);
//Set the adapter layout
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
//Apply the adapter layout to the Number of Nights spinner
NumNightsSpinner.setAdapter(adapter);
NumNightsSpinner.setOnItemSelectedListener(new MyOnNumNightsSelectedListener());
/*Adults Spinner*/
//Create an instance of the Number of Adults spinner
Spinner NumAdultsSpinner = (Spinner) findViewById(R.id.NumAdultsSpinner);
//Create an ArrayAdapter for the Number of adults spinner
ArrayAdapter<CharSequence> adapter1 = ArrayAdapter.createFromResource(this, R.array.NumAdults_array, android.R.layout.simple_spinner_item);
//Set the adapter layout
adapter1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
//Apply the adapter layout to the Number of Adults spinner
NumAdultsSpinner.setAdapter(adapter);
NumAdultsSpinner.setOnItemSelectedListener(new MyOnNumAdultsSelectedListener());
/*Children Spinner*/
//Create an instance of the Number of Children spinner
Spinner NumChildSpinner = (Spinner) findViewById(R.id.NumChildSpinner);
//Create an ArrayAdapter for the Number of Children spinner
ArrayAdapter<CharSequence> adapter2 = ArrayAdapter.createFromResource(this, R.array.NumChild_array, android.R.layout.simple_spinner_item);
//Set the adapter layout
adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
//Apply the adapter layout to the Number of Children spinner
NumChildSpinner.setAdapter(adapter);
NumChildSpinner.setOnItemSelectedListener(new MyOnNumChildSelectedListener());
Button CheckAvailable = (Button) findViewById(R.id.CheckAvailabilityBtn);
CheckAvailable.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
intent = new Intent(v.getContext(), RoomsAvailable.class);
startActivity(intent);
}
});
}
//Listener for the selected item from the number of nights spinner
public class MyOnNumNightsSelectedListener implements OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent,View view, int pos, long id){
//If no number of nights has been selected or onCreate occurs cancel the toast
if (parent.getItemAtPosition(pos).toString().equals("0")){
Toast.makeText(parent.getContext(), "You selected " + parent.getItemAtPosition(pos).toString() + " night(s)", Toast.LENGTH_LONG).cancel();
}
//Else create a toast stating the number of nights selected
else{
Toast.makeText(parent.getContext(), "You selected " + parent.getItemAtPosition(pos).toString() + " night(s)", Toast.LENGTH_LONG).show();
}
}
public void onNothingSelected(AdapterView<?> parent) {
// TODO Auto-generated method stub
}
}
//Listener for the selected item from the number of adults spinner
public class MyOnNumAdultsSelectedListener implements OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent,View view, int pos, long id){
//If no number of nights has been selected or onCreate occurs cancel the toast
if (parent.getItemAtPosition(pos).toString().equals("0")){
Toast.makeText(parent.getContext(), "You selected " + parent.getItemAtPosition(pos).toString() + " adults", Toast.LENGTH_LONG).cancel();
}
else if (parent.getItemAtPosition(pos).toString().equals("1")){
Toast.makeText(parent.getContext(), "You selected " + parent.getItemAtPosition(pos).toString() + " adult", Toast.LENGTH_LONG).cancel();
}
//Else create a toast stating the number of nights selected
else{
Toast.makeText(parent.getContext(), "You selected " + parent.getItemAtPosition(pos).toString() + " adult(s)", Toast.LENGTH_LONG).show();
}
}
public void onNothingSelected(AdapterView<?> parent) {
// TODO Auto-generated method stub
//Do Nothing
}
}
//Listener for the selected item from the number of adults spinner
public class MyOnNumChildSelectedListener implements OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent,View view, int pos, long id){
//If no number of nights has been selected or onCreate occurs cancel the toast
if (parent.getItemAtPosition(pos).toString().equals("0")){
Toast.makeText(parent.getContext(), "You selected " + parent.getItemAtPosition(pos).toString() + " children", Toast.LENGTH_LONG).cancel();
}
else if (parent.getItemAtPosition(pos).toString().equals("1")){
Toast.makeText(parent.getContext(), "You selected " + parent.getItemAtPosition(pos).toString() + " child", Toast.LENGTH_LONG).show();
}
//Else create a toast stating the number of nights selected
else{
Toast.makeText(parent.getContext(), "You selected " + parent.getItemAtPosition(pos).toString() + " children", Toast.LENGTH_LONG).show();
}
}
public void onNothingSelected(AdapterView<?> parent) {
// TODO Auto-generated method stub
//Do Nothing
}
}
}
and the xml that goes with this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/linearLayout1" android:background="#color/custom_theme_color"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:baselineAligned="false" android:orientation="vertical">
<TableLayout android:layout_width="wrap_content"
android:layout_alignParentLeft="true" android:layout_height="wrap_content"
android:id="#+id/tableLayout1" android:stretchColumns="1"
android:layout_weight="1">
<TableRow android:id="#+id/tableRow1" android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageButton android:src="#drawable/icon"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:id="#+id/QuickRoomSelect" android:layout_weight="1" />
<ImageButton android:src="#drawable/icon"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:id="#+id/QuickCustomerDetails" android:layout_weight="1" />
<ImageButton android:src="#drawable/icon"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:id="#+id/imageButton1" android:layout_weight="1" />
</TableRow>
</TableLayout>
<TextView android:layout_width="match_parent"
android:textColor="#color/custom_theme_text_color" android:id="#+id/availabilityLbl"
android:text="#string/AvailableLbl" android:layout_height="wrap_content"
android:layout_weight="1" />
<Button android:layout_height="wrap_content" android:id="#+id/DateFromBtn"
android:layout_width="match_parent" android:text="#string/DateFromBtn"
android:layout_weight="1" />
<TextView android:textColor="#color/custom_theme_text_color"
android:layout_height="wrap_content" android:id="#+id/NumNightsLdl"
android:text="#string/NumNightsLbl" android:layout_width="wrap_content"
android:layout_weight="1"></TextView>
<Spinner android:layout_height="wrap_content" android:id="#+id/NumAdultsSpinner"
android:layout_width="wrap_content" android:layout_weight="1"></Spinner>
<TableLayout android:layout_height="wrap_content"
android:id="#+id/tableLayout2" android:layout_width="match_parent"
android:layout_weight="1">
<TableRow android:id="#+id/tableRow3" android:layout_height="wrap_content"
android:layout_width="match_parent" android:layout_weight="1">
<TextView android:textColor="#color/custom_theme_text_color"
android:layout_height="wrap_content" android:id="#+id/NumAdultsLbl"
android:text="#string/NumAdultsLbl" android:layout_weight="2"></TextView>
<TextView android:textColor="#color/custom_theme_text_color"
android:layout_height="wrap_content" android:id="#+id/NumChildLbl"
android:layout_weight="2" android:text="#string/NumChildLbl"></TextView>
</TableRow>
<TableRow android:id="#+id/tableRow2" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_weight="1">
<Spinner android:layout_height="wrap_content" android:id="#+id/NumNightsSpinner"
android:layout_width="wrap_content" android:layout_weight="1"></Spinner>
<Spinner android:layout_height="wrap_content" android:id="#+id/NumChildSpinner"
android:layout_width="wrap_content" android:layout_weight="1"></Spinner>
</TableRow>
</TableLayout>
<Button android:layout_width="match_parent" android:id="#+id/CheckAvailabilityBtn"
android:layout_height="wrap_content" android:text="#string/CheckAvailableBtn"
android:layout_weight="1" />
</LinearLayout>
Basically what I need to know is how do I get the Availability.class file to use the second xml file? All that I can see is the tabs which looks great! I don't want to have to create the buttons etc. in the main code as I'm trying to be as OO as possible. All of the examples I have seen either use the tabs.xml to layout the activity which is great if you want every tab to have the same information, or the layout stuff is written straight into the java class.
Is it possible to do what I want? If so can someone advise me in how to do this or link me to somewhere?
What you want is basically exactly how my application is organized (with a second version I am fiddling around with that is View-based instead).
There seems to be a bit of an issue with your Tabs XML file though.
1) Why do you have the xmlns:android tag twice? TabHost and LinearLayout both have it - remove the one from the LinearLayout.
2) Not sure about the match_parent layout params on the LinearLayout (this is likely not the issue though) - my first TabHost (later revised a bit) looked like this, which is very similar to yours (I imagine we followed the same tutorial off the Android docs ;)), and worked just fine:
<TabHost android:id="#android:id/tabhost" android:layout_width="fill_parent" android:layout_height="fill_parent">
<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"/>
<FrameLayout android:id="#android:id/tabcontent" android:layout_width="fill_parent" android:layout_height="fill_parent"/>
</LinearLayout>
</TabHost>
Try to fix the first thing and it should work just fine, I see no reason it shouldn't.

Categories

Resources