Reputation: 1034
I am in the process of making my first android app, and I am having a problem.
I am trying to make it so that, if a person clicks on a item in my listview, it then changes the XML view for it. In my listNotes activity, I have created a Int variable named itemNumber, and set it to the content of -10. I then have a onclick event for the listView item Rows, and in there, I set it so that on a onClick event, itemNumber gets set to the the position of the item that was clicked.
But I need to make it so that, in my custom adapter, if the itemNumber = -10, it runs as default, but if the itemNumber is not = to -10, it only changes the XML view for the item the user clicked on (the position is stored in itemnumber.
I have tried using if statements, and methods, in the custom adapter, but I get a host of errors with them. Can anyone please tell me which way I should do this, as its been annoying me for 2 days now.
Here is the code:
public class ListNotesActivity extends Activity {
public ArrayList <Note> notes = new ArrayList<Note>();
private ListView notesListView;
private int editingNoteId = -1;
public int itemNumberId = -10;
int itemListLayout = R.layout.item_list;
int itemListOnCLickLayout = R.layout.item_list_onclick;
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
notes.remove(info.position);
populateList(itemListLayout, itemNumberId);
return true;
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_CANCELED){
return;
}
if (resultCode == EditNotesActivity.RESULT_DELETE){
notes.remove(editingNoteId);
editingNoteId = -1;
populateList(itemListLayout, itemNumberId);
}
Serializable extra = data.getSerializableExtra("Note");
if (extra != null){
Note newNote = (Note)extra;
if (editingNoteId > -1){
notes.set(editingNoteId, newNote);
editingNoteId = -1;
}
else {
notes.add(0,newNote);
};
populateList(itemListLayout, itemNumberId);
}
}
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_notes);
notesListView = (ListView)findViewById(R.id.notesListView);
notesListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView adapterView, View view, int itemNumber, long id) {
/* Intent editNoteIntent = new Intent(view.getContext(), EditNotesActivity.class);
editNoteIntent.putExtra("Note", notes.get(itemNumber));
startActivityForResult(editNoteIntent, 1);
*/
//editingNoteId = itemNumber;
itemNumberId = itemNumber;
populateList(itemListOnCLickLayout ,itemNumberId);
itemNumberId = -10;
}
});
registerForContextMenu(notesListView);
notes.add(0, new Note("1 Note", "blah blah", new Date()));
notes.add(0, new Note("2 Note", "blah blah", new Date()));
notes.add(0, new Note("3 Note", "blah blah", new Date()));
notes.add(0, new Note("4 Note", "blah blah", new Date()));
notes.add(0, new Note("5 Note", "blah blah", new Date()));
notes.add(0, new Note("6 Note", "blah blah", new Date()));
notes.add(0, new Note("7 Note", "blah blah", new Date()));
notes.add(0, new Note("This should display first", "This should display first!!!!", new Date()));
populateList(itemListLayout, itemNumberId);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.list_notes, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Intent editNoteIntent = new Intent (this, EditNotesActivity.class);
startActivityForResult(editNoteIntent, 1);
return true;
}
public void populateList(int itemRowLayout, int itemNumberId) {
CustomListAdapter customAdapter = new CustomListAdapter(this, itemRowLayout, itemNumberId, notes);
notesListView.setAdapter(customAdapter);
}
CustomAdapter:
public class CustomListAdapter extends ArrayAdapter {
Context mContext;
ArrayList<Note> notesR;
int itemRowLayout;
int itemNumber;
public CustomListAdapter (Context context, int itemRowXML, int itemNumberId, ArrayList notes) {
super(context, itemRowXML, itemNumberId, notes);
mContext = context;
notesR = notes;
itemRowLayout = itemRowXML;
itemNumber = itemNumberId;
}
@Override
public int getCount() {
return notesR.size();
}
@Override
public Object getItem(int position) {
return notesR.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
// This method is called to draw each row of the list
@Override
public View getView(int position, View convertView, final ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater inflater;
inflater = LayoutInflater.from(parent.getContext());
v = inflater.inflate(itemRowLayout, null);
}
final Note noteModel = notesR.get(position);
DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
Date myNotesDate = noteModel.getDate();
String noteDate = dateFormat.format(myNotesDate);
TextView content = (TextView) v.findViewById(R.id.content);
content.setText(noteModel.getNote());
TextView title = (TextView) v.findViewById(R.id.title);
title.setText(noteModel.getTitle());
TextView date = (TextView) v.findViewById(R.id.date);
date.setText("" + getDate(noteDate));
return v;
}
String monthName;
String dateWithMonthName;
String dayEnding;
// METHOD
public String getDate(String noteDate){
DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
Date newDate = new Date();
String testDateValue = dateFormat.format(newDate);
String[] testDateSplit = testDateValue.split("-");
String testSplitDay = testDateSplit[0];
String testSplitMonth = testDateSplit[1];
String testSplitYear = testDateSplit[2];
int testYearInt = Integer.parseInt(testSplitYear);
String[] noteDateSplit = noteDate.split("-");
String noteSplitDay = noteDateSplit[0];
String noteSplitMonth = noteDateSplit[1];
String noteSplitYear = noteDateSplit[2];
int noteYearInt = Integer.parseInt(noteSplitYear);
int intSplitDay = Integer.parseInt(noteSplitDay);
int intSplitMonth = Integer.parseInt(noteSplitMonth);
if ((intSplitDay == 1) || (intSplitDay == 21) || (intSplitDay == 31)){
dayEnding = "st ";
}
else if ((intSplitDay == 2) || (intSplitDay == 22)){
dayEnding = "nd ";
}
else if ((intSplitDay == 3) || (intSplitDay == 23)){
dayEnding = "rd ";
}
else if ((intSplitDay >= 4) && (intSplitDay <= 20) || (intSplitDay >= 24) && (intSplitDay <= 30) ){
dayEnding = "th ";
}
//Month
if (intSplitMonth == 1){
monthName = "January";
}
else if (intSplitMonth == 2){
monthName = "February";
}
else if (intSplitMonth == 3){
monthName = "March";
}
else if (intSplitMonth == 4){
monthName = "April";
}
else if (intSplitMonth == 5){
monthName = "May";
}
else if (intSplitMonth == 6){
monthName = "June";
}
else if (intSplitMonth == 7){
monthName = "July";
}
else if (intSplitMonth == 8){
monthName = "August";
}
else if (intSplitMonth == 9){
monthName = "September";
}
else if (intSplitMonth == 10){
monthName = "October";
}
else if (intSplitMonth == 11){
monthName = "November";
}
else if (intSplitMonth == 12){
monthName = "December";
}
if (noteYearInt != testYearInt){
dateWithMonthName = noteSplitDay + dayEnding + monthName + " " + noteSplitYear;
}
else if (noteYearInt == testYearInt){
dateWithMonthName = noteSplitDay + dayEnding + monthName;
}
return dateWithMonthName ;
}
Does anyone know how I would get it to change the XML layout file for the listView item thats clicked on, seeing the above code?.
EDIT 1:
Here is my adapter now:
public class CustomTwoRowAdapter extends ArrayAdapter {
public static final int INITIAL_TYPE = 0;
public static final int CHANGE_TYPE = 1;
private List<Note> notesR;
private LayoutInflater mInflater;
private ArrayList<Integer> mChangedRows = new ArrayList<Integer>();
public CustomTwoRowAdapter(Context context, int id, ArrayList<Note> notes) {
super(context, id, notes);
notesR = notes;
mInflater = LayoutInflater.from(context);
}
public void changeRowLayout(int rowPosition) {
if (mChangedRows.contains(rowPosition)) {
mChangedRows.remove(mChangedRows.indexOf(rowPosition));
} else {
mChangedRows.add(rowPosition);
}
notifyDataSetChanged();
}
@Override
public int getItemViewType(int position) {
if (mChangedRows.size() == 0 || !mChangedRows.contains(position)) {
return INITIAL_TYPE;
} else {
return CHANGE_TYPE;
}
}
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public int getCount() {
return notesR.size();
}
@Override
public Object getItem(int position) {
return notesR.get(position);
}
@Override
public long getItemId(int arg0) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
int type = getItemViewType(position);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case INITIAL_TYPE:
convertView = mInflater.inflate(
R.layout.item_list, parent, false);
holder.mText = (TextView) convertView
.findViewById(R.id.title);
break;
case CHANGE_TYPE:
convertView = mInflater.inflate(
R.layout.item_list_onclick, parent, false);
holder.mText = (TextView) convertView
.findViewById(R.id.title);
holder.mPressMe = (Button) convertView
.findViewById(R.id.date);
holder.mCheckMe = (CheckBox) convertView
.findViewById(R.id.content);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
switch (type) {
case INITIAL_TYPE:
holder.mText.setText(getItem(position));
break;
case CHANGE_TYPE:
holder.mText.setText(getItem(position));
break;
}
return convertView;
}
static class ViewHolder {
TextView mText;
Button mPressMe;
CheckBox mCheckMe;
}
}
My problem is, in to the adapter i parse the ArrayList "notes", which is made of my "Note" Objects.
in the getItem method, it only works if i set the return type to "Object", but then in the else statement, where it has "getItem(position)" it gives a error saying "can not resolve method "setText(java.lang.object".
Do you have any idea how i can get the code to work with my ArrayList of objects?.
Thanks again for all your help. Cheers Corey
Upvotes: 0
Views: 281
Reputation: 87064
That is not the right way to change the row layout. You need to use the getItemViewType()
and getViewTypeCount()
methods of the adapter to let it know that there could be two types of rows. You would then update(when the user clicks one of the rows) some sort of list with the position of the clicked row and let the adapter(through the methods above) know about this so it can update the rows:
public static final int INITIAL_TYPE = 0;
public static final int CHANGE_TYPE = 1;
private ArrayList<Integer> mChangedRows = new ArrayList<Integer>();
public void changeRowLayout(int rowPosition) {
if (mChangedRows.contains(rowPosition)) {
mChangedRows.remove(mChangedRows.indexOf(rowPosition));
} else {
mChangedRows.add(rowPosition);
}
notifyDataSetChanged();
}
@Override
public int getItemViewType(int position) {
if (mChangedRows.size() == 0 || !mChangedRows.contains(position)) {
return INITIAL_TYPE;
} else {
return CHANGE_TYPE;
}
}
@Override
public int getViewTypeCount() {
return 2;
}
You can see the full sample code here.
My example is a very simple one, in the getView()
method you would do:
//...
else {
holder = (ViewHolder) convertView.getTag();
}
Note data = (Note) getItem(position);
switch (type) {
case INITIAL_TYPE:
// for the initial row extract whatever you want from the data object
// like for example:
holder.mText.setText(data.getNote());
break;
case CHANGE_TYPE:
// for the second row type extract whatever you want from the data object
// like for example:
holder.mText.setText(data.getNote());
break;
}
return convertView;
Upvotes: 1