Android BaseAdapter : position not really the position? - android

When my list view using a BaseAdapter goes off the screen, each row no longer maintains a consecutive position. I don't know how else to explain it other than this.
If my BA/LV shows 4 items on the screen, and I add a view that displays a TextView of each row, it shows 0,1,2,3 for the row numbers (which is correct). But as soon as I scroll the list down to the bottom 4 items (items 5-8) it then shows those as 4,5,0,1?? Why?
EDIT:
I did discover that if I change
rv = (RowView) convertView;
to
rv = new RowView(mContext,(cursor.getString(2)),
(cursor.getString(5)),
cursor.getString(cursor.getColumnIndex(DBHelper.KEY_IMAGEFILENAME)),
cursor.getString(cursor.getColumnIndex(DBHelper.KEY_CITY)),position);
it works, but then it is not re-using the code. So, I guess I am on the right track. I did try some convenience methods, but that did not help me too much because I needed to set those values before the Constructor fired off. Do I need to create a new method and fire that at the end? Such as addRow method? This also causes it to scroll VERY Slow.
#Override
public void onCreate(Bundle bundle)
{
super.onCreate(bundle);
//setContentView(R.layout.findlist);
//getListView().setEmptyView(findViewById(R.id.empty));
mDbHelper = new DBHelper(this);
mDbHelper.open();
cursor = mDbHelper.fetchAllLocations();
startManagingCursor(cursor);
mAdapter = new myListAdapter(this);
setListAdapter(mAdapter);
}
public class myListAdapter extends BaseAdapter {
public String testing;
public myListAdapter(Context c) {
mContext = c;
// TODO Auto-generated constructor stub
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return cursor.getCount();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
cursor.moveToPosition(position);
RowView rv;
if (convertView == null) {
rv = new RowView(mContext,(cursor.getString(2)),
(cursor.getString(5)),
cursor.getString(cursor.getColumnIndex(DBHelper.KEY_IMAGEFILENAME)),
cursor.getString(cursor.getColumnIndex(DBHelper.KEY_CITY)),position);
} else {
rv = (RowView) convertView;
try {
// I KNOW THIS SECTION IS NOT RIGHT, BUT I HAVE BEEN MESSING IN HERE
rv.setAddress(cursor.getString(2));
rv.setCity(cursor.getString(5));
rv.setFocusable(true);
rv.setClickable(true); }
catch (Exception e) {
rv = (RowView) convertView;
rv.setAddress(cursor.getString(2));
rv.setCity(cursor.getString(5));
rv.setFocusable(true);
rv.setClickable(true);
Toast mToast;
mToast = Toast.makeText(FindList.this, "Error :" + e.toString() ,
Toast.LENGTH_LONG);
mToast.show();
}
}
return rv;
}
public void addItems() {
//String[] from = new String[] { DBHelper.KEY_BUSINESSNAME, DBHelper.KEY_ADDRESS, DBHelper.KEY_CITY, DBHelper.KEY_GPSLONG, DBHelper.KEY_GPSLAT, DBHelper.KEY_IMAGEFILENAME + ""};
// create array of values of widgits
//to = new int[] { R.id.businessname, R.id.address, R.id.city, R.id.gpslong, R.id.gpslat, R.id.preview};
// Now create an array adapter and set it to display using our row from notes_row.xml
}
}
private class RowView extends LinearLayout {
private TextView mAddress;
private TextView mCity;
public ImageView mArrow;
public ImageView mPicture;
public String mPathName;
public String mDateTime;
public RowView(Context context, String title, String words, String pathName, String city, int position) {
super(context);
this.setOrientation(HORIZONTAL);
this.setVerticalGravity(16); //CENTER_VERTICAL
// Here we build the child views in code. They could also have
// been specified in an XML file.
//DISPLAY DELETE BUTTON
Button mButton = new Button(context);
mButton.setFocusable(false);
mButton.setId(position);
mButton.setBackgroundResource(R.drawable.delete3);
addView(mButton, new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
TextView mTitle;
mTitle = new TextView(context);
mTitle.setText(Integer.toString(position));
addView(mTitle, new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
this.setOrientation(HORIZONTAL);
try {
Bitmap bm = Bitmap.createScaledBitmap(BitmapFactory.decodeFile(cursor.getString(cursor.getColumnIndex(DBHelper.KEY_IMAGEFILENAME))),100, 100, true);
mPicture = new ImageView(context);
mPicture.setImageBitmap(bm);
} catch (Exception e) {
mPicture = new ImageView(context);
mPicture.setImageResource(R.drawable.noimage);
}
addView(mPicture, new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
mArrow = new ImageView(context);
mArrow.setBackgroundResource(R.drawable.arrowleft3);
addView(mArrow, new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
currentPosition = position;
Button button = (Button)findViewById(position);
button.setOnClickListener(mCorkyListener);
}

When using the convertView, you are given a view which has been previously used but which is not displayed anymore. You should take care of resetting ALL its attributes with the value of the current item. Otherwise, all the values you have set in the RowView constructor will be kept with the value you gave to this view the first time you created it.
To better understand ListViews, you have to understand that it only uses a limited set of RowViews, just the number that is enough to fill the display and a few more that will be filled with your data just before having to display them.

Related

Removing Listview row on Button Click

I have a Listview that gets fed questions and their corresponding choices as such:
The following constructor gets all the necessary information to feed the Listview. All string values are in Arraylists.
public BaseQuestionAdapter(Activity a, ArrayList<String> b, ArrayList<String> c, ArrayList<String> d, ArrayList<String> e) {
activity = a;
this.questionTitleArray = b;
this.choicesArray = c;
this.questionIdArray = d;
this.userIdArray = e;
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
Each row will hold a single question title and a variable number of choices. Dynamically created buttons will instantiate the choices and on each question title position the buttons will start generating. Like so, the following is the getView method in the BaseAdapter:
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
vi = inflater.inflate(R.layout.question_layout, null);
LinearLayout questionContainer = (LinearLayout) vi.findViewById(R.id.question_container);
LinearLayout choicesContainer = (LinearLayout) vi.findViewById(R.id.choices_container);
ViewGroup answersContainerParent = (ViewGroup) choicesContainer.getParent();
if (answersContainerParent != null)
answersContainerParent.removeView(choicesContainer);
JSONArray choicesJSONArray = new JSONArray(choicesArray);
try {
String bhb = choicesJSONArray.get(position).toString();
jsnArray = new JSONArray(bhb);
} catch (JSONException e) {
e.printStackTrace();
}
for (int answersArrayIterator = 0; answersArrayIterator < jsnArray.length(); answersArrayIterator++) {
try {
final Button choiceButton = new Button(activity);
choiceButton.setId(buttonId);
String questionId = questionIdArray.get(position).toString();
choiceButton.setTag(questionId);
choiceButton.setTag(position);
ViewGroup layout = (ViewGroup) choiceButton.getParent();
if (layout != null)
layout.removeView(choiceButton);
choiceButton.setText(jsnArray.get(answersArrayIterator).toString());
choiceButton.setTextSize(16);
choiceButton.setBackgroundResource(R.drawable.question_button_template_style);
choiceButton.setGravity(Gravity.CENTER);
choiceButton.setWidth(270);
choiceButton.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
String choiceString = choiceButton.getText().toString();
Object questionId = choiceButton.getTag();
setDataToBeSent(userId, questionId, choiceString);
Integer index = (Integer) v.getTag();
System.out.println("SATURN ASCENDS: " + index);
choicesArray.remove(index);
notifyDataSetChanged();
new HttpAsyncTask2().execute();
return false;
}
});
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.setMargins(10, 10, 10, 10);
choiceButton.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
choiceButton.setLayoutParams(params);
buttonId++;
choicesContainer.addView(choiceButton);
} catch (JSONException e) {
e.printStackTrace();
}
}
TextView questionTitleET = (TextView) vi.findViewById(R.id.question_title);
String questionTitle = questionTitleArray.get(position).toString();
questionTitleET.setText(questionTitle);
ViewGroup questionTitleETParent = (ViewGroup) questionTitleET.getParent();
if (questionTitleETParent != null)
questionTitleETParent.removeView(questionTitleET);
questionContainer.addView(questionTitleET);
questionContainer.addView(choicesContainer);
return vi;
}
What I'm trying to achieve is to remove the parent Listview row whenever a button is LonClicked. I'm trying to achieve this by setting an OnLongClickListener on every button created. Like so:
choiceButton.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
Integer index = (Integer) v.getTag();
System.out.println("SATURN ASCENDS: " + index);
choicesArray.remove(index);
notifyDataSetChanged();
return false;
}
});
Problem is that I don't know what to reference precisely in order for that to happen. Don't know whether its the choicesArray or any of the other resources I'm receiving. Currently when I long click on a button nothing happens. Any clue as to where I'm going wrong? Thank you.
As Luksprog said on the comment, you need to remove the items from the container which is referenced in the getCount(). However I would also like to offer an improvement. Instead of using four different lists of Strings, use an Object which holds each of those string.
Eg.
public class MyClass {
public String questionTitle;
public String choice;
public String questionId;
public String userId;
}
After you have this class you can use a single list, which contains your object. This way you won't be confused as to which list items should be removed in order for the list to change.

custom adapter do not refresh the listview for onclicklistener in android

I delete database entry using onclicklistener but it is not refreshing the listview. how can i refresh this listview?
This is main class for listview:
public class AFragment extends Fragment implements OnItemClickListener {
protected static final String file_name ="user";
ListView list;
Database entry;
View v;
String values[];
MySimpleArrayAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
SharedPreferences settings = getActivity().getSharedPreferences(file_name, 0);
String name = settings.getString("name", null);
entry = new Database(getActivity());
entry.open();
values=entry.planlist(name);
entry.close();
if(values.length>0){
v = inflater.inflate(R.layout.activity_afragment, container,false);
adapter = new MySimpleArrayAdapter(getActivity(), values);
list=(ListView)v.findViewById(R.id.list);
list.setAdapter(adapter);
adapter.notifyDataSetChanged();
list.setOnItemClickListener(this);
}else{
v = inflater.inflate(R.layout.activity_my_tabs_listener, container,false);
}
// Toast.makeText(getActivity(),String.valueOf(values.length), Toast.LENGTH_LONG).show();
return v;
}
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// TODO Auto-generated method stub
Intent i = new Intent(getActivity(),Details.class);
i.putExtra("sub", values[arg2]);
startActivity(i);
Toast.makeText(getActivity(), "clicked", Toast.LENGTH_SHORT).show();
}
}
Here i use onclicklistener to delete data from database but it is not refreshing:
public class MySimpleArrayAdapter extends ArrayAdapter<String> {
private final Context context;
private final String[] values;
public Business aFragment = new Business();
int mypos =0;
ViewHolder holder;
View row;
public MySimpleArrayAdapter(Context context, String[] values) {
super(context,R.layout.activity_my_simple_array_adapter, values);
this.context = context;
this.values = values;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
mypos = position;
row = convertView;
holder = new ViewHolder();
if (row == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(R.layout.activity_my_simple_array_adapter, parent, false);
TextView textView = (TextView) row.findViewById(R.id.text);
Button btn = (Button) row.findViewById(R.id.button1);
holder.tv = textView;
holder.btn = btn;
row.setTag(holder);
}else{
holder = (ViewHolder)row.getTag();
}
holder.tv.setText(values[position]);
final int id = position;
holder.btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Database entry = new Database(context);
entry.open();
entry.delete(values[id]);
entry.close();
// Toast.makeText(getContext(), String.valueOf(id), Toast.LENGTH_LONG).show();
}
});
return row;
}
static class ViewHolder{
TextView tv;
Button btn;
}
}
as anil said, you should put notifyDataSetChanged(); inside the onClickListener
this basically tells the adapter to render the list again and will call getView() again for every visible item in the list, if your code crashes, you should check two things:
first - debug the program and check that the new data fits what you want, in your case, check that the entry was deleted properly.
second - debug the getView method, step through each call and see what gives you the crash.
in your case the problem is that you are only updating the database, but in fact your listview data is taken from the values[] array which is not updated after you delete the database entry, you should create a function for updating it.
Put adapter.notifyDataSetChanged(); on click of ListView
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Database entry = new Database(context);
entry.open();
entry.delete(values[id]);
entry.close();
adapter.notifyDataSetChanged();
// Toast.makeText(getContext(), String.valueOf(id), Toast.LENGTH_LONG).show();
}
If you do lots of adding and deleting to the list I think you should do the things below.
You should use ArrayList<String> instead of simple String[] so that you can easily delete. Database deletion do not effect the list directly unless you use Loaders
After you delete and item from the list, you should call notifyDataSetChanged() to the adapter. If you do not call this method, the list wont be updated.
adapter.notifyDataSetChanged();
you are removing it from the database but you are not removing it from the dataset that fills up your ListView. The simplest thing you can do is to change values from array to ArrayList, and since you are using an ArrayAdapter, you can call remove(int position). You need a List<T> of objects otherwise remove will throws an exception.
You can do one thing.
Firstly create a method called myAdapter().
In this put your creation of adapter code,so you can create new adapter for loading new data by simply calling myAdapter() method.
Whenever there should be modification in your ListView just called the following code,
listview.invalidate();
Then simply call the myAdapter().
That's it.Hope this is useful to you..:)

Android :I can't get value in dialog while binding dynamic textviews through base adapter class

I got exception in dialog while binding dynamic textviews through base adapter class
i can get the dialog box but it doesnot bind the textview value hell.. plz help me.. wat i did wrong :)
Train_Origin_Destination.java
public void loadAutocomplete1(String strCmdTrain) {
c.moveToFirst();
if (c.isAfterLast() == false) {
do {
listFrom1 = new ArrayList<String>(Arrays.asList(strComments));
listTo1 = new ArrayList<String>(Arrays.asList(strComments));
listFrom1.removeAll(Collections.singleton(null));
HashMap<String, String> map = new HashMap<String, String>();
map.put(KEY_Start, "Hello");
listData.add(map);
Log.e("map", map.toString());
Log.e("list4", listData.toString());
customAdapter = new MyCustomAdapter2(
Train_Origin_Destination.this, listData);
lvTrainTime1.setAdapter(customAdapter);
} while (c.moveToNext());
}
onButtonClick Event
public void onClick(View arg0) {
Log.d("Dialog", "Dialog");
dialog = new Dialog(context1);
//dialog.setContentView(R.layout.traintimings_dialog);
//dialog.getWindow().getAttributes().windowAnimations = R.style.Animations_SmileWindow;
dialog.setTitle("Train Timings");
//dialog.setContentView(R.id.lvTrainTimings1);
if (chkSunday.isChecked()) {
if (Area_Index < Area_Index1) {
Log.d("Sunday", "Sunday");
} else if (Area_Index > Area_Index1) {
Log.d("SundayReverse", "SundayReverse");
}
} else {
if (Area_Index < Area_Index1) {
Log.d("Normal", "Normal");
if (strSpSelectedItem.contentEquals("Beach - Tambaram")) {
int id = Area_Index + 1;
int id1 = Area_Index1 + 1;
/*
* strCmdTrainFrom =
* "Beach_Thirumalpur_WeekD ays where _id='" + id +
* "' or _id='" + id1 + "'";
*/
strCmdTrainFrom = "Beach_Thirumalpur_WeekDays where _id='"
+ id + "'";
loadAutocomplete1(strCmdTrainFrom);
}
} else if (Area_Index > Area_Index1) {
Log.d("NormalReverse", "NormalReverse");
}
}
Log.d("DialogEndB4", listData.toString());
dialog.show();
Log.d("DialogEnd", "DialogEnd");
}
MyCustomAdapter2.java
public class MyCustomAdapter2 extends BaseAdapter {
private String[] strKeys;
private ArrayList<HashMap<String, String>> alData;
private Context context;
TextView txtBusNo, txtBusVia, txtBusServiceType, txtBusJourneyTime;
TextView[] tvStart;
ListView lvTrainTime1;
View rowView2;
public MyCustomAdapter2(Context context,
ArrayList<HashMap<String, String>> listData) {
super();
Log.d("Custom", "Custom");
this.alData = listData;
this.context = context;
Log.d("alData", alData.toString());
Log.d("Custom1", "Custom1");
}
public int getCount() {
// TODO Auto-generated method stub
Log.d("alData.size()", String.valueOf(alData.size()));
return alData.size();
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
Log.d("View", "View");
rowView2 = convertView;
if (rowView2 == null) {
Log.d("View1", "View1");
Train_Origin_Destination trDetails = new Train_Origin_Destination();
// Inflate the layout, list_view.xml, in each row.
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(context.LAYOUT_INFLATER_SERVICE);
Log.d("View2", "View2");
rowView2 = inflater
.inflate(R.layout.textview_autofrom, null, false);
}
txtBusNo = (TextView) rowView2.findViewById(R.id.idTvAutoFrom1);
Log.d("View3", "View3");
HashMap<String, String> hashmap = new HashMap<String, String>();
txtBusNo.setText("Bus No : Hello");
Log.d("View30", "View30");
Log.d("View5", String.valueOf(rowView2));
} else {
}
return rowView2;
}
Well what you do is add lvTrainTime to the scr ScrollView than use it as a content view for the dialog. Maybe what you want to do is setContentView(scr);? If you do it this way scr will play the role of a container of the view. So basically you need to set the container as a content view.
EDIT - clarifications:
What I meant was that in your loadAutocomplete1 method you create a ScrollView scr = new ScrollView(this);. Later in the same method, after the loop, you add a view to that scroll view - scr.addView(lvTrainTime); and then set the content view of the dialog to be the mentioned view - dialog.setContentView(lvTrainTime);. You cant do that because scr and dialog are different controls and one view (lvTrainTime) can't have two parents.
So, instead of setting the content view to be that view - lvTrainTime - I meant that you should set it's parent(container) as a content view. By the time I answered I thought it was scr that should be set as content view but I just saw that you actually put the scr in a tableLayout - tablelayout.addView(scr, new TableLayout.LayoutParams(LayoutParams.MATCH_PARENT, 50));. So your current situation is that lvTrainTime is inside scr and scr is inside tableLayout. So try dialog.setContentView(tableLayout); instead. In addition I am not sure what happens when you set the content view of the dialog twice so maybe you should try without dialog.setContentView(R.layout.traintimings_dialog); too.

Updating a List View

I've been stuck with this for a long while and it's really frustrating. Basically the app starts off with a ListView containing Movie Titles, their Gross, and Year.
The user then can add a new movie, gross, and year using a different activity from the menu. The values are then returned back to the first activity and is placed at the bottom of the list.
This is where my problem begins. The first problem I had is that the app Force Closes when it's about to display the new item. Now, it doesn't want to display at all. Here's the Code:
public class Lab7_084106 extends ListActivity {
private SampleCustomAdapter adapter;
private ArrayList<MyMovies> movieList;
public static boolean Flag = false;
#SuppressWarnings("null")
#Override
public void onCreate(Bundle savedInstanceState) {
//create stuff
super.onCreate(savedInstanceState);
movieList = new ArrayList<MyMovies>();
Intent data = getIntent();
//Flag = data.getStringExtra("Flag");
String[] oldMovieList = getResources().getStringArray(R.array.movieArray);
String[] oldGrossList = getResources().getStringArray(R.array.worldwideGross);
String[] oldYearList = getResources().getStringArray(R.array.yearArray);
//if there's no new movie to display
if(!Flag){
for (int i = 0; i < oldMovieList.length; i++) {
MyMovies newMovie = new MyMovies();
newMovie.setMovie(oldMovieList[i] + "NEW");
newMovie.setGross(oldGrossList[i]);
newMovie.setYear(oldYearList[i]);
movieList.add(newMovie);
}
//adapter = new SampleCustomAdapter(movieList);
//setContentView(R.layout.row);
//setListAdapter(adapter);
}
else{
Toast.makeText(getApplicationContext(), "Else Entered", Toast.LENGTH_SHORT).show();
int newLength = 50; //oldMovieList.length + 1;
//create new array to store the new value
String[] newMovieArray = new String[newLength];
String[] newGrossArray = new String[newLength];
String[] newYearArray = new String[newLength];
//populate the new list with the old one plus the new one
for (int i = 0; i < newLength; i++) {
if( i != newLength - 1){
newMovieArray[i] = oldMovieList[i];
newGrossArray[i] = oldGrossList[i];
newYearArray[i] = oldYearList[i];
}
else{
newMovieArray[i] = data.getStringExtra("Title");
newGrossArray[i] = data.getStringExtra("Gross");
newYearArray[i] = data.getStringExtra("Year");
}
}
//populate the old one using the new list
for (int i = 0; i < newLength; i++) {
oldMovieList[i] = newMovieArray[i];
oldGrossList[i] = newGrossArray[i];
oldYearList[i] = newYearArray[i];
}
//display stuff
for (int i = 0; i < newLength; i++) {
MyMovies newMovie = new MyMovies();
newMovie.setMovie(oldMovieList[i]);
newMovie.setGross(oldGrossList[i]);
newMovie.setYear(oldYearList[i]);
movieList.add(newMovie);
}
//adapter = new SampleCustomAdapter(movieList);
//setListAdapter(adapter);
}
adapter = new SampleCustomAdapter(movieList);
setListAdapter(adapter);
ListView lv = getListView();
lv.setTextFilterEnabled(true);
//set stuff such that Page2 sends back a result to page 1
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView t = (TextView) view.findViewById(R.id.title);
String name = (String) t.getText();
Toast.makeText(getApplicationContext(), name, Toast.LENGTH_SHORT).show();
}
});
}
private class SampleCustomAdapter extends BaseAdapter {
private ArrayList<MyMovies> internalList;
String[] oldMovieList = getResources().getStringArray(R.array.movieArray);
String[] oldGrossList = getResources().getStringArray(R.array.worldwideGross);
String[] oldYearList = getResources().getStringArray(R.array.yearArray);
private ArrayList<MyMovies> GetSearchResults(){
ArrayList<MyMovies> results = new ArrayList<MyMovies>();
// make sure the arrays have the same length
for (int i = 0; i < oldMovieList.length; i++) {
MyMovies sr = new MyMovies();
sr.setMovie(oldMovieList[i]);
sr.setGross(oldGrossList[i]);
sr.setYear(oldYearList[i]);
results.add(sr);
}
return results;
}
public SampleCustomAdapter(ArrayList<MyMovies> contacts){
internalList = contacts;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return internalList.size();
}
#Override
public Object getItem(int index) {
// TODO Auto-generated method stub
return internalList.get(index);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// NOTE: you can only do this if you have access to the Activity object
// which is why this is an inner class
LayoutInflater inflater = getLayoutInflater();
View view;
//System.out.println(parent.getClass().getName());
//System.out.println(position);
if (convertView==null){
view = inflater.inflate(R.layout.row, null);
}
else{
view = convertView;
}
// extract the views to be populated
TextView movie = (TextView) view.findViewById(R.id.title);
TextView gross = (TextView) view.findViewById(R.id.gross);
TextView date = (TextView) view.findViewById(R.id.date);
// extract the object that will fill these
MyMovies movies = GetSearchResults().get(position);
//MyMovies movies = internalList.get(position);
movie.setText(movies.getMovie());
gross.setText(movies.getGross());
date.setText(movies.getYear());
// return the view
return view;
}
}
//menu lawl
#Override
public boolean onCreateOptionsMenu(Menu menu){
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menupage1, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
//Handle item selection using item.getItemId()
switch(item.getItemId()){
case R.id.addMovie:
AddMovie();
break;
}
return true;
}
//end menu stuff lol
public void AddMovie(){
Intent intent2 = new Intent(this, com.Android.Lab7.addMovie.class);
startActivity(intent2);
finish();
}
}
The Flag Boolean variable basically tells if the user added a movie. If the user added a movie, it will enter the else statement and update from there. I'm really confused where to put this if-else statement.
I ran a few experiments with the GetSearchResult function of SampleCustomAdapter and found out that it directly affects the output of the ListView. I tried placing the if-else statement there but I ended up with a LOT of items in the ListView.
Using adapter.notifyDataSetChanged(); gives a NullPointerException error and points to where I placed it. So even if do something like:
MyMovies newMovie = new MyMovies();
newMovie.setMovie(data.getStringExtra("Title"));
newMovie.setGross(data.getStringExtra("Gross"));
newMovie.setYear(data.getStringExtra("Year"));
movieList.add(newMovie);
adapter.notifyDataSetChanged();
As the else block, it does not work. I think it has something to do with the fact that I'm getting my initial values from the string.xml resource folder and not via hardcode or user input.
This problem has been frustrating me ever since 2-3 days ago and help is really appreciated. Thanks.
you just have to notify the data set Changed on your adapter
movieList.add(newMovie);
adapter.notifyDataSetChanged();
the listview will be updated automatically
UPDATE
you can always use the following it'll work but I prefer notifying the adapter.
movieList.add(newMovie);
adapter = new SampleCustomAdapter(movieList);
setListAdapter(adapter);
you should use adapter.notifyDataSetChanged(). CheckThis Link

Android: HowTO delete last item of a list and the list

I have an activity which extends ListActivity. It has many things but amongst them it shows the articles the user has purchased with an adapter. Well I have a method that the user can delete the items from the list. The problem is when there is only one item. If I try to delete the last one the app crashes. Here is a it of my code:
public class Ventas extends ListActivity {
......
lv = getListView();
......
protected void confirmRemoval(final int arg2) {
// TODO Auto-generated method stub
AlertDialog alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle(getResources().getString(R.string.ventas));
alertDialog.setMessage(getResources().getString(R.string.confirmacion2));
alertDialog.setButton("Si",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
if(adapter2.mEvents.size()>=1){
adapter2.mEvents.remove(arg2);
} else {
//doesn't work
/*adapter2=null;
adapter2.notifyDataSetInvalidated();
lv.setVisibility(View.GONE);*/
}
}
});
alertDialog.setButton2("No", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
dialog.dismiss();
}
});
alertDialog.show();
}
here is the adapter and wrapper:
private class EventAdapter2 extends BaseAdapter {
public ArrayList<Articulo> mEvents = null;
public EventAdapter2(Context c, ArrayList<Articulo> clientes) {
mContext = c;
mEvents = clientes;
}
public int getCount() {
return mEvents.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
EventEntryView2 btv;
if (convertView == null) {
btv = new EventEntryView2(mContext, mEvents.get(position));
} else {
btv = (EventEntryView2) convertView;
String title1 = mEvents.get(position).getCantidad() + "";
if (title1 != null) {
btv.setText1Title(title1);
}
String title2 = mEvents.get(position).getDescripcion();
if (title2 != null) {
btv.setText2Title(title2);
}
String title3 = mEvents.get(position).getpVenta() + "0";
if (title3 != null) {
btv.setText3Title(title3);
}
String title4 = (mEvents.get(position).getCantidad() * mEvents
.get(position).getpVenta()) + "0";
if (title4 != null) {
btv.setText4Title(title4);
}
}
return btv;
}
private Context mContext;
}
private class EventEntryView2 extends LinearLayout {
private TextView text1;
private TextView text2;
private TextView text3;
private TextView text4;
private View inflatedView;
public EventEntryView2(Context context, Articulo resp) {
super(context);
this.setOrientation(VERTICAL);
inflatedView = View.inflate(context, R.layout.results, null);
text1 = (TextView) inflatedView.findViewById(R.id.textView1);
text2 = (TextView) inflatedView.findViewById(R.id.textView2);
text3 = (TextView) inflatedView.findViewById(R.id.textView3);
text4 = (TextView) inflatedView.findViewById(R.id.textView4);
String t = resp.getCantidad() + "";
text1.setText(t);
String t1 = resp.getDescripcion();
text2.setText(t1);
String t2 = resp.getpVenta() + "0";
text3.setText(t2);
String t3 = (resp.getCantidad() * resp.getpVenta()) + "0";
text4.setText(t3);
addView(inflatedView, new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
}
public void setText4Title(String title4) {
text4.setText(title4);
}
public void setText3Title(String title3) {
text3.setText(title3);
}
public void setText2Title(String title2) {
text2.setText(title2);
}
public void setText1Title(String title1) {
text1.setText(title1);
}
}
as you can see when I have only one item left I have tried to set adapter to null or adapter.notifyDataSetInvaliadted or even making the listview invisible, nothing works. What happens is when I click ok nothing changes then when I click a second time it all crashes
What I would like is the listView to disappear when the adapter is empty but I am now out of ideas, is it even possible?
Any ideas?
EDIT:
Thank you all for the answers but the problem was I was modifying the list from inside an inner anonymous class. It is actually pretty simple, create a method and call it from inside the dialog, once the array is empty the list disappears automatically:
protected void removeFromList(int arg2) {
adapter2.mEvents.remove(arg2);
adapter2.notifyDataSetChanged();
}
remove item from the arraylist which you add into the adapter and then call this method.
youradapter.notifyDataSetChanged();
and whatever you do for single item that was
adapter2 = null;
adapter2.notifyDataSetInavlidated();
this will obviously crash it because adapter2 object was null so how null object notify its data
Try calling lv.invalidate() after the remove() and see whether that makes any difference.
You should check in your adapter class if it is null then you should not fetch value from it......that's the main reason why you are getting exception as you are fetching the value from null variable.Put check there.
For setVisibility to Work:
You create your main.xml
Add to it a ListView
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/sherif.android.deedz"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView android:layout_width="match_parent"
android:layout_height="match_parent" android:id="#+id/myListView"
android:divider="#ffa500" android:dividerHeight="1px"
android:background="#drawable/somedrawable_xml"
android:choiceMode="singleChoice"></ListView>
</ListView>
Now you can make it GONE
If you want the whole details of this :
Check my answer

Categories

Resources