I'm learning android programming, following a book's examples, but I'm still a beginner in this field.
The aim of the book is to build a progressively more sophisticated "note taking" app, starting from a very simple one then each time adding features.
I got a working app that allows adding notes, deleting notes: each note added becomes an item in a listview, and has a title, a text, and some boolean flag like "idea", "todo" and "important". Adding notes having the "important" boolean flag set, makes an "important" icon visible.
Internally, notes are stored in a List (see code later).
Each note, tapping its listitem, can be also opened in a modal showing its properties, which has a button to delete the shown note. Pressing that delete button, the modal is dismissed, the note is deleted, and the item in the listview is removed.
This works.
Now I'm following the next step: adding a "flashing" animation for items (notes) with the "Important" flag set. Regular notes' items are not animated, but "important" ones are constantly "flashing" when they appear in the listview.
This works.
Removing the notes, one by one, still works, and each item is removed.
But, if I remove all notes, and the last one is flashing - this last note is effectively "removed" from the list - but the listview still shows (only) its animation!?!
But the flashing animation, showing the last note (deleted) title and text in the listitem, cannot be clicked... inspecting the code it is effectively gone fro the List, but not its flashing animation.
Btw, the book at this point doesn't cover deleting notes, and that's a feature I added on my own.
the modal showing the note has, as said a btnDelete, that works like this:
btnDelete.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View view) {
new AlertDialog.Builder(getContext())
.setMessage("Really delete this note?")
.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
//nothing
}
}
)
.setPositiveButton("Ok",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
MainActivity mainActivity = (MainActivity) getActivity();
mainActivity.deleteNote(getNoteId());
String msg = "Note " + getNoteId() + " deleted (" + mNote.getTitle() + ")";
Toast.makeText(getContext(), msg, Toast.LENGTH_LONG).show();
dismiss();
}
})
.show();
}
}
);
I tried adding and deleting many notes, flashing and not, but the only way to get this "last" flashing ghost is to remove all notes but remain with one last flashing note. Then, after removing that last flashing note, the flashing ghost remains.
I can have any number of flashing notes, and maybe one normal note but if I delete all notes leaving a normal one, that is deleted just fine: leave a last flashing note and, even if it is deleted, the flashing ghost remains.
When this ghost flashing animation lasts forever, if I add a new note, I can see the new listitem note text and icons over the flashing ghost animation, since it is added at first place... there are two animation overimposed, one is the old "ghost" and the other is the "regular" new note...
Now, some more code:
The listview is
listNote = (ListView) findViewById(R.id.listView);
and is "ruled" by a mNoteAdapter object
listNote.setAdapter(mNoteAdapter);
which extends BaseAdapter, overriding needed methods and also has two methods to add and remove notes
public void addNote(Note n) {
noteList.add(n);
notifyDataSetChanged();
saveNotes();
}
public void deleteNote(int i) {
//(I tried getting the view and canceling animation, setting it to null.. nothing works)
//View listItem = listNote.getAdapter().getView(i, null, listNote);
noteList.remove(i);
notifyDataSetChanged();
saveNotes();
}
the added notes are stored in a list:
List<Note> noteList;
the main overridden method is getView, which is "magically" called by the adapter when a node is added, and creates the listitem view, including the flashing animation if necessary.
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
if (view == null) {
LayoutInflater inflater = (LayoutInflater)
getSystemService(getApplicationContext().LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.listitem, viewGroup, false);
}
TextView txtTitle = (TextView) view.findViewById(R.id.txtSettingsTitle);
TextView txtDescription = (TextView) view.findViewById(R.id.txtDescription);
ImageView ivImportant = (ImageView) view.findViewById(R.id.imageViewImportant);
ImageView ivTodo = (ImageView) view.findViewById(R.id.imageViewTodo);
ImageView ivIdea = (ImageView) view.findViewById(R.id.imageViewIdea);
Note tmpNote = noteList.get(i);
if (mAnimationSpeed != SettingsActivity.NONE && tmpNote.isImportant()) {
view.setAnimation(mAnimFlash);
} else {
view.setAnimation(mAnimFadeIn);
}
if (!tmpNote.isIdea()) ivIdea.setVisibility(View.GONE);
if (!tmpNote.isImportant()) ivImportant.setVisibility(View.GONE);
if (!tmpNote.isTodo()) ivTodo.setVisibility(View.GONE);
txtTitle.setText(tmpNote.getTitle());
txtDescription.setText(tmpNote.getDescription());
return view;
}
I don't need the flashing feature, of course, but I wish to understand what's happening and possibly solve it.
the "flashing" animation (mAnimFlash) xml is:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha android:fromAlpha="0.0"
android:toAlpha="1.0"
android:interpolator="@android:anim/accelerate_interpolator"
android:repeatMode="reverse"
android:repeatCount="infinite"/>
</set>
while the "fading in" (mAnimFadeIn, which is not causing any issue) animation xml is:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="500"
android:interpolator="@android:anim/accelerate_interpolator">
</alpha>
</set>
Can anyone help me understand why that ghost animation remains, just in that case, and how can I better implement this kind of thing?