I'm pulling data into Custom Listview from the mysql database, but as follows, I have a custom button. The button is either black or red, according to the records in the database. For example, there are 30 yields in my database and I pull the data with only 2 red and 28 black. Let's say the data in red is my data number 3 and data number 5. When I start to scroll down; my data number 3 and 5 turn red, then 8 data then the yield number 13 and 15, 23 and 25 turns red .. so there is a repetition .. I can't prevent it .. Is there a solution to this? Can you give support with sample code? My Custom Adapter code is as follows:
public class CostumAdaptor extends ArrayAdapter<Ses> {
private ArrayList<Ses> list;
private ViewHolderr vHolder;
boolean flag = false;
public CostumAdaptor(Context context, int resource, ArrayList<Ses> list) {
super(context, resource, list);
list = new ArrayList<Ses>();
list.addAll(list);
}
public int getCount() {
return list.size();
}
public Ses getItem(int position) {
return list.get(position);
}
public long getItemId(int position) {
return list.get(position).hashCode();
}
public View getView(int position, View conView, ViewGroup parent) {
View vi = conView;
if (vi == null) {
vHolder = new ViewHolderr();
vi = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.tiyatro_item, null);
vHolder.tiyatro_adi = vi.findViewById(R.id.tiyatro_adi);
vHolder.begeni_sayisi2 = (TextView) vi.findViewById(R.id.begeni_sayisi2);
vHolder.daha_sonra_dinleyecegim_2 = (TextView) vi.findViewById(R.id.daha_sonra_dinleyecegim_2);
vHolder.begenmedim_2 = (TextView) vi.findViewById(R.id.begenmedim_2);
vHolder.tiyatro = vi.findViewById(R.id.tiyatro);
vHolder.tur = vi.findViewById(R.id.tur);
vHolder.mensei = vi.findViewById(R.id.mensei);
vHolder.yapimci = vi.findViewById(R.id.yapimci);
vHolder.songCoverImage = vi.findViewById(R.id.coverImage);
vHolder.begendim = vi.findViewById(R.id.begendim);
vHolder.begenmedim = vi.findViewById(R.id.begenmedim);
vHolder.daha_sonra_dinleyecegim = vi.findViewById(R.id.daha_sonra_dinleyecegim);
vi.setTag(vHolder);
}
else {
vHolder = (ViewHolderr) vi.getTag();
}
Ses dmodel = (Ses) list.get(position);
String t_tiyatro_adi = dmodel.getTiyatro_adi();
vHolder.tiyatro_adi.setTag(dmodel);
vHolder.tiyatro.setTag(dmodel);
vHolder.tur.setTag(dmodel);
vHolder.mensei.setTag(dmodel);
vHolder.yapimci.setTag(dmodel);
vHolder.begendim.setTag(dmodel);
vHolder.tiyatro_adi.setText(dmodel.getTiyatro_adi());
vHolder.tiyatro.setText(dmodel.getTiyatro());
vHolder.tur.setText(dmodel.getTur());
vHolder.mensei.setText(dmodel.getMensei());
vHolder.yapimci.setText(dmodel.getYapimci());
String CACHE = t_tiyatro_adi;
new Handler().postDelayed(new Runnable() {
public void run() {
for (int i = 0; i < List1.size(); i++) {
for (int ii = 0; ii < List2.size(); ii++) {
if (List1.get(i).equals(List2.get(ii))) {
if (List1.get(i).equals(CACHE)) {
flag = true;
vHolder.begendim.setImageResource(R.drawable.begendim_dolu);
}
}
}
}
if (!flag) {
vHolder.begendim.setImageResource(R.drawable.begendim_bos);
}
}
}, 250);
return vi;
}
private class ViewHolderr {
TextView tiyatro_adi, tiyatro, tur, mensei, yapimci, begeni_sayisi2, daha_sonra_dinleyecegim_2, begenmedim_2;
ImageView songCoverImage;
ImageView begendim;
}
}
Note: List1 and List2 are ArrayLists pulled from the mysql database and compared with a for loop. The color of the button is red or black as a result of the comparison.
Related
I have a method that add days in the date of the listview, the problem is when I scroll down and up again the values are changed, I have 2 kinds of date, so the method has to be called when the second kind appears in the list, but how can I use the method once so it doesn't keep adding each time I scroll it?
public class FaturasAdapter extends ArrayAdapter<Faturas> {
private Activity activity;
private LayoutInflater inflater;
private List<Faturas> faturasItens;
private Ferramentas mFerramentas;
private String entrada;
private String parcela = "";
private Map<Integer, Integer> intervaloMap;
private String data ="";
public FaturasAdapter(Activity activity, RealmList<Faturas> inItems) {
super(activity, R.layout.faturas_adapter, inItems);
this.activity = activity;
this.faturasItens = inItems;
this.mFerramentas = new Ferramentas();
this.intervaloMap = new HashMap<Integer, Integer>();
}
#Override
public int getCount() {
return faturasItens.size();
}
#Override
public Faturas getItem(int location) {
return faturasItens.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View vi = convertView;
final ViewHolder holder;
final Faturas mFaturas = faturasItens.get(position);
if (inflater == null)
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
vi = inflater.inflate(R.layout.faturas_adapter, null);
holder = new ViewHolder();
holder.numero = (TextView) vi.findViewById(R.id.numero);
holder.intervalo = (TextView) vi.findViewById(R.id.intervalo);
holder.valor = (TextView) vi.findViewById(R.id.valor);
holder.data = (TextView) vi.findViewById(R.id.data);
vi.setTag(holder);
} else {
holder = (ViewHolder) vi.getTag();
}
addIntervalo(mFaturas.getIntervalo(), mFaturas.getTipo());
data = mFerramentas.dataText(intervaloMap.get(mFaturas.getTipo()));
holder.intervalo.setText(String.valueOf(mFaturas.getIntervalo()));
if (mFaturas.getTipo() == Faturas.intervaloConstanteEntrada) {
entrada = "ENT - ";
holder.numero.setText(entrada + mFaturas.getOrder() + "/" + mFaturas.getQtParcelasEntrada());
holder.valor.setText(String.valueOf(mFaturas.getValor()) + " ");
} else {
parcela = "PAR - ";
holder.numero.setText(parcela + mFaturas.getOrder() + "/" + mFaturas.getQtParcela());
holder.valor.setText(String.valueOf(mFaturas.getValor()) + " ");
}
holder.data.setText(data);
return vi;
}
private void addIntervalo(int intervalo, int tipo) {
int intervaloSum = intervalo;
if (!intervaloMap.isEmpty()) {
if (intervaloMap.get(tipo) != null)
intervaloSum += intervaloMap.get(tipo);
}
intervaloMap.put(tipo, intervaloSum);
}
public List<Faturas> getfaturasItens() {
return faturasItens;
}
public void setData(List<Faturas> fat) {
this.faturasItens.addAll(fat);
this.notifyDataSetChanged();
}
public class ViewHolder {
TextView numero;
TextView intervalo;
TextView data;
TextView valor;
}
}
As I said in my comment I don't see why do you need to call the addIntervalo() method in the getView() method. The problem with this is that getView() will be called a lot as the user uses the ListView so you'll end up adding the same data again and again.
From your code it seems you just show the data calculated with addIntervalo()(I'm assuming each item will present its data relative to the total that you calculate for that type that you calculate with addIntervalo()) so you could simply calculate in advance the values and then in getView() simply use that.
// in the constructor you get the data so calculate the values
// iterating over the data
public FaturasAdapter(Activity activity, RealmList<Faturas> inItems) {
super(activity, R.layout.faturas_adapter, inItems);
this.activity = activity;
this.faturasItens = inItems;
this.mFerramentas = new Ferramentas();
this.intervaloMap = new HashMap<Integer, Integer>();
foreach(Faturas f : inItems) {
addIntervalo(f.getIntervalo(), f.getTipo());
}
}
You also have the setData() method where you update the data list so you also need to calculate the result of addIntervalo() for the new items that are about to be added to the adapter:
public void setData(List<Faturas> fat) {
// because you're adding the fat list to the current set of items
// simply calculate addIntervalo() for them to add their count to the total
foreach(Faturas f : fat) {
addIntervalo(f.getIntervalo(), f.getTipo());
}
this.faturasItens.addAll(fat);
this.notifyDataSetChanged();
}
In getView() remove the line:
addIntervalo(mFaturas.getIntervalo(), mFaturas.getTipo());
as you already calculated the values.
Oh, it's problem for base android list's widget to change view. You should know, that ListView and RecycleView caching and invalidating views per scrolling! So your views will be changed to default type!
RecycleView has solution, it's using several type from method getItemType(). But you work with ListView. Anyway! Better solution it's use special list widget which supports custom views and changing that views in anytime. For this task use LinkedListView!
I have list of contacts which has to be displayed in alphabetic under each alphabet as shown in the image shown
How can I do this in RecyclerView, please suggest a solution.thanks
Sort list with data by name
Iterate via list with data, and in place when current's item first letter != first letter of next item, insert special kind of object.
Inside your Adapter place special view when item is "special".
This is what I did following #divers's post:
as he mentioned I pass a team list to the the adapter which is sorted and alphabets are added before the next name.
this is he code used to set adapter
void updateUI(ArrayList<TeamMember> teamMembers) {
adapter = new TeamMemberActivityAdapter(this, addAlphabets(sortList(teamMembers)));
recList.setAdapter(adapter);
recList.setVisibility(View.VISIBLE);
spinningProgressView.setVisibility(View.GONE);
}
code to sort the team list obtained from server is given below:
ArrayList<TeamMember> sortList(ArrayList<TeamMember> list) {
Collections.sort(list, new Comparator<TeamMember>() {
#Override
public int compare(TeamMember teamMember1, TeamMember teamMember2) {
return teamMember1.getFullname().compareTo(teamMember2.getFullname());
}
});
return list;
}
while adding alphabets to the list I am setting a type value to know whether its alphabet or team name to check this inside the adapter for showing corresponding layout .the code for that is as shown below:
ArrayList<TeamMember> addAlphabets(ArrayList<TeamMember> list) {
int i = 0;
ArrayList<TeamMember> customList = new ArrayList<TeamMember>(); TeamMember firstMember = new TeamMember();
firstMember.setFullname(String.valueOf(list.get(0).getFullname().charAt(0)));
firstMember.setType(1);
customList.add(firstMember);
for (i = 0; i < list.size() - 1; i++) {
TeamMember teamMember = new TeamMember();
char name1 = list.get(i).getFullname().charAt(0);
char name2 = list.get(i + 1).getFullname().charAt(0);
if (name1 == name2) {
list.get(i).setType(2);
customList.add(list.get(i));
} else {
list.get(i).setType(2);
customList.add(list.get(i));
teamMember.setFullname(String.valueOf(name2));
teamMember.setType(1);
customList.add(teamMember);
}
}
list.get(i).setType(2);
customList.add(list.get(i));
return customList;
}
And finally inside your adapter check if the item is teamMember name or alphabet and display corresponding layout as shown below:
#Override
public int getItemViewType(int position) {
int viewType = 0;
if (mMembers.get(position).getType() == TYPE_LETTER) {
viewType = TYPE_LETTER;
} else if (mMembers.get(position).getType() == TYPE_MEMBER) {
viewType = TYPE_MEMBER;
}
return viewType;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
LayoutInflater mInflater = LayoutInflater.from(viewGroup.getContext());
switch (viewType) {
case TYPE_LETTER:
ViewGroup vGroupImage = (ViewGroup) mInflater.inflate(R.layout.board_team_letter_item, viewGroup, false);
ViewHolderLetter image = new ViewHolderLetter(vGroupImage);
return image;
case TYPE_MEMBER:
ViewGroup vGroupText = (ViewGroup) mInflater.inflate(R.layout.board_team_member_item, viewGroup, false);
ViewHolderMember text = new ViewHolderMember(vGroupText);
return text;
default:
ViewGroup vGroupText2 = (ViewGroup) mInflater.inflate(R.layout.board_team_member_item, viewGroup, false);
ViewHolderMember text1 = new ViewHolderMember(vGroupText2);
return text1;
}
}
hope this could help you. all the best
compare your model and get first character from title ....
private void getHeaderListLatter(ArrayList<CountriesModel> usersList) {
Collections.sort(usersList, new Comparator<CountriesModel>() {
#Override
public int compare(CountriesModel user1, CountriesModel user2) {
return String.valueOf(user1.name.charAt(0)).toUpperCase().compareTo(String.valueOf(user2.name.charAt(0)).toUpperCase());
}
});
String lastHeader = "";
int size = usersList.size();
for (int i = 0; i < size; i++) {
CountriesModel user = usersList.get(i);
String header = String.valueOf(user.name.charAt(0)).toUpperCase();
if (!TextUtils.equals(lastHeader, header)) {
lastHeader = header;
mSectionList.add(new CountriesModel(header,true));
}
mSectionList.add(user);
}
}
and in your adapter getItemViewType Layout like this ....
#Override
public int getItemViewType(int position) {
if (mCountriesModelList.get(position).isSection) {
return SECTION_VIEW;
} else {
return CONTENT_VIEW;
}
}
for complete reference .
https://github.com/sayanmanna/LetterSectionedRecyclerView
I'm currently using this. It's very easy to implement, compatible with RecyclerView adapter, and so lightweight you'd barely call it a library!
You can achieve it with this library.
There is a full example here of how to add headers.
And if you want to implement the search functionality, there is also a full example here, this is the result:
https://github.com/emilsjolander/StickyListHeaders
I hope this is what You want.
I'm facing a strange behaviour using an ArrayAdapter.
When the number of listview item exceed the height of the listView (say after item 8), the next item get the id 0 instead the id 9.
In my opinion this type of issue was explained here with the convertView, but i use it in the same way (i think).
The following code is my ArrayAdapter.
public class StepsAdapter extends ArrayAdapter<String> {
Context context;
List<String> steps;
public StepsAdapter(Context context, int resourceId, List<String> steps) {
super(context, resourceId, steps);
this.context = context;
}
private class ViewHolder {
EditText stepValue;
ImageView removeStep;
}
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
final String step = getItem(position);
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.row_step, null);
holder = new ViewHolder();
holder.stepValue = (EditText) convertView.findViewById(R.id.stepEdit);
holder.removeStep = (ImageView) convertView.findViewById(R.id.removeStep);
holder.stepValue.setText(step);
holder.removeStep.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context,"* Remove id step " + position, Toast.LENGTH_LONG).show();
steps.remove(position);
notifyDataSetChanged();
}
});
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
return convertView;
}
}
Then my main activity where i get existing data and put it in my listView, the add button and the save button.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.add_game);
mContext = getApplicationContext();
steps = new ArrayList<String>();
stepsAdapter = new StepsAdapter(mContext,R.layout.row_step,steps);
Gson gson = new GsonBuilder().create();
game = gson.fromJson(gameJson, Games.class);
/*
* Settings values
*/
gameNameValue.setText(game.getName());
gameBackgroundPreview.setBackgroundColor(game.getColor());
colorSelected = game.getColor();
for(int i = 0; i < game.getSteps().size() ; i++){
//steps.add(game.getSteps().get(i).toString());
//notifyDataSetChanged();
stepsAdapter.add(game.getSteps().get(i).toString());
}
final ListView listSteps = (ListView) findViewById(R.id.listViewSteps);
listSteps.setAdapter(stepsAdapter);
gameNameValue.setText(gameName);
addSteps.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stepsId = steps.size();
Toast.makeText(getApplicationContext(), "addSteps : " + stepsId, Toast.LENGTH_LONG).show();
stepsAdapter.insert("newstep", stepsId);
}
});
buttonSaveGame.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String valueEditGameName = gameNameValue.getText().toString();
int valueColorBackaground = colorSelected;
String picture = "testPic";
for(int i=0; i < listSteps.getChildCount(); i++) {
LinearLayout rowLayout = (LinearLayout) listSteps.getChildAt(i);
//Log.e(TAG, ">> :) layout >>" + listSteps.getChildAt(i).getClass().getName());
EditText editRow = (EditText) rowLayout.getChildAt(0);
stepsValues.add(editRow.getText().toString());
//Log.e(TAG, ">> :) inside layout >>" + editRow.getText().toString());
}
if(valueEditGameName.trim().length() > 0 && picture.trim().length() >0 ){
Games game = new Games(valueEditGameName,valueColorBackaground,picture,stepsValues);
String goToSave = game.createJson();
Log.e(TAG, ">>Saved>>" + goToSave);
final CkdFile file = new CkdFile();
String saved = file.writeToSDFile(game.getName(), goToSave);
Toast.makeText(mContext, saved, Toast.LENGTH_LONG).show();
Intent backToMain = new Intent(mContext,MainActivity.class);
startActivity(backToMain);
} else {
Toast.makeText(mContext, "Fill all texts", Toast.LENGTH_LONG).show();
}
}
});
}
I try to add items in 2 different ways :
add item through : List steps
add item through : StepsAdapter stepsAdapter
Both give me same behaviour.
If someone has a clue to help understanding what i'm doing wrong with my implementation of ListView/ArrayAdapter.
Thanks in advance !
EDIT 1 :
After pushing some logs everywere, it understand the strange behaviour :
My adapter have only 6 slots (the limit came from the size of the listview in layout), and when my arraylist have more than 6 items, the getView select items only between 0 and 5.
I'm searching now a way to get the position in ArrayList and not the position in arrayadapter.
I faced same issue recently. Add following overrides to Adapter:
#Override
public int getViewTypeCount() {
return getCount();
}
#Override
public int getItemViewType(int position) {
return position;
}
I found a simple xml "trick" to avoid this behaviour : i set a biger height to listView.
<ListView
android:layout_width="match_parent"
android:layout_height="1000dp"
android:layout_gravity="center_horizontal"
android:id="#+id/listViewSteps"
android:layout_margin="10dp">
</ListView>
It's not really resolve but a take it ...
I've looked for this issue but nothing I've found matches my situation.
My problem occurs onAndroid 2.3.x (on 4.x it works perfectly)
I have an application with a custom list view. I initialize my listview as follows
ListAdapter mListAdapter = new ListAdapter(getApplicationContext(), this, ...);
lvSelector = (ListView) findViewById(R.id.listView1);
lvSelector.setAdapter(mListAdapter);
My ListAdapter is as follows:
public class ListAdapter extends BaseAdapter {
static class Holder {
LinearLayout layoutRoot, layoutColor;
TextView hText;
Animation anim = AnimationUtils.loadAnimation(mActivity, R.anim.anim_list_item);
public Holder() {
layoutRoot = new LinearLayout(mContext);
layoutColor = new LinearLayout(mContext);
hText = new TextView(mContext);
}
public Holder(Holder holder) {
this.layoutRoot = holder.layoutRoot;
this.layoutColor = holder.layoutColor;
this.hText = holder.hText;
}
}
int mSwap1, mSwap2;
Animation mAnimation;
public ListAdapter(Context _context, Activity _activity, FileHandler _fileHandler, String _strSchemaName, List<String> _list, List<String> _solution) {
mContext = _context;
mActivity = _activity;
mAnimation = AnimationUtils.loadAnimation(mActivity, R.anim.anim_list_item);
mAnimation.reset();
mSwap1 = mSwap2 = -1;
/* ... */
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final int fPosition = position;
View row = convertView;
Holder lHolder = null;
if (row==null) {
LayoutInflater inflater = mActivity.getLayoutInflater();
row = inflater.inflate(R.layout.layout_schema_element, parent, false);
lHolder = new Holder();
lHolder.layoutRoot = (LinearLayout) row.findViewById(R.id.elementLayoutRoot);
lHolder.layoutColor = (LinearLayout) row.findViewById(R.id.elementLayoutColor);
lHolder.hText = (TextView) row.findViewById(R.id.textViewWord);
row.setTag(lHolder);
}
else {
lHolder = (Holder)row.getTag();
}
row.setOnClickListener(null);
if (position==0 || position==mDataList.size()-1) {
lHolder.layoutColor.setBackgroundResource(R.drawable.bg_elem_fixed);
lHolder.layoutColor.setOnClickListener(null);
}
else {
lHolder.layoutColor.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
moveElement(fPosition);
}
});
}
lHolder.hText.setText(mDataList.get(position));
lHolder.layoutRoot.setBackgroundResource(0);
mHolder.set(position, lHolder);
return row;
}
}
protected void moveElement(int _element) {
if (mDataList.get(_element).equals(mSolution.get(_element)))
return;
if (mSwap1==-1)
{
System.out.println("setting swap1=" + _element);
mHolder.get(_element).layoutRoot.setBackgroundResource(R.drawable.bg_elem_selected_lite);
mSwap1 = _element;
}
else
{
if (mSwap2==-1)
{
System.out.println("setting swap2=" + _element);
mHolder.get(_element).layoutRoot.setBackgroundResource(R.drawable.bg_elem_selected_lite);
mSwap2 = _element;
}
}
if (mSwap1!=-1)
{
System.out.println("running animation on mSwap1=" + mSwap1);
mHolder.get(mSwap1).layoutRoot.clearAnimation();
mHolder.get(mSwap1).layoutRoot.startAnimation(mAnimation);
}
/***** THIS IS WHAT DOES NOT WORK *****/
if (mSwap2!=-1)
{
System.out.println("running animation on mSwap2=" + mSwap2);
mHolder.get(mSwap2).layoutRoot.clearAnimation();
mHolder.get(mSwap2).layoutRoot.startAnimation(mAnimation);
}
if (mSwap1!=-1 && mSwap2!=-1)
{
mHolder.get(mSwap1).layoutRoot.setBackgroundColor(0);
mHolder.get(mSwap2).layoutRoot.setBackgroundColor(0);
if (mSwap1==mSwap2)
{
mSwap1 = mSwap2 = -1;
return;
}
Collections.swap(mDataList, mSwap1, mSwap2);
Collections.swap(mHolder, mSwap1, mSwap2);
Collections.swap(dataObjs, mSwap1, mSwap2);
mSwap1 = mSwap2 = -1;
notifyDataSetChanged();
}
}
}
Everything works fine when I perform Collections.swap(list, mSwap1, mSwap2), elements are correctly swapped.
First animation (mSwap1) is run fine; my problem is that when second animation is run (mSwap2), it is executed on another element in screen even if mSwap2 is right (e.g.: mSwap1=1 -> second element in list is animated, mSwap2=2 -> n-1 element and n-2 element in list are animated where n is the number of visible elemnts).
I've solved my problem replacing animation calls
mHolder.get(idx).layoutRoot.clearAnimation();
mHolder.get(idx).layoutRoot.startAnimation(mAnimation);
with the following method
private void animateItem(int _index, Animation _animation) {
if (
_index<mLvSelector.getFirstVisiblePosition() // selected item is above first visible element
|| _index>mLvSelector.getLastVisiblePosition() // selected item is below last visible element
)
// element is invisible -> no animation
return;
int newIndex = _index;
if (
android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH // before android 4.0
&& mSwap2>=0 // second selection
&& mSwap1!=mSwap2 // second selection differs from first selection
)
newIndex = mLvSelector.getFirstVisiblePosition() + (mLvSelector.getLastVisiblePosition() - _index);
mHolder.get(newIndex).layoutRoot.clearAnimation();
mHolder.get(newIndex).layoutRoot.startAnimation(_animation);
}
Adding Animation argument to the method allows to differentiate animation between elements (mSwap1 and mSwap2).
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