problems updating a listview from xml - android

i have a listview builded from xml file by an lazyadapter (baseadpter)
for example: urlxml --> parser ---> baseadapter ---> listview
when i modified xml file on server i would like to refresh listview and see rows changed in it. By the way im using lib "pull to refresh".
When i pull to refresh i got new rows togheter old rows.
Do i have to delete listview content first and repeat this:
urlxml --> parser ---> baseadapter ---> listview
what is wrong?
EDIT woth some code
my adapter
public class LazyAdapter extends BaseAdapter {
private Activity activity;
ArrayList<ArrayList<String>> data = new ArrayList<ArrayList<String>> ();
private static LayoutInflater inflater=null;
public ImageLoader imageLoader;
public LazyAdapter(Activity a, ArrayList<ArrayList<String>> d) {
activity = a;
data=d;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageLoader=new ImageLoader(activity.getApplicationContext());
}
public int getCount() {
return data.get(0).size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.elenco_articoli_items, null);
String Tt = data.get(0).get(position);
String URl = data.get(1).get(position);
TextView text=(TextView)vi.findViewById(R.id.title);;
ImageView image=(ImageView)vi.findViewById(R.id.image);
text.setText(Html.fromHtml(Tt));
imageLoader.DisplayImage(URl, image,1);
return vi;
}
}
my main activity
public class Lista_articoli_categoria extends Activity {
ArrayList<String> images = new ArrayList<String> ();
ArrayList<String> title = new ArrayList<String> ();
ArrayList<String> author = new ArrayList<String> ();
ArrayList<String> description = new ArrayList<String> ();
private LazyAdapter adapter;
private RefreshableListView mListView;
Parser task = new Parser();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.elenco_articoli);
try {
task.execute();
final RefreshableListView list = (RefreshableListView) findViewById(R.id.refreshablelistview);
adapter= new LazyAdapter(this, fill_data(task.get()));
mListView = list;
list.setAdapter(adapter);
list.setOnUpdateTask(new OnUpdateTask() {
public void updateBackground() {
refresh_data();
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void updateUI() {
adapter.notifyDataSetChanged();
}
public void onUpdateStart() {
}
});
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
mListView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
/*
TODO
*/
}
});
}
#Override
public void onDestroy()
{
mListView.setAdapter(null);
super.onDestroy();
}
public ArrayList<ArrayList<String>> fill_data(ArrayList<Struttura_rss> Datidaxml){
ArrayList<ArrayList<String>> rec = new ArrayList<ArrayList<String>> ();
for(int i=0;i<Datidaxml.size();i++){
Struttura_rss p = Datidaxml.get(i);
title.add(p.getTitle());
images.add(p.getImage());
description.add(p.getArticolo());
author.add(p.getAuthor());
}
rec.add (title);
rec.add (images);
rec.add (description);
rec.add (author);
return rec;
}
public void refresh_data(){
try {
Parser task = new Parser();
task.execute();
adapter= new LazyAdapter(this, fill_data(task.get()));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}

If you look at the example, you should understand easily...
Link: https://github.com/chrisbanes/Android-PullToRefresh/blob/master/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshListActivity.java
On the refreshn you have to download only the new items (by exemple by sending a timestamp or an id to the webservice)
#Override
protected String[] doInBackground(Void... params) {
// Simulates a background job.
try {
//Go to webservice
} catch (InterruptedException e) {
}
return mStrings;
}
And then, parse only the new items and add them here:
#Override
protected void onPostExecute(String[] result) {
mListItems.addFirst("Added after refresh...");
mAdapter.notifyDataSetChanged();
// Call onRefreshComplete when the list has been refreshed.
mPullRefreshListView.onRefreshComplete();
super.onPostExecute(result);
}
EDIT: if you cannot download only the needed items (RSS feed) download evrything and add the correct items in onPostExecute.
if(!isALreadyInTheList(currentItem))
mListItems.addFirst(currentItem);
else
doNothing();

Related

android: listview load incorrectly

My listview load properly but when I go back to my MainActivity then again go to ViewAll activity then it load incorrectly like below.
Here is my ViewAll activity where I have load list view.
public class ViewAll extends Activity {
private ListView listView;
public ArrayList<Model> arrayList;
private Database_Handler database_handler;
private SQLiteDatabase db;
private MyAdapter adapter;
private SwipeRefreshLayout swipeContainer;
private long i = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_all);
listView = (ListView) findViewById(R.id.listView);
swipeContainer = (SwipeRefreshLayout) findViewById(R.id.swipeContainer);
addNewData();
database_handler = new Database_Handler(ViewAll.this);
db = database_handler.getReadableDatabase();
arrayList = database_handler.getAllContacts();
adapter = new MyAdapter(ViewAll.this, arrayList);
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
swipeContainer.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
try {
database_handler = new Database_Handler(ViewAll.this);
db = database_handler.getReadableDatabase();
arrayList = database_handler.getAllContacts();
adapter = new MyAdapter(ViewAll.this, arrayList);
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
swipeContainer.setRefreshing(false);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private void addNewData() {
try {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
String str1 = "List "+i+" ", str2 = "Handler testing";
database_handler = new Database_Handler(ViewAll.this);
db = database_handler.getWritableDatabase();
database_handler.addRegister(str1, str2, db);
database_handler.close();
handler.postDelayed(this, 60 * 10);
i++;
}
}, 60 * 10);
} catch (Exception e) {
e.printStackTrace();
}
}
}
and here is my adapter.
public class MyAdapter extends BaseAdapter{
private Context context;
private ArrayList<Model> arrayList;
private static LayoutInflater inflater;
public MyAdapter(ViewAll viewAll, ArrayList<Model> arrayList) {
this.context = viewAll;
this.arrayList = arrayList;
}
#Override
public int getCount() {
return arrayList.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
public class Holder {
TextView tvFirstName,tvLastName;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View myView = null;
try {
Holder holder;
myView = convertView;
if (myView == null) {
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
myView = inflater.inflate(R.layout.adapter, null);
holder = new Holder();
holder.tvFirstName= (TextView) myView.findViewById(R.id.tvFirstName);
holder.tvLastName= (TextView) myView.findViewById(R.id.tvLastName);
myView.setTag(holder);
}
else {
holder = (Holder) myView.getTag();
}
holder.tvFirstName.setText(arrayList.get(position).getF_name());
holder.tvLastName.setText(arrayList.get(position).getL_name());
} catch (Exception e) {
e.printStackTrace();
}
return myView;
}
}
Actually I am inserting data into database using handler class and show all data into listview in my ViewAll activity and it work fine but when i go to my previous MainActivity and again go to ViewAll activity then listview load incorrectly which show in the image like after "List 24" data inserted incorrectly.
Please Clear your Arraylist and also clear your adapter when you are loading it from first item of listview.
You can clear this by lstVwList.setAdapter(null);

android get rssitem description from listview

In my android app I'm using a ListView populated by RSSItems taken from a webpage url; the listview shows me only title and pubdate of rssitem.
I would realize that when I click on rssitem of the listview, app shows me an alert dialog showing me in message box the descritpion of the rssitem title.
How can I realize it?
Here the code:
public class MainActivity extends ActionBarActivity{
private ListView listview;
URL url = null;
RssFeed feed = null;
AlertDialog.Builder alert;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listview = (ListView) findViewById(R.id.listView);
alert = new AlertDialog.Builder(MainActivity.this);
try {
url = new URL("http://www.unikore.it/index.php/ingegneria-informatica-home?format=feed");
} catch (MalformedURLException e) {
e.printStackTrace();
}
new ReadRssTask().execute(url);
}
private class ReadRssTask extends AsyncTask<URL, Void, RssFeed> {
#Override
protected RssFeed doInBackground(URL... params) {
RssFeed result = null;
URL url = params[0];
if (!TextUtils.isEmpty(url.toString())) {
try {
result = RssReader.read(url);
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
#Override
protected void onPostExecute(RssFeed result) {
if (result != null) {
ArrayList<RssItem> rssItems = (ArrayList<RssItem>) result.getRssItems();
ArrayList<String> arrayList = new ArrayList<String>();
for (final RssItem rssItem : rssItems) {
arrayList.add(rssItem.getTitle()+"\n"+rssItem.getPubDate()+"\n");
ArrayAdapter<String> lista = new ArrayAdapter<String>(getBaseContext(),android.R.layout.simple_list_item_1,arrayList);
listview.setAdapter(lista);
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,long id) {
alert.setTitle(listview.getItemAtPosition(position).toString());
alert.setMessage(); //HERE I SHOULD SET THE rssItem.getDescription()
alert.show();
}
});
Log.i("RSS Reader", rssItem.getTitle());
}
}
}
}
}
You need to change here
alert.show();
to
AlertDialog dialog = alert.create(); // You missed this
dialog.show():
Edit:
Remove this from loop and move to onCreate() after your asynctask executed.
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,long id) {
alert.setTitle(listview.getItemAtPosition(position).toString());
alert.setMessage(rssItems.get(position).getDescription()); //HERE YOU SHOULD SET THE rssItem.getDescription()
alert.show();
}
});
Make this ArrayList<RssItem> rssItems public static and use as
rssItems = (ArrayList<RssItem>) result.getRssItems();

Skipped 60 frames! The application may be doing too much work on its main thread

I'm working on a App that should get a JSON response from a webservice and write every element in a listview, I have read that I should work with AsyncTask to get the HTTP Response and I did it and I could retrieve data from the webservice and display them in TextViews. But when I try to display elements in a listview it doesn't display anything and gives me the following message in the logcat : 06-05 19:44:27.418: I/Choreographer(20731): Skipped 60 frames! The application may be doing too much work on its main thread.
here's my main code :
public class MainActivity extends Activity {
private static JsonObject response = new JsonObject();
private ArrayList<SearchResults> results = new ArrayList<SearchResults>();
private SearchResults sr1 = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new LoginAction().execute("");
ArrayList<SearchResults> searchResults = results;
final ListView lv1 = (ListView) findViewById(R.id.ListView01);
lv1.setAdapter(new MyCustomBaseAdapter(this, searchResults));
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private class LoginAction extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
Map<String, String> callArgs = new HashMap<String, String>(1);
callArgs.put("suuid", "dtr0bdQGcqwSh3QO7fVwgVfBNWog6mvEbAyljlLX9E642Yfmur");
try {
response = EventPulseCloud.call("ListEvents", callArgs);
} catch (HttpClientException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JsonException e) {
e.printStackTrace();
}
return response.get("Type").toString();
}
protected void onPostExecute(String result) {
if(result.equals("success")) {
JsonArray records = null;
try {
records = response.getObject ("Data").getArray ("Records");
} catch (JsonException e) {
e.printStackTrace();
}
for(int i = 0; i < records.count(); i++) {
JsonObject record = (JsonObject) records.get(i);
sr1 = new SearchResults();
sr1.setAddress(record.get("address").toString());
results.add(sr1);
}
}
}
}
}
My list adapter :
public class MyCustomBaseAdapter extends BaseAdapter {
private static ArrayList<SearchResults> searchArrayList;
private LayoutInflater mInflater;
public MyCustomBaseAdapter(Context context, ArrayList<SearchResults> results) {
searchArrayList = results;
mInflater = LayoutInflater.from(context);
}
public int getCount() {
return searchArrayList.size();
}
public Object getItem(int position) {
return searchArrayList.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.custom_row_view, null);
holder = new ViewHolder();
holder.txtAddress = (TextView) convertView.findViewById(R.id.address);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.txtAddress.setText(searchArrayList.get(position).getAddress());
return convertView;
}
static class ViewHolder {
TextView txtAddress;
}
}
and finally, SearchResults.java :
public class SearchResults {
private String address = "";
public void setAddress(String address) {
this.address = address;
}
public String getAddress() {
return address;
}
}
So, what do I do wrong ? Do you have an idea about this ?
Thank you.
onPostExecute() happens on the Main UI thread. It looks like you are still doing a fair amount of work in that method that should be done off the UI thread, i.e. processing the response, iterating over JSON objects, etc. Do that in doInBackground() and have that return a list of results, so the only thing onPostExecute needs to do is pass the new items to your list adapter.
Also, do not use the same ArrayList as the one your adapter holds. If for some reason the adapter discovers that the data has changed without you having called notifyDataSetChanged(), it will probably crash (or at least display odd behaviors). Create a new ArrayList in your AsyncTask, then put this in your Adapter and call it from onPostExecute:
public void setListItems(ArrayList<SearchResult> newList) {
searchArrayList = newList;
notifyDataSetChanged();
}
private class LoginAction extends AsyncTaskList<String, Void, ArrayList<SearchResult>> {
#Override
protected ArrayList<SearchResult> doInBackground(String... params) {
List<SearchResults> resultList = new ArrayList<SearchResults>();
Map<String, String> callArgs = new HashMap<String, String>(1);
callArgs.put("suuid", "dtr0bdQGcqwSh3QO7fVwgVfBNWog6mvEbAyljlLX9E642Yfmur");
try {
response = EventPulseCloud.call("ListEvents", callArgs);
} catch (HttpClientException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JsonException e) {
e.printStackTrace();
}
//See here I am running the loop in the background so its not on the main thread, then passing the list off to the onpostexecute that way all the main thread does is set the adapter list and notify it of the data update and the list should be updated on the screen
if( response.get("Type").toString().equals("success")) {
JsonArray records = null;
try {
records = response.getObject ("Data").getArray ("Records");
} catch (JsonException e) {
e.printStackTrace();
}
for(int i = 0; i < records.count(); i++) {
JsonObject record = (JsonObject) records.get(i);
sr1 = new SearchResults();
sr1.setAddress(record.get("address").toString());
resultList.add(sr1);
}
}
return resultList;
}
protected void onPostExecute(ArrayList<SearchResult> resultList) {
setListItems(resultList);
}
}
}
add this line before the oncreate with all your other global var
//here you want to create an adapter var with your base adapter so you can set it the updated list later when you have populated data from the internet
ArrayList<SearchResults> searchResults = new ArrayList<SearchResults>();
MyCustomBaseAdapter adapter = new MyCustomBaseAdapter(this, searchResults)
paste this over your oncreate method (replace it)
//here is just the code to update your main method to reflect all the changes I made
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new LoginAction().execute("");
final ListView lv1 = (ListView) findViewById(R.id.ListView01);
lv1.setAdapter(adapter);
}
and add this method to the adapter(MyCustomnBaseAdapter class) code
public void setListItems(ArrayList<SearchResult> newList) {
searchArrayList = newList;
notifyDataSetChanged();
}

android - identify items in a ListView

I'm having some troubles with correct identification of items in a ListView.
There are 4 classes that matter, it's a lot of code so at first I'm going to explain the logic of those classes.
Enter the ListActivity and initialize its ListView
execute an AsyncTask that downloads JSON response from the server, parses it, populates the ListView with Objects and sets the adapter while showing a ProgressDialog
the PlaylistItem class includes methods which simply get the data from a single JSONObject. It is used to parameterize the ArrayList with its Objects
after the AsyncTask is done the list is filled with items and looks like |Button| Artist(TextView) - Title(TextView)
UPDATE
resolved 1st issue but still can't figure out what's wrong with buttons
2). I set an OnClickListener to my buttons in the Adapter's getView() method. To find out if the button is identified correctly I did nothing but just changed its background. BUT a click on a certain button forces the background of every 11th or 12th button to be changed. Can't figure it out so far.
I can't proceed to getting url and streaming audio until those problems are resolved, so any help is greatly appreciated. My classes go below, please ask if something appears unclear.
AudioList
public class AudioList extends ListActivity {
private ListView lv;
private PlaylistLoader loader;
private AudioListAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_audio_list);
init(); // initialize the ListView
/*--- populate the list with user's audio in case network connection is available ---*/
loader = new PlaylistLoader(this, lv, adapter);
if (Utils.isNetworkAvailable(this)) {
loader.execute();
} else {
APP_CONSTANTS.NO_DATA_CONNECTION(this);
}
}
#Override
protected void onResume() {
super.onResume();
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
Toast.makeText(getApplicationContext(), Integer.toString(arg2),
Toast.LENGTH_SHORT).show();
}
});
}
private void init() {
lv = getListView();
lv.setTranscriptMode(0x00000000);
lv.setDividerHeight(1);
lv.setSmoothScrollbarEnabled(true);
lv.setVerticalFadingEdgeEnabled(true);
}
PlaylistLoader
public class PlaylistLoader extends AsyncTask<Void, Void, Void> {
private JSONObject usersPlaylist, singleJSONItem;
private JSONArray responseJSONArray;
private ListView lv;
private ArrayList<PlaylistItem> playlist;
private Activity a;
private PlaylistItem audioList;
private SharedPreferences prefs;
private ProgressDialog pd;
AudioListAdapter adapter;
public PlaylistLoader(Activity a, ListView lv, AudioListAdapter adapter) {
this.lv = lv;
this.a = a;
this.adapter = adapter;
}
#Override
protected Void doInBackground(Void... arg0) {
/*--- create new ArrayList of PlaylistItem Objects ---*/
playlist = new ArrayList<PlaylistItem>();
/*--- get the preferences using context of calling activity ---*/
prefs = PreferenceManager.getDefaultSharedPreferences(a);
try {
/*--- download the response JSONObject from server // access_token and
* user_id come from activity's defaultSharedPreferences ---*/
usersPlaylist = Utils.retrieveJsonObjectFromUrl(new URL(
APP_CONSTANTS.REQUEST_AUDIO_LIST(prefs)), a);
/*--- get the response array from received object ---*/
responseJSONArray = usersPlaylist.getJSONArray("response");
/*--- populate the ArrayList with Objects from the response array ---*/
for (int i = 0; i < responseJSONArray.length(); i++) {
singleJSONItem = responseJSONArray.getJSONObject(i);
audioList = new PlaylistItem(singleJSONItem);
playlist.add(audioList);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
pd = new ProgressDialog(a);
pd.setTitle("Please wait");
pd.setMessage("Retrieving audio list...");
pd.show();
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
lv.setVisibility(View.VISIBLE);
pd.dismiss();
/*--- set the adapter passed in constructor as an adapter for passed ListView ---*/
adapter = new AudioListAdapter(a, R.layout.playlist_item, playlist);
lv.setAdapter(adapter);
}
}
AudioListAdapter
public class AudioListAdapter extends ArrayAdapter<PlaylistItem> {
private PlaylistItem pl;
private Context context;
private int layoutResourceId;
private PlaylistItem aud;
private ArrayList<PlaylistItem> data = null;
public AudioListAdapter(Context context, int layoutResourceId,
ArrayList<PlaylistItem> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public PlaylistItem getItem(int position) {
return super.getItem(position);
}
#Override
public int getCount() {
return data.size();
}
#Override
public int getPosition(PlaylistItem item) {
return super.getPosition(item);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
pl = new PlaylistItem();
aud = getItem(position);
if (convertView == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
convertView = inflater.inflate(layoutResourceId, parent, false);
pl.btnPlay = (Button) convertView.findViewById(R.id.btn_list_play);
pl.imgSaved = (ImageView) convertView
.findViewById(R.id.img_list_audio_saved);
pl.tvArtist = (TextView) convertView
.findViewById(R.id.tvListItemArtist);
pl.tvTitle = (TextView) convertView
.findViewById(R.id.tvListItemSong);
convertView.setTag(pl);
} else {
pl = (PlaylistItem) convertView.getTag();
pl.btnPlay.setBackgroundResource(R.drawable.list_button_play);
}
pl.tvArtist.setText(aud.getArtist() + " " + "-");
pl.tvTitle.setText(aud.getTitle());
pl.btnPlay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
/*--- vibrate if this option is enabled in the preferences ---*/
if (APP_CONSTANTS.isHapticFeedbackEnabled(getContext())) {
APP_CONSTANTS.doVibrate(getContext());
}
pl.btnPlay.setBackgroundResource(R.drawable.list_button_pause);
}
});
return convertView;
}
PlayListItem
public class PlaylistItem {
private String artist, title;
private JSONObject obj;
public Button btnPlay;
public TextView tvArtist, tvTitle;
public ImageView imgSaved;
public int duration;
public int audio_id;
public String url;
/*--- the constructor takes a single JSONObject from the response array ---*/
public PlaylistItem(JSONObject obj) {
this.obj = obj;
}
public PlaylistItem() {
// default constructor
}
/*--- the methods below return values by key from the passed JSONObject ---*/
public String getArtist() {
try {
artist = obj.getString("artist");
} catch (JSONException e) {
e.printStackTrace();
}
return artist;
}
public String getTitle() {
try {
title = obj.getString("title");
} catch (JSONException e) {
e.printStackTrace();
}
return title;
}
public int getID() {
try {
audio_id = obj.getInt("aid");
} catch (JSONException e) {
e.printStackTrace();
}
return audio_id;
}
public String getURL() {
try {
url = obj.getString("url");
} catch (JSONException e) {
e.printStackTrace();
}
return url;
}
}
Edit:
Try this
Take a custom Selector in your drawable
button_play.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/pause_button"
android:state_selected="true" />
<item android:drawable="#drawable/play_button" />
</selector>
Modifty your adapter like this
public class AudioListAdapter extends ArrayAdapter<PlaylistItem> {
private PlaylistItem pl;
private Context context;
private int layoutResourceId;
private PlaylistItem aud;
private ArrayList<PlaylistItem> data = null;
Button previous;
public AudioListAdapter(Context context, int layoutResourceId,
ArrayList<PlaylistItem> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
previous=new Button(context);
this.context = context;
this.data = data;
}
....
....
#Override
public View getView(int position, View convertView, ViewGroup parent) {
pl = new PlaylistItem();
aud = getItem(position);
if (convertView == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
convertView = inflater.inflate(layoutResourceId, parent, false);
pl.btnPlay = (Button) convertView.findViewById(R.id.btn_list_play);
pl.btnPlay.setBackGroundResouce(R.drawable.button_play); //you can set here or in xml
pl.imgSaved = (ImageView) convertView
.findViewById(R.id.img_list_audio_saved);
pl.tvArtist = (TextView) convertView
.findViewById(R.id.tvListItemArtist);
pl.tvTitle = (TextView) convertView
.findViewById(R.id.tvListItemSong);
convertView.setTag(pl);
} else {
pl = (PlaylistItem) convertView.getTag();
}
pl.tvArtist.setText(aud.getArtist() + " " + "-");
pl.tvTitle.setText(aud.getTitle());
pl.btnPlay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
/*--- vibrate if this option is enabled in the preferences ---*/
if (APP_CONSTANTS.isHapticFeedbackEnabled(getContext())) {
APP_CONSTANTS.doVibrate(getContext());
}
//for some reason, the background gets changed for every 11th or 12th button in the list
Button current=((Button)v);
current.setSelected(true);
previous.setSelected(false);
previous=current;
}
});
return convertView;
}
}
The reason why your button and listitem not clickable is because Your list have a focus item button, so you need to setFocusable=false for your button.
Try setting focusable=false for your button in the xml. If it is not worked for you than do like this
In your row xml file
1.set focusable=true for your button.
2.In the same set android:descendantFocusability="blocksDescendants" for your parent item.(i.e parent layout in which your views lie).
In getView() method after setting the onclickListener for the button, set focusable false for the button.
It will work for sure. I hope this will help you..
BUT a click on a certain button forces the background of every 11th or 12th button to be changed. Can't figure it out so far.
You are fighting the way ListViews recycle the row layouts.
Think of it this way: if you have a ListView with 10,000 rows but can only fit 9 of them on the screen, then it doesn't make sense to create 10,000 unique layouts. This just waste resources, instead ListView only creates ~10 layouts and reuses them.
Solution: return each row to it's default state when it is reused. In getView() add:
} else {
pl = (PlaylistItem) convertView.getTag();
pl.btnPlay.setBackgroundResource(R.drawable.list_button_play);
// I guessed at the resource's name ^^^^^^^^^^^^^^^^
}
(Also you can make a few small changes to speed up your code. For instance, you only need one OnClickListener since they all contain the same code, make this a class variable and pass this to each play Button. There are more.)

How to call addHeaderView in ListFragment?

Is it a correct way to set headerView to ListView in Fragment?
I have some fragment(see below code). In this fragment i populate ListView.
But I don't know where I can call addHeaderView.
Can anybody help me?
public class FeedsListForViewFragment extends ListFragment {
private Context mContext;
List<FeedItem> items;
private int layoutForList = R.layout.list_feeds_simple;
private ActiveRecordBase _db;
private Activity mActivity;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivity = getActivity();
_db = ((JtjApplication)getActivity().getApplication()).getDatabase();
try {
_db.open();
} catch (ActiveRecordException e) {
e.printStackTrace();
}
}
public void setItemsToList(List<FeedItem> items, int curPosition) {
mContext = getActivity().getApplicationContext();
this.items = items;
ListView lv = getListView();
setListAdapter(new ListOfFeedsAdapter(mContext, layoutForList, items, mActivity));
lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
lv.setCacheColorHint(Color.WHITE);
setPosition(curPosition);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
if (!(((FeedsActivity) getActivity()).getCurrentPosition() == position)) {
updateUnreadItemsInDb(position);
updateLinksList(position, items.get(position));
((FeedsActivity) getActivity()).setCurrentPosition(position);
}
}
#SuppressWarnings("unchecked")
private void updateUnreadItemsInDb(int position) {
FeedItem feed = items.get(position);
if (feed.isRead != true) {
List<FeedItem> feedsForUpdate = null;
List<FeedType> lft = null;
try {
feedsForUpdate = _db.find(FeedItem.class, false, "GUID=?", new String[] { String.valueOf(feed.guid) }, null, null, "PUBLICATIONDATE DESC", null);
lft = _db.findAll(FeedType.class);
} catch (ActiveRecordException e1) {
e1.printStackTrace();
}
for (FeedItem curFeed:feedsForUpdate) {
curFeed.isRead = true;
try {
curFeed.save();
FeedType ft = lft.get(Integer.parseInt(curFeed.channel_id) - 1);
ft.unread_count = ft.unread_count - 1;
ft.update();
} catch (ActiveRecordException e) {
e.printStackTrace();
}
}
items.get(position).isRead = true;
((ArrayAdapter<FeedItem>) getListView().getAdapter()).notifyDataSetChanged();
}
}
private void setPosition(int position) {
ListView lv = getListView();
lv.setSelection(position);
lv.setItemChecked(position, true);
try{
updateLinksList(position, items.get(position));
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
}
}
private void updateLinksList(int position, FeedItem feedItem) {
FeedsViewFragment viewFragment = (FeedsViewFragment) getFragmentManager().findFragmentById(R.id.feed_view_fragment);
viewFragment.setViewItem(feedItem);
}
}
You would call addHeaderView() between:
ListView lv = getListView();
and:
setListAdapter(new ListOfFeedsAdapter(mContext, layoutForList, items, mActivity));
Now, I have not tried a header View on a ListFragment, so while it should work, there is a chance that for some reason it does not.

Categories

Resources