So guys, i'll try to explain a bit of this part of my project i wanted to do so you guys can better understand my problem. I'm trying no develop an app to a bus station, to show the schedule. And to show it, i was using a ListView, a costum one. And it works if i only pass Strings to the adapter. But in order to do only in an Array of Strings would take a lot of memory cause i would have to build a lot of arrays. Because, try to imagine, i have the schedule of the bus leaving a certain place, but then, depending in what destination the user selects i have to exclude some of items from the array because not all bus's end at the same place, some won't go to the destination selected, so i have to take those out. So if i was going to do that in just multiple arrays e would have to build dozens of array to every single possibilitie of departure and destination. So i thought in doing it with an arraylist, so would be easier to remove the items i don't want.
Now the problem is that i can't send to the adapter of the costum listview and arraylist, like this:
ArrayList<String> horarios= new ArrayList<String>();
ListAdapter horarioAdapter = new costum_adapter(this, horarios);
ListView horarioListView = (ListView) findViewById(R.id.horario_listView);
horarioListView.setAdapter(horarioAdapter);
It gives me error in the second line, because i can't put "horarios" in adapter because its an arraylist. How can i solve this ? Hope you guys understood what i was trying to do.
Sorry for the long description.
Here is my costum_adapter, doesn't have much, only 2 textView, i was just trying this to work, and then add a few things.
class costum_adapter extends ArrayAdapter<String>{
public costum_adapter(Context context, String[] horarios) {
super(context, R.layout.costum_listview ,horarios);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater horarioInflater = LayoutInflater.from(getContext());
View costumView = horarioInflater.inflate(R.layout.costum_listview, parent, false);
String singleHorario = getItem(position);
TextView hora = (TextView) costumView.findViewById(R.id.Hora);
TextView nota = (TextView) costumView.findViewById(R.id.Nota);
hora.setText(singleHorario);
nota.setText(" ");
return costumView;
}
}
Fix arguments in adapter constructor
public costum_adapter(Context context, ArrayList<String> horarios) {
super(context, R.layout.costum_listview ,horarios);
}
Related
I am new to android and my code has got a bit messy. I have successfully created a list view extended from item_layout.xml. When I click on the list view It works exactly how I want it. However in each item of the list view I have a button that when clicked I want the item of the list to delete.
When researching I have come across that you need to create a customer adapter to do this however I have come so far in the project that I wouldn't even know where to start.
This code it used successfully to when the list items are clicked it works. This is just put in the Main Activity class
mylist.setOnItemClickListener(
new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View view, final int position, long id) {
}
}
);
I populate the list using this function just outside the main activity class. It is needed to be written like this as It gets the items from a database and has to be called depending on different circumstances
private void populatelistView() {
Cursor res = userDb.getAllRows();
String[] fromFeildnames = new String[]{ DatabaseUser.KEY_1, DatabaseUser.KEY_2};
int[] toViewIds = new int[]{R.id.textViewNum, R.id.textViewItem};
SimpleCursorAdapter myCursorAdaptor;
myCursorAdaptor = new SimpleCursorAdapter(getBaseContext(), R.layout.item_layout, res, fromFeildnames, toViewIds, 0);
//ListView mylist = (ListView) findViewById(R.id.listViewID);
mylist.setAdapter(myCursorAdaptor);
}
I would like to be able to get the button on each items to work by not changing much of what I have already written. I have tried just using the following code. But because it is in a different xml layout it display an error of null reference towards the item button
delete.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
View parentRow = (View) v.getParent();
ListView listView = (ListView) parentRow.getParent();
final int position = listView.getPositionForView(parentRow);
Toast.makeText(getApplicationContext(), "Button " + position, Toast.LENGTH_SHORT).show();
}
}
);
Please could someone help me make the button work without changing much code or give me a step by step tutorial on how to add an adapter but make my populateListView function do the same thing.
Ps. I have looked at so many tutorials about list adapters but can't find ones that are for my specific need
I'm parsing a web service to display in a listView backed by my own subclass of ArrayAdapter. The data is static ArrayList<Wait> in Application.java. You'll see it referenced by App.getWaits().
I use a simple refresh method for when there's new data. I've confirmed that it's being updated but it only renders if I navigate away and then return to the view.
In the past I've been able to refresh the listView by calling notifyDataSetChanged() on the adapter but right now none of these have worked for me. Thanks for taking a look... any ideas!?
//1 This is how I'd normally update the listView dynamically, but not tonight.
adapter.notifyDataSetChanged();
//2 It's the same thing really, so no good.
((WaitAdapter) list.getAdapter()).notifyDataSetChanged();
//3 Saw this as the answer to a similar question, doesn't work.
adapter.getWaits().clear();
adapter.getWaits().addAll(App.getWaits());
adapter.notifyDataSetChanged();
//4 Called in onCreate but tried a 2nd time in refresh() to manually reset adapter, doesn't work.
adapter = new WaitAdapter(getHost().getApplicationContext(), App.getWaits());
list.setAdapter(adapter);
//5 Kinda the same thing, new adapter, reset adapter... also no good.
WaitAdapter adapter = new WaitAdapter(getHost().getApplicationContext(), App.getWaits());
list.setAdapter(adapter);
//6 I read ArrayAdapter keeps its own reference to initial data object but this fails too.
adapter = null;
adapter = new WaitAdapter(getHost().getApplicationContext(), App.getWaits());
list.setAdapter(adapter);
*Update to share my WaitAdapter.java.
public class WaitAdapter extends ArrayAdapter<Wait> {
private LayoutInflater inflater;
private ArrayList<Wait> waits;
public WaitAdapter(Context context, ArrayList<Wait> data) {
super(context, R.layout.list_item_wait, data);
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
waits = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_item_wait, parent, false);
holder = new ViewHolder();
holder.checkpointName = (TextView) convertView.findViewById(R.id.checkpointName);
holder.delayAmount = (TextView) convertView.findViewById(R.id.delayAmount);
holder.timeReported = (TextView) convertView.findViewById(R.id.timeReported);
holder.dateReported = (TextView) convertView.findViewById(R.id.dateReported);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Wait wait = waits.get(position);
holder.checkpointName.setText(wait.getName());
holder.delayAmount.setText(wait.getDelayInMinutes());
holder.timeReported.setText(wait.getTimeLabel());
holder.dateReported.setText(wait.getDateLabel());
return convertView;
}
#Override
public boolean isEnabled(int position) {
return false;
}
static class ViewHolder {
TextView checkpointName;
TextView delayAmount;
TextView timeReported;
TextView dateReported;
}
}
12/14/14 Update: General implementation background.
At launch the App class starts WaitAsyncTask, which parses remote XML to fill its ArrayList waits. I'll access these waits in a few places so this way I keep them global.
WaitFragment, working with WaitAdapter, displays waits in a ListView and listens for changes to waits. User's can post waits to the web service via an AlertDialog. A successful response executes WaitAsyncTask again, updating the waits object, triggering a WaitFragment refresh().
Console logs and the web service confirm this flow of control and that waits gets updated. If I leave WaitFragment then return, it shows the updated waits. The code posted with comments #1-6 are what I've tried inside of the refresh() to update the ListView.
I use this general approach with other data and fragments in this app and their UIs refresh as intended, but none are listViews. I'm not sure I could post more source without redacting most of it but I'll share my findings once I get it working. I haven't had trouble with ListView before, but it'll be something embarrassing for sure. Thanks to everyone who took a little time :)
Just create a method in Adapter class to update/refresh the listview as follows,
public class WaitAdapter extends ArrayAdapter<Wait> {
private LayoutInflater inflater;
private ArrayList<Wait> waits;
public WaitAdapter(Context context, ArrayList<Wait> data) {
super(context, R.layout.list_item_wait, data);
inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
waits = data;
}
/**
* Update content
*/
public void updateListContent(ArrayList<Wait> data)
{
waits = data;
notifyDataSetChanged();
}
}
In your acivity class, just call this adapter method to update the content. Refer the below code
Note:Dont clear the array content of the adapter.
//Dont clear the arraylist of adapter
adapter.updateListContent(App.getWaits());
This may help you.
I have watched Android developer's videos on animating ListView insertion and deletion on YouTube. These have had very complex code in them and I tried searching for something else and found this.
http://karnshah8890.blogspot.fi/2013/04/listview-animation-tutorial.html
It has pretty simple implementation that works in most parts. My problem is that when I insert a new item in the ArrayList that is supplied to the ArrayAdapter, all the existing elements get reinserted due to adapter.notifyDataSetChanged()... I think. When I insert an entry in the ListView, how do I prevent all the entries from getting animated again? I just want the new one to animate in.
I use my ListView in the code this way:
toggles = (ListView) v.findViewById(R.id.toggleListView);
adapter = new ToggleListAdapter(getActivity(), toggleTasks);
toggles.setAdapter(adapter);
When a new item is inserted, I update the ArrayList (toggleTasks) and then call notifyDataSetChanged() on the adapter.
toggleTasks.add(task);
adapter.notifyDataSetChanged();
Here is my getView() method from the ArrayAdapter.
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ToggleTask task = toggles.get(position);
String startActionName = "";
String finishActionName = "";
int imageDrawableId = -1;
// Deleted the part where I get the values for those three variables above
final Holder holder;
if(convertView == null) {
convertView = inflater.inflate(R.layout.mute_toggles_toggle_view, null);
holder = new Holder();
holder.image = (ImageView) convertView.findViewById(R.id.image);
holder.startAction = (TextView) convertView.findViewById(R.id.startAction);
holder.finishAction = (TextView) convertView.findViewById(R.id.finishAction);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
holder.image.setImageResource(imageDrawableId);
holder.startAction.setText(startActionName);
holder.finishAction.setText(finishActionName);
Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.listview_push_left_in); // Third animation example on the site linked earlier
animation.setDuration(500);
convertView.startAnimation(animation);
animation = null;
return convertView;
}
in the ArrayAdatper class add a global integer (I'll call it changedIndex) and create getter and setters for it. Then before you add an item to the list say adapter.setChangedIndex(index) (whatever you name your setter). You are essentially telling it ahead of time which one you want to animate.
Change this in getView
if(changedIndex == position){
Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.listview_push_left_in); // Third animation example on the site linked earlier
animation.setDuration(500);
convertView.startAnimation(animation);
animation = null;
}
then change
toggleTasks.add(task);
adapter.notifyDataSetChanged();
to
toggleTasks.add(task);
toggles.getPosition(task);
adapter.notifyDataSetChanged();
*I haven't checked any of this code but I believe it should work
Well if you want to animate only the last item inserted, then before animating check if it is last item in the List.
if (position == getCount() - 1) {
Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.listview_push_left_in); // Third animation example on the site linked earlier
animation.setDuration(500);
convertView.startAnimation(animation);
animation = null;
}
Use the ListViewAnimations library. After setting up your ListView and ListAdapter like this:
MyListAdapter mAdapter = new MyListAdapter(this, getItems());
SwingRightInAnimationAdapter swingRightInAnimationAdapter = new SwingRightInAnimationAdapter(mAdapter);
// Assign the ListView to the AnimationAdapter and vice versa
swingRightInAnimationAdapter.setAbsListView(getListView());
getListView().setAdapter(swingRightInAnimationAdapter);
Call AnimationAdapter.setShouldAnimateFromPosition(int position) somewhat like this:
swingRightInAnimationAdapter.setShouldAnimateFromPosition(swingRightInAnimationAdapter.getCount());
swingRightInAnimationAdapter.add(myItem);
Have a look at the wiki for more information about how to use the library.
I am currently creating a basic news aggregator app for Android, I have so far managed to create multiple HorizontalListViews derived from this: http://www.dev-smart.com/archives/34
I am parsing all data from live JSON objects and arrays.
The process goes something like this:
1) Start app
2) Grab a JSON file which lists all feeds to display
3) Parse feed titles and article links, add each to an array
4) Get number of feeds from array and create individual HorizontalListView for each. i.e. "Irish Times".
5) Apply BaseAdapter "mAdapter" to each HorizontalListView during creation.
My baseadapter is responsible for populating my HorizontalListViews by getting each title and thumbnail.
My problem is however that all my feeds seem to contain the same articles and thumbnails. Now I am only new to Android so I'm not 100% sure whats going wrong here. See screenshot below.
Do I need to create a new BaseAdaptor for each HorizontalListview or can I use the same one to populate all my listviews with unique data.
Here's some code to help explain what I mean:
1) OnCreate method to get JSON data, parse it, get number of feeds and create each HorizontalListView
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listviewdemo);
//--------------------JSON PARSE DATA------------------
// Creating JSON Parser instance
JSONParser jParser = new JSONParser();
// getting JSON string from URL
String json = jParser.getJSONFromUrl(sourcesUrl);
//Parse feed titles and article list
getFeeds(json);
//Create Listviews
for(int i = 0; i < feedTitle.size()-1; i++){
//getArticleImage(i);
addHorzListView(i);
articleArrayCount++;//Used to mark feed count for adaptor to know which array position to look at and retrieve data from.
//Each array position i.e. [1] represents a HorizontalListview and its related articles
}
}
2) addHorzListView method, used to create HorizontalListView and apply adaptor
//Method used to dynamically add HorizontalListViews
public void addHorzListView(int count){
LinearLayout mainLayout = (LinearLayout) findViewById(R.id.main_layout);
View view = getLayoutInflater().inflate(R.layout.listview, mainLayout,false);
//Set lists header name
TextView header = (TextView) view.findViewById(R.id.header);
header.setText(feedTitle.get(count));
//Create individual listview
HorizontalListView listview = (HorizontalListView) view.findViewById(R.id.listviewReuse);
listview.setAdapter(mAdapter);
//add listview to array list
listviewList.add(listview);
mainLayout.addView(view, count);
}
3) Baseadaptor itself:
private BaseAdapter mAdapter = new BaseAdapter() {
private OnClickListener mOnButtonClicked = new OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(HorizontalListViewDemo.this);
builder.setMessage("hello from " + v);
builder.setPositiveButton("Cool", null);
builder.show();
}
};
#Override
public int getCount() {
return noOfArticles.length;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
//Each listview is populated with data here
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View retval = LayoutInflater.from(parent.getContext()).inflate(R.layout.viewitem, null);
TextView title = (TextView) retval.findViewById(R.id.title);
title.setText(getArticleTitle(position));
new DownloadImageTask((ImageView) retval.findViewById(R.id.ImageView01)) .execute(getArticleImage(position));
Button button = (Button) retval.findViewById(R.id.clickbutton);
button.setOnClickListener(mOnButtonClicked);
return retval;
}
};
The adapter mAdapter is currently displaying the articles from the last HorizontalListView that calls it.
Currently I am using the same BaseAdaptor for each ListView as I figured it populated the listview as soon as its called but i looks as though a BaseAdaptor can only be called once, I really dont know.
I want to dynamically populate feeds though without having to create a new Adaptor manually for each HorizontalListView.
Any help would be much appreciated.
So...you got the same info in 4 listview, right? In that case you only need oneAdapter populating 4 listview.
An adapter just provide the views which are visible in that moment to the listview (if it is implemented in the right way) so you can reuse the adapter if the info contained is the same.
I'm following the example on the android tutorial about the GridView, but instead of showing image, i want to just simple show some text using a TextView. it turns out seems to be harder than i thought. it might seems like this is totally unnecessary and it doesn't have a valid use case, but i'm trying this out to just get myself familiar with the sdk.
so my code is pretty much the same as the GridView example in http://developer.android.com/guide/tutorials/views/hello-gridview.html, but instead of using a ImageAdapter, i created a dummy adapter like following:
public class MyAdapter extends BaseAdapter {
private Context context;
private String[] texts = {"aaa", "bbb", "ccc", "ddd", "eee", "fff", "eee", "hhh", "iii"};
public MyAdapter(Context context) {
this.context = context;
}
public int getCount() {
return 9;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv;
if (convertView == null) {
tv = new TextView(context);
tv.setLayoutParams(new GridView.LayoutParams(85, 85));
}
else {
tv = (TextView) convertView;
}
tv.setText(texts[position]);
return tv;
}
}
it all seems valid to me, but running this gives me nothing on the screen. and there's no error message. there are some selectable/clickable (invisible) blocks if i click them, but the text is obvious not shown. i wonder is my layout doesn't have the android:text causing this problem? or anything else?
any feedback will be appreciated and thanks for your help!
I am not sure what could be causing your problem. I followed the step by step instructions on the page that you linked to to set up "Hello, GridView", and used your code and was able to see the text.
The only things I changed was rather than creating a class for ImageAdapter I used your MyAdapter. In the activity HelloGridView.java onCreate I used "MyAdapter" rather than "ImageAdapter". I didn't change the layout at all.
Here is a Screenshot of what I get when running your code.
I see GridView so I'm almost assuming that this is similar to SWT?
If so you need to show the relationship between your view and the ViewGroup parent
I don't think your getItem implementation is correct. Top of my head it should be
return texts[position];