i created a demo app to display the list of products on screen. the product list comes from remote server. in the logs i can see the data coming and being stored in the arralist but somehow it is not binding with list view. i am making the http call in the background using async class.
below is the activity on create code
ListAdapter adapter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dbtest2_all_products);
Log.i("Entrey level=","entere dbtest2allproducts class");
// Hashmap for ListView
productsList = new ArrayList<HashMap<String, String>>();
// Loading products in Background Thread
new LoadAllProducts().execute();
// Get listview
ListView lv = new ListView(DBtest2AllProducts.this);
// updating listview
lv.setAdapter(adapter);
below is postexecute method of
protected void onPostExecute(String file_url) {
// dismiss the dialog after getting all products
pDialog.dismiss();
// ((BaseAdapter) adapter).notifyDataSetChanged();
Log.i("before adapter",productsList.toString());
adapter = new SimpleAdapter(
DBtest2AllProducts.this, productsList,
R.layout.activity_dbtest2_list_items, new String[] { TAG_PID,
TAG_NAME},
new int[] { R.id.pid, R.id.name });
//setAdapter(adapter);
though i believe as there is some sync issue with the setAdapter(adapter) step but i since i am new to android so couldn't bet on it. i tried calling setAdapter(adapter) method and adapter.notifyDataSetChanged() withing the postexecute method but both of them throw error saying "method is not defined for this type" However if i cast adapter to (BaseAdapter) then adapter.notifyDataSetChanged() doesn't throw any error but i actully dont know what difference does this casting make and also casting didn't work as well.
Below is log cat
I/before adapter(32729): [{pid=1, name=iphone 4s}, {pid=2, name=samsung}]
Please suggest if you see any issues with the code. Thanks for helping in advance.
below are the xml layouts
all_product.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
list_item.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/pid"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone" />
<!-- Name Label -->
<TextView
android:id="#+id/name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:paddingTop="20dip"
android:paddingLeft="10dip"
android:textSize="17sp"
android:textStyle="bold" />
</RelativeLayout>
You need to initialize you adapter before setting it to the ListView. Make ListView global and set the adapter only after getting the data
ListView lv;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dbtest2_all_products);
Log.i("Entrey level=","entere dbtest2allproducts class");
// Hashmap for ListView
productsList = new ArrayList<HashMap<String, String>>();
// Loading products in Background Thread
new LoadAllProducts().execute();
// Get list view from xml file
lv = findViewById(R.id.listview);
FrameLayout rootView = (FrameLayout) findViewById(android.R.id.content);
//Add this line to make sure your list is using the whole screen width
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
rootView.addView(lv);
}
protected void onPostExecute(String file_url) {
// dismiss the dialog after getting all products
pDialog.dismiss();
adapter = new SimpleAdapter(
DBtest2AllProducts.this, productsList,
R.layout.activity_dbtest2_list_items, new String[] { TAG_PID,
TAG_NAME},
new int[] { R.id.pid, R.id.name });
lv.setAdapter(adapter);
}
#Pawan Rawat, after implementing the above answer, and if your confident in carrying on, switch to Volley, a networking library which is more robust, performance network calls faster with less code.
Please read more at http://www.androidhive.info/2014/05/android-working-with-volley-library-1/
Related
i am writing a code to show a multiple selection list (one having check boxes) and when the user checks an item i want to retrieve user's name and id from database table and display it in toast. Here's the code:
Activity code
public class Add_To_Circle extends Activity {
ListView lv;
ListAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.add_to_circle);
// Get listview
lv = (ListView)findViewById(R.id.list);
lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
}
... //all the other code,and then in another class in postexecute there is adapter:
protected void onPostExecute(String file_url) {
// dismiss the dialog after getting all products
//pDialog.dismiss();
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
/**
* Updating parsed JSON data into ListView
* */
adapter = new SimpleAdapter(
Add_To_Circle.this, productsList,
android.R.layout.simple_list_item_multiple_choice, new String[] { TAG_PID,
TAG_NAME},
new int[] { R.id.pid, R.id.name });
// updating listview
lv.setAdapter(adapter);
}
});
}
}
Code of XML file
<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">
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</RelativeLayout>
the output: a blank listview with only checkboxes as in the attched image. What am i doing wrong? i have followed same steps as in tutorials on web still no luck :((
you can use custom adapter that has one textview and checkbox.Here are the links,
http://www.javacodegeeks.com/2013/09/android-listview-with-adapter-example.html
http://androidcocktail.blogspot.in/2012/04/adding-checkboxes-to-custom-listview-in.html
and if you want to use simple array adapter,
refer this link,
Selecting multiple items in ListView
Thanks
Ok, will try and give an answer but I have had to change the Adapter for the answer, so that part is untested.
Lets go bottom up, this is the XML layout for each single element in the list:
view_adapter_item_checklist.xml
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/item"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:gravity="center_vertical"
android:paddingLeft="6dip"
android:paddingRight="6dip"
android:textAppearance="?android:attr/textAppearanceLarge" />
Using CheckedTextView removes the need to handle the checkbox checked/unchecked handling ourselves.
Now the ListView, in my code it is placed inside a LinearLayout, hence the 0dp height. The important part is choiceMode:
<ListView
android:id="#id/android:list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:choiceMode="multipleChoice"
android:drawSelectorOnTop="false" />
The adapter is really rather simple. It takes a list of Strings and inflate list rows based on the checktext XML above. The only task is to set the text of the view, actually:
SimpleChecklistAdapter:
public class SimpleChecklistAdapter extends ArrayAdapter<String> {
private final Context context;
private final List<String> values;
public SimpleChecklistAdapter(Context context, List<String> values) {
super(context, R.layout.view_adapter_item_checklist, values);
this.context = context;
this.values = values;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.view_adapter_item_checklist,
parent, false);
CheckedTextView text = (CheckedTextView)rowView.findViewById(R.id.item);
text.setText(values.get(position));
return rowView;
}
}
All there is left is to use the new fancy checklist adapter instead of SimpleAdapter in your code
I am downloading some data from the internet in an Asynctask class.So for that i am using doInBackground function. After this function is executed i am returning the value to onpostexecute method.
In this onpostexecute method
i need to make dynamic textviews.
P.S: I am getting all the data in my for loop, i am not getting any errors, i just cannot form the dynamic textviews.
This is my code:
protected void onPostExecute(String file_url) {
//Links.setText(file_url);
int iterator=0;
Elements linksText = doc.select("#chapters .tips");
for (Element link : linksText) {
link_link = link.attr("href");
narutoLinks[iterator]=link_link;//from latestlinks
System.out.println("narutoLinks[iterator]= "+iterator+" "+link_link);
link_Text = link.text();
narutoLinkHeadingName[iterator]=link_Text;
System.out.println("narutoText[iterator]= "+iterator+" "+narutoLinkHeadingName[iterator]);
iterator++;
}
System.out.println("iterator= "+iterator);
TextView[] textViewArray = new TextView[iterator];
for( int i = 0; i < iterator; i++) {
textViewArray[i] = new TextView(narutoLinksOnly.this);
textViewArray[i].setText(narutoLinkHeadingName[i]);
textViewArray[i].setId(i);
textViewArray[i].setTextColor(0xff000000);
textViewArray[i].setTextSize(20);
textViewArray[i].setOnClickListener(this);
textViewArray[i].setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
((LinearLayout) linearLayout).addView(textViewArray[i]);
}
System.out.println("senkai");
if(connectionTimeout==true)
{showToast("Connection Timeout");
connectionTimeout=false;
}
// dismiss the dialog after the file was downloaded
dismissDialog(progress_bar_type);
// Displaying downloaded image into image view
// Reading image path from sdcard
}
and this is my xml file
<?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:background="#color/Ivory"
android:id="#+id/dynamicTextview1"
android:orientation="vertical" >
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:id="#+id/tvNarutoLinksOnly"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello"
android:textColor="#color/black" />
</ScrollView>
</LinearLayout
This is how my oncreate method looks like:
View linearLayout;//declaring it inside the class itself
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.narutolinksonly);
linearLayout = findViewById(R.id.dynamicTextview1);
initialize();
new DownloadLinksFromURL().execute(url);
System.out.println("inside on create");
}
Am i missing something in my code?
Also what is the best way to achieve dynamic textview after getting data from an Asynctask class?
Kindly help.
use a listview instead.
And set an array adapter to it with the list of string that you get from the server.
But in your case try:
textViewArray[i].setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
you have to setup a listview adapter. You have the data, but nothing on your onCreateView ties that data to a listView.
Here's an example from the Android site on an adapter using cursors
String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME};
int[] toViews = {android.R.id.text1}; // The TextView in simple_list_item_1
// Create an empty adapter we will use to display the loaded data.
// We pass null for the cursor, then update it in onLoadFinished()
mAdapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_1, null,
fromColumns, toViews, 0);
setListAdapter(mAdapter);
Trade their cursor data in for your textViewArray data and make it a BaseAdapter or similar and you're done
I have an activity that uses setContentView to initiate a listview, and then I have an If-Else condition. In the If part of the statement I use a simpleAdapter to place a new layout in the listview and other data from a cursor. In the Else part, I just want to put a sentence in a label to provide some information. How can I do that? I tried parameters and textview but they didn't work. I tried to put another setcontentView but it can't work either.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_listview);
doMySearch() is a cursor that extracts data from database based on a keyword input by user.
public void onPostExecute() {
SimpleCursorAdapter adapter;
Int count = doMysearch().getCount;
If (count >= 1){
adapter=new SimpleCursorAdapter(this, R.layout.activity_results,
doMySearch(), new String[] {
DB.COL_NAME,
DB.COL_CITY },
new int[] { R.id.lblName, R.id.lblCity },
0);
setListAdapter(adapter);
}
Else {
}
I just want a sentence that says "No data found" for the Else part. Thanks.
It is not clear for me what you are asking but here we go.
There is empty view setting in ListView for empty lists, you have to add another empty view in your current layout. Then you will set the empty view layout in code like below:
//add to your layout
<LinearLayout
android:id="#+id/empty"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="There is no item" >
</TextView>
</LinearLayout>
//set empty view
ListView listView = (ListView) container.findViewById(R.id.list);
LinearLayout emptyView = (LinearLayout) container.findViewById(R.id.empty);
listView.setEmptyView(emptyView);
As far as I understand the label doesn't show up because of the listview, right?`
EDIT:
Okay I think I get it now.
To keep it simple you could hide your ListView with myList.setVisibility(View.GONE);
Then make a premade Label visible with myLabel.setVisibility(View.VISIBLE) that already holds your error-string.
The harder way you could make a StringArray, like this in (for example) the strings.xml
<string-array name="error">
<item>No results found</item>
</string-array>
Then, in your else-block you can do somethink like that:
ListView lv = (ListView) findViewById(R.id.myList);
String[] content = getResources().getStringArray(R.array.error);
ArrayAdapter<String> typeList = new ArrayAdapter<String>(this, R.layout.simple_list_item_custom, content);
lv.setAdapter(typeList);
I was following this tutorial.
I've modified it to my app's needs, such as no CRUD functionality and no main menu - I just want to list all the items during the main activity that gets executed when the app is launched.
Code seems to have no errors, but running it gives me: Unfortunately, MyFirstApp has stopped in the VM.
LogCat gives me this:
E/AndroidRuntime(910): java.lang.RuntimeException: Unable to start
activity
ComponentInfo{com.example.myfirstproject/com.example.myfirstproject.MainActivity}:
java.lang.RuntimeException: Your content must have a ListView whose id
attribute is 'android.R.id.list'
What do? I've checked my .xml layouts and made the changes, but the app still crashes.
MainActivity.java
package com.example.myfirstproject;
//imports
public class MainActivity extends ListActivity implements OnItemClickListener {
// Progress Dialog
private ProgressDialog pDialog;
// Creating JSON Parser object
JSONParser jParser = new JSONParser();
ArrayList<HashMap<String, String>> carsList;
// url to get all products list
private static String url_all_cars = "http://localhost/webservice/get_all_cars.php";
// JSON Node names
private static final String TAG_SUCCESS = "success";
private static final String TAG_CARS = "cars";
private static final String TAG_NAME = "name";
// products JSONArray
JSONArray cars = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Hashmap for ListView
carsList = new ArrayList<HashMap<String, String>>();
// Loading products in Background Thread
new LoadAllcars().execute();
// Get listview
ListView lv = getListView();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
/**
* Background Async Task to Load all product by making HTTP Request
* */
class LoadAllcars extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("Loading cars. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
/**
* getting All products from url
* */
protected String doInBackground(String... args) {
// Building Parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
// getting JSON string from URL
JSONObject json = jParser.makeHttpRequest(url_all_cars, "GET", params);
// Check your log cat for JSON reponse
Log.d("All cars: ", json.toString());
try {
// Checking for SUCCESS TAG
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
// products found
// Getting Array of Products
cars = json.getJSONArray(TAG_CARS);
// looping through All Products
for (int i = 0; i < cars.length(); i++) {
JSONObject c = cars.getJSONObject(i);
// Storing each json item in variable
String title = c.getString(TAG_NAME);
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
// adding each child node to HashMap key => value
map.put(TAG_NAME, name);
// adding HashList to ArrayList
carsList.add(map);
}
} else {
// no products found
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("No cars found");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
/**
* After completing background task Dismiss the progress dialog
* **/
protected void onPostExecute(String file_url) {
// dismiss the dialog after getting all products
pDialog.dismiss();
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
/**
* Updating parsed JSON data into ListView
* */
ListAdapter adapter = new SimpleAdapter(
MainActivity.this, carsList,
android.R.id.list, new String[] {TAG_NAME},
new int[] { R.id.title });
// updating listview
setListAdapter(adapter);
}
});
}
}
}
activity_main.xml (layout for the mainactivity with listview):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/list"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" >
</ListView>
</LinearLayout>
list_item.xml (layout for individual list items):
<?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="wrap_content"
android:orientation="vertical" >
<!-- Name Label -->
<TextView
android:id="#+id/name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="6dip"
android:paddingLeft="6dip"
android:textSize="17dip"
android:textStyle="bold" />
</LinearLayout>
Take a look at how they define the layout in the ListActivity documentation here
Your ListView Id is android:id="#+id/list" and it needs to be android:id="#android:id/list"
additionally, your ListAdapter is going to crash
ListAdapter adapter = new SimpleAdapter(
MainActivity.this, carsList,
android.R.id.list, new String[] {TAG_NAME},
new int[] { R.id.title });
You are telling the adapter to use the android ListView as the Item view..
You should be passing in your list_item.xml ID for this and using the proper TextView ID (name)
ex:
ListAdapter adapter = new SimpleAdapter(
MainActivity.this, carsList,
R.layout.list_item, new String[] {TAG_NAME},
new int[] { R.id.name});
In your activity_main.xml use android:id="#android:id/list" and not android:id="#+id/list" and it should work.
For now the ID of your ListView is yourapplicationpackage.R.id.list.
use android:id="#android:id/list" while assigning the id in xml.
Note that the id of the ListView must be #android:id/list to reference the required android.R.id.list per the ListActivity documentation.
In contrast, your id of #+id/list creates a new id com.example.myfirstproject.R.id.list.
It is old post but for others who faced same problem here is my solution:
If you are make sure, the ID of the List View or any other object you created is existed in layout - To make sure go head to gen sources, check the name of the id in R.java file. If it is not there, then you didn't create any item. - Then, In Java Code make sure android.R is not in the import list. If so rid off. Then manually add your package R.java
import com.yourpackagename.R;
Now you are able to add our item into Java Code: exp:
ListView lvitems = (ListView) findViewById(R.id.nameofit);
I don't recommend that Project>Clean in these situations, you could easily lose your generated R.java file.
I'm writing an IM client and I need to download (from filesystem or network) and show new elements at the top of ListView (it is history of messages -- older messages are at the top, newer -- at the bottom). I implemented my own Adapter for ListView but I can't add new elements at the beginning of the list and redraw it. (notifyDataSetChanged() isn't good for me, because indexes of messages in ListView changes and android can't redraw it normally).
How do other apps do something similar?
I don't create special code for it, I am simply creating new Adapter for my ListView:
messagesListView.setAdapter(new MessagesListAdapter(this));
And redefine getView() and getCount() method in MessagesListAdapter (extends ArrayAdapter now).
My XML for ListView is
<ListView
android:id="#+id/dialog_messages_list"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:layout_marginTop="#dimen/title_height">
</ListView>
And my XML for one element (one message) is
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="#+id/dialogMessageText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:background="#drawable/dialog_message_in"
/>
<TextView
android:id="#+id/dialogMessageDatetime"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=""/>
</LinearLayout>
May be you need other code?
EDIT: I tried
messagesListView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, arrayList));
(new Thread() {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
arrayList.add(0, "qwer");
}
}).start();
But it also not seems good. I tried to call ((ArrayAdapter<String>)messagesListView.getAdapter()).notifyDataSetChanged(); in thread, but it makes exception.
I suggest reversing the order of the List to display the newest result first.
Run this example:
public class Example extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String[] array = {"oldest", "older", "old", "new", "newer"};
List<String> list = new ArrayList<String>();
Collections.addAll(list, array);
Collections.reverse(list);
// When you want to add new Strings, put them at the beginning of list
list.add(0, "newest");
ListView listView = (ListView) findViewById(R.id.list);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);
listView.setAdapter(adapter);
}
}
You don't have to override anything in the ArrayAdapter or ListView this way.
you can programmatically add some views in the class associated with your list view. For example:
To add stuff to a layout and make new elements:
TextView tv = new TextView(getApplicationContext());
EditText edit = new EditText(getApplicationContext());
relative.addView(tv);
relative.addView(edit);
This is to manipulate an existing element in the xml layout:
final TextView tv = (TextView) v.findViewById(R.id.listItem);
tv.setText("This an item I am changing");
If you look at some of the related questions, they will give your more information on this. But you can also checkout other people's custom listviews and adapters online. This one is really nice: http://www.androidhive.info/2012/02/android-custom-listview-with-image-and-text/