OK, I am working on an App that has a page with a listview and a edittext box at top. As you type things into the edittext box it will filter what items are shown in the listview. The problem I am having is with the fast scroll icon that appears on the side of the slider.
When the page first loads NO MATTER what I do the fast scroll slider icon will not appear on the screen. Then I click in the edit text box and type one character and then erase it and now my fast scroll slider icon will appear.
First load no fast scroll icon.
Edittext box and then erase text and fast scroll icon appears.
I have the android:fastScrollEnabled="true" set in my listview. Plus I have set it manually in the code by doing lv1.setFastScrollEnabled(true);
No matter I change I still get the same behavior, unless I remove it complete from the code and xml and then it will stop working on the second page. I have tried cleaning my project and still no good. I am leaning towards it being a bug in android or I am missing something extremely simple.
Here is my code.
public class SearchByFood extends ParentClass
{
private ListView lv1;
private EditText ed;
int textlength = 0;
private ArrayList<String> arr_sort = new ArrayList<String>();
private ArrayList<String> foods = new ArrayList<String>();
private LayoutInflater mInflater;
private ArrayList<Food> foodList;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.search_by_food);
setTextTitle("Search by Food");
lv1 = (ListView) findViewById(R.id.ListView01);
ed = (EditText) findViewById(R.id.EditText01);
mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
DataLayerFunctions d = new DataLayerFunctions(getApplicationContext());
foodList = d.selectFoodsWithSubstitutes();
for (Food f : foodList)
{
// this is to build a ArrayList<String> to pass to the setAdapter
Log.d("SearchByFood", "FoodName: " + f.getFood_Name());
foods.add(f.getFood_Name());
}
ArrayAdapter<String> firstAdapter = new ArrayAdapter<String>(SearchByFood.this, R.layout.search_food_listview, foods);
lv1.setAdapter(firstAdapter);
lv1.setFastScrollEnabled(true);
ed.addTextChangedListener(new TextWatcher()
{
public void afterTextChanged(Editable s)
{
}
public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
}
public void onTextChanged(CharSequence s, int start, int before, int count)
{
textlength = ed.getText().length();
arr_sort.clear();
for (String f : foods)
{
if (textlength <= f.length())
{
if (f.toString().toLowerCase().contains((CharSequence) ed.getText().toString().toLowerCase()))
{
Log.d("STRING", "STRING: " + f.toString() + " contains " + ed.getText());
if (ed.getText().length() > 0)
{
String newString = boldMyString(f, ed.getText().toString());
arr_sort.add(newString);
}
else
{
arr_sort.add(f);
}
}
}
}
// if empty add a no foods found
if (arr_sort.isEmpty())
{
arr_sort.add("No Foods Found");
}
// Load array
// lv1.setAdapter(new
ArrayAdapter<String> adapter = new ArrayAdapter<String>(SearchByFood.this, R.layout.search_food_listview, arr_sort)
{
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
View row;
if (null == convertView)
{
row = mInflater.inflate(R.layout.search_food_listview, null);
}
else
{
row = convertView;
}
TextView tv = (TextView) row.findViewById(android.R.id.text1);
tv.setText(Html.fromHtml(getItem(position)));
// tv.setText(getItem(position));
return row;
}
};
lv1.setAdapter(adapter);
}
private String boldMyString(String foodName, String guess)
{
int gLength = guess.length();
ArrayList<Integer> results = new ArrayList<Integer>();
for (int i = foodName.toLowerCase().indexOf(guess.toLowerCase()); i >= 0; i = foodName.toLowerCase()
.indexOf(guess.toLowerCase(), i + 1))
{
System.out.println("TEST:" + i);
results.add(i);
}
// Count value is for words that have 2 or more values of guess
// in them.
int count = 0;
for (int i : results)
{
StringBuffer s1 = new StringBuffer(foodName);
s1.insert(i + count, "<b>");
count = count + 3;
s1.insert(i + count + gLength, "</b>");
count = count + 4;
foodName = s1.toString();
System.out.println("FOOD NAME:" + i + ":" + foodName);
}
return foodName;
}
});
// This is what actually does stuff when you click on a listview item.
lv1.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
// Strip out the bold tags
String clicked = (String) lv1.getItemAtPosition(position);
clicked = clicked.replaceAll("<b>", "");
System.out.println("Clicked" + clicked);
clicked = clicked.replaceAll("</b>", "");
// Find the Food ID match and pass the food id to the
// fooddisplay page
for (Food f : foodList)
{
if (null != clicked && clicked.equals(f.getFood_Name()))
{
Intent intent = new Intent(SearchByFood.this, SubstituteDisplay.class);
intent.putExtra("FoodID", f.getFood_ID());
startActivity(intent);
}
}
}
});
}
#Override
public void onBackPressed()
{
final Intent intent = new Intent(this, MasterTemplateActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
this.startActivity(intent);
return;
}
}
Again, any help as to why my fast scroll icon doesn't show up at first would be much appreciated. It is a small thing but it is really annoying me.
try list.setFastScrollAlwaysVisible(true)
and also try list.smoothScrollToPosition(0); so that icon appears when scroll is called...
something like this..
new Handler().postDelayed(new Runnable() {
#Override
public void run(){
list.smoothScrollToPosition(0);
}
}, 100);
So again I'm posting this because my issue was genuinly different. Fast scrolling also doesn't seem to work in a ConstraintLayout. Both ListView Fast Scrolling and RecyclerView Fast Scrolling don't seem to work.
Related
I'm creating a music player. This class among other things is suppose to add new songs to the playlist.
A new window pops up with available songs and the checked songs get added. Songs can be filtered and the selected rows are to change the color when the checkbox is checked. The filtering works and everything is being added the way it's suppose to but...
The problem is that when I check a song/some songs and then click on the search filter and the soft keyboard pops up the color of the selected rows changes to the default color, (the the song is still checked and can be added to the Playlist). When songs are checked and I hide the keyboard the same thing happens.
The other issue is that when the list gets filtered the color of the row previously selected goes away as well when the search box is cleared, the songs remain schecked though.
And I don't understand how and why that happens and therefore how to fix this.
Anyone has any ideas, please?
I think I don't understand how updating after filtering works and what notifyDataSetChanged() does exactly.
Here's the adapter code :
public class MyTrackAdapter extends ArrayAdapter<File>
{
private final Activity context;
private ArrayList<File> album, temp;
private ArrayList<File> piosenki;
public MyTrackAdapter(Activity context, ArrayList<File> album)
{
super(context, R.layout.adapter_traki, album);
this.context = context;
this.temp = new ArrayList<File>(album);
this.album = album;
this.piosenki=new ArrayList<File>();
}
public View getView(int position, View view, ViewGroup parent)
{
LayoutInflater inflater = context.getLayoutInflater();
final View rowView = inflater.inflate(R.layout.adapter_traki, null,true);
final CheckBox cb_plus = (CheckBox) rowView.findViewById(R.id.add);
final int position1=position;
final TextView txt = (TextView) rowView.findViewById(R.id.list_text);
if(position1 %2 == 1) rowView.setBackgroundResource(R.color.bbcolor);
else rowView.setBackgroundResource(R.color.bpcolor);
txt.setText(album.get(position1).getName().toString().replace(".mp3",""));
cb_plus.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
{
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
if (cb_plus.isChecked())
{
cb_plus.setBackgroundResource(R.drawable.x2);
txt.setTextColor(context.getResources().getColor(R.color.bdcolor));
rowView.setBackgroundResource(R.color.acolor);
piosenki.add(album.get(position1));
}
else
{
cb_plus.setBackgroundResource(R.drawable.plus);
txt.setTextColor(context.getResources().getColor(R.color.gcolor));
if(position1 %2 == 1) rowView.setBackgroundResource(R.color.bbcolor);
else rowView.setBackgroundResource(R.color.bpcolor);
piosenki.remove(album.get(position1));
}
}
});
return rowView;
}
public void showTost(String s)
{
Toast.makeText(context, s, Toast.LENGTH_SHORT).show();
}
public ArrayList<File> getpiosenki()
{
return piosenki;
}
public Filter getFilter()
{
return filtr;
}
private Filter filtr = new Filter()
{
protected FilterResults performFiltering(CharSequence s)
{
FilterResults r = new FilterResults();
ArrayList<File> f = new ArrayList<File>();
if(s==null || s.length()==0) f.addAll(temp);
else
{
String ss=s.toString().toLowerCase().trim();
for(File ff : temp) if(ff.getName().replace(".mp3", "").toLowerCase().contains(ss)) f.add(ff);
}
r.values=f;
r.count=f.size();
return r;
}
protected void publishResults(CharSequence s, FilterResults r)
{
album.clear();
album.addAll((ArrayList)r.values);
notifyDataSetChanged();
}
};
}
And the Playlist class :
public class Playlist extends Activity implements TextWatcher
{
int where;
long pos;
String pllist;
ArrayList<String> lstp, lsts;
ArrayList<Long> lsti;
ArrayList<Integer> lstx;
DBHandler db;
private TextView txt1, txt2;
ImageView pic;
private ListView lv_traki;
ListView lv_traki2add;
PopupWindow pw;
View popupv;
TextView etext;
MyTrackAdapter tadapter;
ImageView add2list;
ArrayList <File> piosenki, toadd;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.playlist);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
db = new DBHandler(getApplicationContext());
Intent tnt = getIntent();
Bundle bn = tnt.getExtras();
lstp = (ArrayList) bn.getParcelableArrayList("path");
lsts = (ArrayList) bn.getParcelableArrayList("song");
lsti = (ArrayList) bn.getParcelableArrayList("indx");
lstx = (ArrayList) bn.getParcelableArrayList("pause");
pos = bn.getLong("pos", 0);
where = bn.getInt("skad", 0);
pllist = bn.getString("album");
piosenki = (ArrayList) bn.getParcelableArrayList("full");
setData(0, lstp.size());
songlist();
lv_traki.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> adapterView, View v, int i, long l)
{
Intent it;
lstp.clear();
lsti.clear();
lsts.clear();
lstx.clear();
db.gett1path(pos, lstp);
db.gett1song(pos, lsts);
db.gett1pause(pos, lstx);
db.gett1id(pos, lsti);
it=new Intent(getApplicationContext(), Player.class);
it.putExtra("path", lstp).putExtra("nazwa", lsts).putExtra("pause", lstx).putExtra("pos",i).putExtra("skad",4);
startActivity(it);
}
});
if(where==5) lv_traki.performItemClick(lv_traki.getAdapter().getView(0, null, null), 0, lv_traki.getAdapter().getItemId(0));
add2list = (ImageView) findViewById(R.id.btn_addtoplay);
toadd = new ArrayList<File>();
add2list.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
popupv = ((LayoutInflater) getApplicationContext().getSystemService("layout_inflater")).inflate(R.layout.popup_addtolist, null);
ImageView btn01 = (ImageView) popupv.findViewById(R.id.btn_addtoplay);
FrameLayout fl = (FrameLayout) findViewById(R.id.frameLayout1);
etext = (EditText) popupv.findViewById(R.id.etext);
etext.addTextChangedListener(Playlist.this);
lv_traki2add = (ListView) popupv.findViewById(R.id.lst_traki2add);
tadapter = new MyTrackAdapter(Playlist.this, piosenki);
lv_traki2add.setAdapter(tadapter);
toadd=tadapter.getpiosenki();
btn01.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
if(toadd.size()>0)
{
for (File addt1 : toadd)
{
db.addt1(pos, addt1);
}
lstp.clear();
lsts.clear();
lstx.clear();
lsti.clear();
db.gett1path(pos, lstp);
db.gett1song(pos, lsts);
db.gett1pause(pos, lstx);
db.gett1id(pos, lsti);
lv_traki.setAdapter(null);
setData(0, lstp.size());
MyPlaylistAdapter adapter=new MyPlaylistAdapter(Playlist.this, lsts, lstp, lsti, lstx, pos, pllist, lv_traki, txt2);
lv_traki.setAdapter(adapter);
for(int x=0; x<lv_traki2add.getChildCount(); x++)
{
CheckBox cb = lv_traki2add.getChildAt(x).findViewById(R.id.add);
cb.setChecked(false);
}
pw.dismiss();
showTost("Songs Added");
}
else pw.dismiss();
}
});
pw = new PopupWindow(popupv, -1, -1, true);
pw.showAtLocation(fl, 17, 0, 0);
}
});
}
private void songlist()
{
lv_traki = (ListView) findViewById(R.id.lst_traki);
MyPlaylistAdapter adapter=new MyPlaylistAdapter(this, lsts, lstp, lsti, lstx, pos, pllist, lv_traki, txt2);
lv_traki.setAdapter(adapter);
}
public void setData(int z, int size)
{
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
MediaMetadataRetriever tmp = new MediaMetadataRetriever();
mmr.setDataSource(lstp.get(z));
txt1 = (TextView) findViewById(R.id.txt1);
txt2 = (TextView) findViewById(R.id.txt2);
pic = (ImageView) findViewById(R.id.img_bg);
int tmax = 0;
for(int i=0;i<size;i++)
{
tmp.setDataSource(lstp.get(i));
tmax+=Integer.parseInt(tmp.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
tmax+=lstx.get(i)*1000;
}
txt1.setText(pllist);
if (size>1) txt2.setText(size+" songs; "+mili_t(tmax));
else txt2.setText("1 song; "+mili_t(tmax));
Bitmap bm;
Drawable d;
byte [] img = mmr.getEmbeddedPicture();
if(img!=null)
{
bm = BitmapFactory.decodeByteArray(img, 0, img.length);
d = new BitmapDrawable(getResources(), bm);
pic.setBackground(d);
}
else
{
pic.setBackgroundResource(R.drawable.no_image);
pic.getLayoutParams().height = 400;
pic.getLayoutParams().width = 400;
pic.setScaleType(ScaleType.CENTER_INSIDE);
}
}
public String mili_t(int t)
{
int s = (int) (t / 1000) % 60 ;
int m = (int) ((t / (1000*60)) % 60);
int h = (int) ((t / (1000*60*60)) % 24);
String dt="", dh, ds, dm;
if(h>0)
{
dh=Integer.toString(h);
if(h<10) dh="0"+dh;
dt=dt+dh+":";
}
if(m>=0)
{
dm=Integer.toString(m);
if(m<10) dm="0"+dm;
dt=dt+dm+":";
}
if(s>=0)
{
ds=Integer.toString(s);
if(s<10) ds="0"+ds;
dt=dt+ds;
}
return dt;
}
public void showTost(String s)
{
Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT).show();
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
tadapter.getFilter().filter(s);
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
#Override
public void afterTextChanged(Editable s) {}
}
And the xml :
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/popupwrap"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#color/bdcolor">
<RelativeLayout
android:id="#+id/popup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/bdcolor">
<EditText
android:id="#+id/etext"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColorHint="#color/bbcolor"
android:hint="SEARCH FILTER"
android:background="#drawable/etext"
android:textSize="24sp"
android:textCursorDrawable="#drawable/cursor"
android:textColor="#color/gcolor"
android:inputType="text"
android:layout_marginLeft="10dp"
android:layout_marginRight="80dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"/>
<ImageView
android:id="#+id/btn_addtoplay"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginBottom="10dp"
android:layout_marginRight="10dp"
android:src="#drawable/check1"
android:clickable="true"
android:layout_alignParentRight="true"
android:layout_marginTop="10dp"
android:layout_centerVertical="true"/>
</RelativeLayout>
<ListView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/lst_traki2add">
</ListView>
</LinearLayout>
The problem is that you are relying on the Checkbox view in each row to maintain the selection state for that row. You will also see strange behavior if you have a long list of songs, select some, and then scroll. Both of these problems are because ListView will recycle the views that are used to render the songs that are currently displayed rather than creating a new set of views for every row.
To solve this problem, you need to maintain the selection state yourself. You can do this with a bool[] or List<Boolean> that stores a flag for every song in your current data. Use this to set the background color and checkbox state rather than relying on the checkbox state to set the background color.
reason is simple - you have OnCheckedChangeListener which fires after every (un)check and is changing background. Everytime you call notifyDataSetChanged() whole list will be redrawn, so background color will be again set with if(position1 %2 == 1) condition in getView method, but listener won't fire again. check out his code with manual listener call
CompoundButton.OnCheckedChangeListener listener = new CompoundButton.OnCheckedChangeListener()
{
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
if (cb_plus.isChecked())
{
cb_plus.setBackgroundResource(R.drawable.x2);
txt.setTextColor(context.getResources().getColor(R.color.bdcolor));
rowView.setBackgroundResource(R.color.acolor);
if(piosenki.get(album.get(position1)) != null) // won't duplicate
piosenki.add(album.get(position1));
}
else
{
cb_plus.setBackgroundResource(R.drawable.plus);
txt.setTextColor(context.getResources().getColor(R.color.gcolor));
if(position1 %2 == 1) rowView.setBackgroundResource(R.color.bbcolor);
else rowView.setBackgroundResource(R.color.bpcolor);
piosenki.remove(album.get(position1));
}
}
}
boolean isAdded = ...;
cb_plus.setChecked(isAdded);
cb_plus.setOnCheckedChangeListener(listener); // set listener after setting (un)checked
listener.onCheckedChanged(cb_plus, isAdded); // manual call
isAdded is your condition for CheckBox checked or not, problably piosenki.contains(album.get(position1)); or piosenki.get(album.get(position1)) != null;. you can also get rid of few duplicated lines from getView method, like those with background or textcolor setting - these will be called inside manual listener call
PS. also change piosenki to songs ;)
this is my code; basically, it is a listview with multiple choice that add a number to a score (textview) when its clicked. My problem is that i would like the number be added to the score when the item is selected in the listview, and removed when the item is deselected. With my code each time that you click an item, the number is added to the score.
public class MainActivity extends Activity {
ListView myList;
TextView tv1;
String[] listContent = {
"Add 2 to total",
"Add 3 to total",
"Add 1 to total",
"Add 5 to total",
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myList = (ListView) findViewById(R.id.listView1);
tv1 = (TextView) findViewById(R.id.textView);
final int[] counter = {0};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice, listContent);
myList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
myList.setAdapter(adapter);
myList.setOnItemClickListener(new OnItemClickListener() {
private String[] listview_array2 = {"2", "3", "1", "5"};
public void onItemClick(AdapterView<?> arg0, View v, int position, long id) {
if (myList.isItemChecked(position)) {
String name = this.listview_array2[position];
int counter2 = Integer.parseInt(name);
counter[0] = counter[0] + counter2;
tv1.setText("Total " + counter[0]);
} else {
}
}
});
}
}
I have thought that maybe changing to setOnItemSelected instead of ItemClicked, but I am not sure.
Hope I have explain myself properly and you can help me.
Thank you in advanced.
Try with OnItemClickListener with a Boolean for selection/deselection.
Hope this will work
You can do that through your code.
Maintain a flag in the list of your values like List list;
Values is a model containing the number and a flag.
If a item is clicked, set the flag true and do your calculations.
If already clicked item is clicked again, you just need to check the flag.
if(list.getposition(position).isItemClickd){
// Decrease that value from total
// list.getposition(position).isItemClickd = false;
} else{
// list.getposition(position).isItemClickd = true;
// total = total+prevValue;
}
I finally made it in a easy way!!!
public void onItemClick(AdapterView<?> arg0, View v, int position, long id) {
if (myList.isItemChecked(position)) {
String name = this.listview_array2[position];
int counter2 = Integer.parseInt(name);
counter[0] = counter[0] + counter2;
tv1.setText("Total " + counter[0]);
I add in "else" the same action than in "if", but subtracting the number
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 ...
We have a list view fragment that contains a listview, edit text(for search) and check box(Select All). As mentioned we are using Edit Text for searching the values from the list view.
Problem:
We have list view displaying 10 items( list view sorted alphabetically).
When we type 'W' in the edit text we are displayed with two values i.e. WF and WH.
The selection is made for WF(first item displayed).
After clearing the characters in the edit text, we are now displayed with the complete list of the list view.
But the selection is now made for first item in the list AHMD. (we intended to select WF)
Basically, the positions of the data in the list view is not getting refreshed after we have performed search.
code:
public static class ListViewFragment extends Fragment {
private ListView myListView;
private EditText editsearch;
private CheckBox selectAll;
private String SELECTED_FILTER;
private ArrayList<String> SelectedFilter1;
private ArrayList<String> checkekprev=new ArrayList<String>();
private ArrayList<String> CheckedFitlers=new ArrayList<String>();
ArrayAdapter<String> adapter_list;
OnCheckedItemsLister onCheckedItemsLister;
public ListViewFragment() {
// Empty constructor required for fragment subclasses
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
onCheckedItemsLister = (OnCheckedItemsLister) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement onSomeEventListener");
}
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setRetainInstance(true);
SelectedFilter1=getArguments().getStringArrayList("ArrayList");
SELECTED_FILTER=getArguments().getString("SELECTED_FILTER");
checkekprev=getArguments().getStringArrayList("checkedprevlist");
if(checkekprev.size()==SelectedFilter1.size())
selectAll.setChecked(true);
else
selectAll.setChecked(false);
adapter_list = new ArrayAdapter<String>(this.getActivity(),
android.R.layout.simple_list_item_multiple_choice,SelectedFilter1);
adapter_list.notifyDataSetChanged();
myListView.setAdapter(adapter_list);
myListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
myListView.setTextFilterEnabled(true);
try{
if(checkekprev.isEmpty()==false){
Log.i("Adapter set", "Yes");
for(int j=0;j<checkekprev.size();j++){
Log.i("Adapter set", "Yes:"+j);
int pos=adapter_list.getPosition(checkekprev.get(j));
Log.i("Adapter set", "Pos:"+pos);
myListView.setItemChecked(pos,true);
}
}
}catch(NullPointerException e){
Log.i("Null set", "Yes");
}
editsearch.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
String text = editsearch.getText().toString().toLowerCase(Locale.getDefault());
adapter_list.getFilter().filter(text);
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3) {
// TODO Auto-generated method stub
}
#Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
});
selectAll.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
Log.i("CheckBOX","Is Checked:"+isChecked);
if(isChecked)
{
for ( int i=0; i< myListView.getCount(); i++ )
myListView.setItemChecked(i, true);
}else
{
for ( int i=0; i< myListView.getCount(); i++ )
myListView.setItemChecked(i, false);
}
SparseBooleanArray checked = myListView.getCheckedItemPositions();
CheckedFitlers.clear();
for(int i=0;i<=checked.size();i++){
if (checked.get(i)){
CheckedFitlers.add(SelectedFilter1.get(i));
}
}
onCheckedItemsLister.someEvent(CheckedFitlers,SELECTED_FILTER);
}
}
);
myListView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,int position, long id){
setItemChecked(position);
onCheckedItemsLister.someEvent(CheckedFitlers,SELECTED_FILTER);
}
});
}
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
if(savedInstanceState!=null){
checkekprev=savedInstanceState.getStringArrayList("Checked_Values");
}
}
public void setItemChecked(int position){
//if(SelectedFilter1.get(position).)
//int len = myListView.getCount();
SparseBooleanArray checked = myListView.getCheckedItemPositions();
for(int i=0;i<=checked.size();i++){
Log.i("Check Sparse Array","Check Sparse Array: "+checked.get(i));
}
//for (int i = 0; i < len; i++){
Log.i("SelectedFilter1.get(position)","SelectedFilter1.get(position):::"+SelectedFilter1.get(position));
Log.i("checked.get(position))","checked.get(position)):::"+checked.get(position));
for (int i=0; i<CheckedFitlers.size();i++){
Log.i("CheckedFitlers","CheckedFitlers:::" + CheckedFitlers.get(i));
}
for (int i=0; i<checkekprev.size();i++){
Log.i("checkekprev","checkekprev:::" + checkekprev.get(i));
}
Log.i("CheckedFitlers","CheckedFitlers:::" + CheckedFitlers.size());
Log.i("checkekprev","checkekprev:::" + checkekprev.size());
if(CheckedFitlers.size() == 0 && checkekprev.size() != 0){
CheckedFitlers = checkekprev;
}
Log.i("CheckedFitlers","CheckedFitlers:::" + CheckedFitlers.size());
if (checked.get(position)) {
Log.i("Adding","Adding::"+checked.get(position));
CheckedFitlers.add(SelectedFilter1.get(position));
for(int i=0;i<checkekprev.size();i++){
//Log.i("Checked Filters FOr loop","Checked Filters:"+CheckedFitlers.get(i));
}
} else
{
Log.i("Removing","Removing::"+checked.get(position)+":"+SelectedFilter1.get(position));
CheckedFitlers.remove(SelectedFilter1.get(position));
for(int i=0;i<checkekprev.size();i++){
//Log.i("Checked Filters for loop","Checked Filters:"+CheckedFitlers.get(i));
}
}
Log.i("CheckedFitlers","CheckedFitlers:::" + CheckedFitlers.size());
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_list_view, container, false);
myListView=(ListView) rootView.findViewById(R.id.listView_brand);
editsearch = (EditText) rootView.findViewById(R.id.search);
selectAll=(CheckBox) rootView.findViewById(R.id.checkBox1);
selectAll.setFocusable(false);
return rootView;
}
public void onSaveInstanceState(Bundle savedInstanceState){
super.onSaveInstanceState(savedInstanceState);
Log.i("savedInstanceState in listfragment","savedInstanceState in listfragment");
//onCheckedItemsLister.someEvent(CheckedFitlers,SELECTED_FILTER);
onCheckedItemsLister.getSelectedFilter(SELECTED_FILTER);
}
}
When you typed 'W' in the edit text we are displayed with two values i.e. WF and WH. The selection is made for WF(first item displayed).
But you have performed action for first row of a listview, Now the checkbox of listview is checked and when clearing the characters in the edit text, your are seeing the complete list of the list view with first box checked. which is correct.
If you want to avoid this issues, Create custom adapter and override getfilter method.
Otherwise, Create your own logic and call listView.setItemChecked( stored positions, true/false); in ontextchanged.
In this example, let's say that the activity labels and listview items have equal values. There are 10 items from WF to WZ. (I sampled with 4 items) When "WZ" is typed in the edittext, the "WZ" item is displayed on the first line of the listview. When the first line is clicked, it is desirable to calling the "WZ" activity, not the "WF" activity. I've created the following little code for it, and it works fine.
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String v1 = getString(R.string.title_activity_wf).toString();
String v2 = getString(R.string.title_activity_wh).toString();
String v3 = getString(R.string.title_activity_wm).toString();
String v4 = getString(R.string.title_activity_wt).toString();
.
.
.
.
.
.
String selectedFromList = (String) (listView.getItemAtPosition(position));
if (selectedFromList.equalsIgnoreCase(v1)) {
startActivity(new Intent(getApplicationContext(), Wf.class));
} else if (selectedFromList.equalsIgnoreCase(v2)) {
startActivity(new Intent(getApplicationContext(), Wh.class));
} else if (selectedFromList.equalsIgnoreCase(v3)) {
startActivity(new Intent(getApplicationContext(), Wm.class));
} else if (selectedFromList.equalsIgnoreCase(v4)) {
startActivity(new Intent(getApplicationContext(), Wt.class));
}
});
Here is my first question on StackOverFlow, I usually always find an answer by myself but I am really stuck on a weird problem that I will explain here:
I implemented a ListView in a fragment activity, this listview contains a list of categories related to the current record that I get from the SQLLite database.
All is working fine, I created a SimpleCursorAdapter to retrieve the data from the DB and I display the categories correctly in the ListView.
The problem is related to the pre-fill of the checkboxes (it is a multiselection list), depending on how I try to pre-check the checkboxes, I get 2 cases:
First, the checkboxes are well pre-checked, but I cannot toggle the checkboxes anymore by clicking them. Second the click toggle well the checkboxes, but they are not pre-checked anymore...
Here is the part of the code where I have the problem:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//super.onCreate(savedInstanceState);
View v = inflater.inflate(R.layout.rate_fragment, container,false);
dbCategories = "";
displayCategories = resources.getText(R.string.no_categories).toString();
/** INITIALIZATION */
mViewSwitcher = (ViewSwitcher)v.findViewById(R.id.profileSwitcher);
/** Edition view */
rateGroup = (RadioGroup)v.findViewById(R.id.rate_group);
rateOne = (RadioButton)v.findViewById(R.id.one_button);
rateOne.setTag(1);
rateTwo = (RadioButton)v.findViewById(R.id.two_button);
rateTwo.setTag(2);
rateThree = (RadioButton)v.findViewById(R.id.three_button);
rateThree.setTag(3);
rateFour = (RadioButton)v.findViewById(R.id.four_button);
rateFour.setTag(4);
rateFive = (RadioButton)v.findViewById(R.id.five_button);
rateFive.setTag(5);
descET = (EditText)v.findViewById(R.id.editdescription);
descTextSize = descET.getTextSize();
descET.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
});
categoriesTV_edit = (TextView)v.findViewById(R.id.edit_categories);
categoriesBT = (Button) v.findViewById(R.id.select_categories);
categoriesBT.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
View categoriesListTitle = getActivity().getLayoutInflater().inflate(R.layout.category_list_title, null);
AlertDialog.Builder alt_bld = new AlertDialog.Builder(v.getContext()).setCustomTitle(categoriesListTitle);
categories = db.getAllCategoriesByRate(currentRate);
categoriesList = new ListView(getActivity());
categoriesList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
categoriesList.setClickable(true);
String[] fromColumns = new String[] {
DatabaseHandler.CATEGORY_NAME
};
int[] toViews = new int[]{
R.id.cat_checked
};
//mAdapter = new SimpleCursorAdapter(getActivity(), android.R.layout.simple_list_item_multiple_choice, categories, fromColumns, toViews, 0);
mAdapter = new SimpleCursorAdapter(getActivity(), R.layout.category_item, categories, fromColumns, toViews, 0);
mAdapter.setViewBinder(new ViewBinder() {
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
if (columnIndex == 1) {
CheckedTextView categRow = (CheckedTextView) view;
String catName = cursor.getString(1);
mAdapter.setViewText((TextView) view, catName);
int catChecked = cursor.getInt(2);
//boolean checkedCat = catChecked==1;
//categoriesList.setItemChecked(cursor.getPosition(),checkedCat);
categRow.setChecked(catChecked==1);
int catID = cursor.getInt(0);
categRow.setTag(catID);
return true;
}
else {
return false;
}
}
});
categoriesList.setAdapter(mAdapter);
alt_bld.setView(categoriesList);
To have one case or another, all depends on these 2 lines:
//boolean checkedCat = catChecked==1;
//categoriesList.setItemChecked(cursor.getPosition(),checkedCat);
If they are commented, the checkboxes are not pre-checked, but the toggle on the clicks is working. But if I comment these lines out, the toggle is not working anymore but the categories are prechecked.
What I also don't understand is that this line is not working:
categRow.setChecked(catChecked==1);
But this one is working well (I succeed to retrieve the tag):
categRow.setTag(catID);
So I hope someone will succeed to explain to me what I do wrong, I guess there is something I misunderstood here...
NOTE: I get 3 columns from the cursor "categories", first one is the ID of the category, second one is the name, and third one is the status: checked or not (1 or 0).
Thanks in advance for your time.
Finally I ended up creating my own custom adapter, this way I could at least understand more easily what was happening.
I had to create actually several multiselect lists, some populated with data from the database, others from the shared preferences.
For this one displaying data from the DB, I created the following adapter (I commented out the lines about the icons because I did not set them up yet):
public class CategoriesLVAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater mInflater;
private List<Category> categoriesList;
// Constructor
public CategoriesLVAdapter(Context c, List<Category> categories_list){
mContext = c;
mInflater = LayoutInflater.from(c);
categoriesList = categories_list;
}
public List<Category> getCategoriesList(){
return categoriesList;
}
#Override
public int getCount() {
return categoriesList.size();
}
#Override
public Object getItem(int position) {
return categoriesList.get(position);
}
#Override
public long getItemId(int position) {
return categoriesList.get(position).getID();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.categories_list_row, null);
//convertView.setLayoutParams(new ListView.LayoutParams(200, 90));
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.categories_list_row_tv);
//holder.icon = (ImageView) convertView.findViewById(R.id.categories_list_row_iv);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
//holder.icon.setImageResource(categoriesList.get(position).getDrawableID());
//holder.icon.setAdjustViewBounds(true);
//holder.icon.setScaleType(ImageView.ScaleType.CENTER_CROP);
holder.title.setText(categoriesList.get(position).getName());
return convertView;
}
static class ViewHolder {
TextView title;
//ImageView icon;
}
}
In my activity, I use this adapter when the AlertDialog is called to populate the ListView, then I pre-select the categories using the last ones saved in the shared preferences:
private void categoriesFilter(){
AlertDialog.Builder alt_bld = new AlertDialog.Builder(this);
alt_bld.setTitle(resources.getText(R.string.select_categories).toString());
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.categories_list,(ViewGroup) findViewById(R.id.categories_layout_root));
categoriesLV = (ListView) layout.findViewById(R.id.categories_list);
alt_bld.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String selectedCategoriesString = getSelectedValues(categoriesLV);
//Update the shared preferences
prefs.edit().putString(RateDayApplication.PREF_KEY_CATEGORIES, selectedCategoriesString).commit();
updateFilterDisplay(resources.getText(R.string.cat_title).toString(), selectedCategoriesString, searchedCategoriesTV, "Category");
}
});
alt_bld.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
});
String selectedCategoriesString = prefs.getString(RateDayApplication.PREF_KEY_CATEGORIES, new String());
categoriesLV.setAdapter(new CategoriesLVAdapter(this, categoriesList));
String[] selectedCategoriesArray = selectedCategoriesString.split(",");
int categoriesLVLength = categoriesLV.getCount();
for(int i = 0; i < categoriesLVLength; i++){
int categoryID = ((Category) categoriesLV.getItemAtPosition(i)).getID();
if(Arrays.asList(selectedCategoriesArray).contains(String.valueOf(categoryID))){
categoriesLV.setItemChecked(i, true);
}
}
alt_bld.setView(layout);
AlertDialog alert = alt_bld.create();
alert.show();
}
Finally here is the function I call from my database handler to get the list of catagories:
// Getting All Categories By ID desc
public List<Category> getCategoriesList() {
String selectQuery = "SELECT " + CATEGORY_ID + ", " + CATEGORY_NAME + " FROM " + CATEGORY_TABLE + " ORDER BY " + CATEGORY_ID + " ASC";
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
List<Category> categoriesList = new ArrayList<Category>();//String[] categoriesList = {};
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Category category = new Category(cursor.getInt(0), cursor.getString(1), false);
categoriesList.add(category);
} while (cursor.moveToNext());
}
cursor.close();
db.close();
return categoriesList;
}
I think my problem before was coming from the fact that the function "setItemChecked" is a little misleading because it does not mean necessarily that anything is checked.
When you use the function "setItemChecked", the item in the list view becomes selected, with or without a checkbox (my rows only contain text views).
The rows selected in my list appear in a different color, and that's enough in my opinion for a simple multi selection list.
The layouts I used are quite simple, "categories_list" contains a ListView in a LinearLayout and "categories_list_row" contains a TextView in a LinearLayout.
Hope it may guide someone!