Android listview with header layout - android

I am rephrasing my question. Please bear with me.
I have a Cursor, which has carNum and tasks needs to be done on that. So carNum repeats in table. Right now I am using SimpleCursorAdapter and displaying all the info as a listitem. What I would like to do is set carNum as a header of a list and tasks need to be done as listitems. In addition to this, I would like to make header it's own layout so that I can display carNum and some info about it. So now where should I start ?
How should I get distinct carNum from Cursor and make that as header ? And then get listitem for that ?
Here is the .java
public class MyTask extends Activity{
String empid;
ListView list;
Cursor cursor = null;
TextView text;
private DbAdapter_Assignment assignment;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listlayout);
empid = getIntent().getExtras().getString("EmpID");
getData(empid);
}
public void getData(final String empid)
{
assignment = new DbAdapter_Assignment(getBaseContext());
assignment.open();
cursor = assignment.getAcceptedTasks(empid);
startManagingCursor(cursor);
text = (TextView) findViewById(R.id.employeename);
text.setText(getEmployeeName(empid) + " has "+ Integer.toString (cursor.getCount()) + " tasks assigned." );
list = (ListView) findViewById(R.id.mytasklist);
list.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> adapterView, View v, int arg2,
long arg3) {
}
});
SimpleCursorAdapter adapter = new SimpleCursorAdapter (this, R.layout.mytaskslayout, cursor, new String[] {"A","B", "C", "D", "E", "F"}, new int[] {R.id.a, R.id.b, R.id.c, R.id.d, R.id.e, R.id.f});
list.setAdapter(adapter);

extend SimpleCursorAdapter
Build list of header indexes in the constructor
c.moveToFirst();
int headerIndex = -1;
String headerValue = null;
do {
headerIndex++;
String header = c.getString(getColumnClass());
if (!header.equalsIgnoreCase(headerValue)) {
mHeaderIndexes.add(headerIndex);
headerValue = header;
headerIndex++;
}
}while (c.moveToNext());
c.moveToFirst();
mDataCount = c.getCount()+mHeaderIndexes.size();
Override methods
#Override
public int getCount() {
return mDataCount;
}
#Override
public int getItemViewType(int position) {
if (mHeaderIndexes.contains(position)) {
return TYPE_HEADER_ROW;
}
return TYPE_ROW;
}
#Override
public Object getItem(int position) {
if (mHeaderIndexes.contains(position)) {
// for header row need return first row with data for this group
getCursor().moveToPosition(position-mHeaderIndexes.indexOf(position));
}
else {
for (int i = 0; i < mHeaderIndexes.size(); i++) {
if (mHeaderIndexes.get(i) > position) {
// need move back by number of headers before position
getCursor().moveToPosition(position - i);
break;
}
}
if (position>mHeaderIndexes.get(mHeaderIndexes.size()-1)) {
// if position is in the last group (position >last group header position)
// move back by number of headers
getCursor().moveToPosition(position - mHeaderIndexes.size());
}
}
return getCursor();
}
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public boolean isEnabled(int position) {
return !mHeaderIndexes.contains(position);
}
Implement getView()
public View getView(int position, View convertView, ViewGroup parent) {
int type = getItemViewType(position);
Cursor cursor = (Cursor) getItem(position);
View view = convertView;
if (type==TYPE_HEADER_ROW) {
boolean isHeader = view!=null && view.findViewById(R.id.title)!=null;
if (!isHeader) {
view = mInflater.inflate(R.layout.row_my_header, null);
}
TextView header = view.findViewById(R.id.title);
header.setText(...);
}
else {
if (view==null) {
view = mInflater.inflate(R.layout.row_my_data, null);
}
// fill data row
}
return view;
}

Related

Android ListView with Sqlite access

I build a activity with a listview.
Populate it by use of sqlite.
But, when I write a few records into the DB and than show the result in the listView.
He doesn't show all the records.
Thank a lot for you help.
debug screen
D/DstNote: Find all arrow info.
D/DstNote: Records : 3
D/DstNote: 454554
D/DstNote: 45545454
D/DstNote: Find all arrow info.
D/DstNote: Records : 3
D/DstNote: position : 0
D/DstNote: position : 1
Méthode to read the data into DB
public ArrayList<ArrowInfo> getAllArrowInfo() {
Log.d("DstNote", "Find all arrow info.");
ArrayList<ArrowInfo> allArrowInfo = new ArrayList<>();
String[] selectedColomns = new String[] {
COLOMN_ID, COLOMN_ARROW_REF, COLOMN_TYPE_ARC, COLOMN_FIELD_IN, COLOMN_FIELD_OUT
};
Cursor c = db.query(TABLE_NAME, selectedColomns, null, null, null, null, null);
c.moveToFirst();
Log.d("DstNote", ""+c.getCount());
while (c.moveToNext()) {
Log.d("DstNote", cursorToArrow(c).getArrowRef());
allArrowInfo.add(cursorToArrow(c));
}
return allArrowInfo;
}
the adapter
class ArrowInfoAdapter extends BaseAdapter {
private Context ctx;
private ArrayList<ArrowInfo> allArrayInfo;
public ArrowInfoAdapter(Context context, ArrayList<ArrowInfo> allArrayInfo) {
ctx = context;
this.allArrayInfo = allArrayInfo;
}
#Override
public int getCount() {
return (allArrayInfo != null) ? allArrowInfo.size() : 0;
}
#Override
public long getItemId(int position) {
return position;
}
#Nullable
#Override
public ArrowInfo getItem(int position) {
return allArrowInfo.get(position);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ArrowInfo currentArrowInfo = allArrowInfo.get(position);
View itemView = convertView;
if (itemView == null) {
itemView = getLayoutInflater().inflate(R.layout.simple_listview_arraw_info_item, parent, false);
}
Log.d("DstNote", "position : " + position);
TextView refArrow = (TextView) itemView.findViewById(R.id.refArrow);
TextView arcType = (TextView) itemView.findViewById(R.id.arctype_TextView);
TextView field = (TextView) itemView.findViewById(R.id.field_textview);
refArrow.setText(currentArrowInfo.getArrowRef());
arcType.setText(currentArrowInfo.getTypeArc().name());
field.setText((currentArrowInfo.getIndoor() == 0) ? "IN" : "OUT");
itemView.setTag(currentArrowInfo);
return itemView;
}
public void refresh() {
/*allArrowInfo.clear();
allArrowInfo.addAll(model.getAllArrowInfo());*/
notifyDataSetChanged();
}
}
and the create méthod
allArrowInfo = model.getAllArrowInfo();
for (ArrowInfo item : allArrowInfo) {
Log.d("DstNote", item.getArrowRef());
}
adapter = new ArrowInfoAdapter(getBaseContext(), allArrowInfo);
registerForContextMenu(arrowInfoListView);
arrowInfoListView.setAdapter(adapter);

Trying to get the _id when an item in gridview is clicked getting a cast exception

I am trying to get the _id field from the cursor when an item in my Grid View is clicked, the same code is working fine in a listview but does not seem to work here:
Class level:
CurAdapter Cur;
GridView grid;
onCreate:
Cursor mCur = dbHelper.contactsQuery();
grid = (GridView)rootView.findViewById(R.id.gridview);
Cur = new CurAdapter(getActivity(), mCur,0);
grid.setAdapter(Cur);
grid.setTextFilterEnabled(true);
onCLick:
grid.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
System.out.println(position);
System.out.println(id);
Cursor cursor = (Cursor) grid.getItemAtPosition(position);
}
});
My CustomAdapter:
private class CurAdapter extends CursorAdapter{
public CurAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
TextView tv = (TextView) view.findViewById(R.id.item_text);
tv.setTypeface(helv_light);
final RoundedImageView iv = (RoundedImageView) view.findViewById(R.id.item_image);
String name = (cursor.getString(cursor.getColumnIndexOrThrow("Name")));
image = cursor.getString(cursor.getColumnIndexOrThrow("imageUri"));
String isAdhoc = (cursor.getString(cursor.getColumnIndexOrThrow("isAdhoc")));
if(isAdhoc.equals("1")){
boolean check = false;
String frName = null;
Cursor mCur = dbHelper.friendsName(name);
if(mCur != null && mCur.moveToFirst()){
do{
frName = mCur.getString(mCur.getColumnIndex("FriendsName"));
if(frName != null){
if(frName.equalsIgnoreCase(selfName)){
check = false;
}else {
check = true;
}
}
}while (mCur.moveToNext());
}
if(check){
name = name+" "+"("+frName+"'s"+" pet)";
}
}
tv.setText(name);
if((image.contains("jpg") || image.contains("png")) && image.contains("adhoc") != true){
image = "file://"+image;
}
final DisplayImageOptions options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.icon_default)
.showImageForEmptyUri(R.drawable.icon_default)
.showImageOnFail(R.drawable.icon_default)
.resetViewBeforeLoading(true)
.cacheInMemory(true) // default
.cacheOnDisk(true) // default
.build();
ImageLoader.getInstance().displayImage(image, iv, options);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = LayoutInflater.from(context).inflate(R.layout.grid_layout, null);
return view;
}
public long getItemId(int position) {
return position;
}
public Object getItem(int position) {
return position;
}
}
My Problem:
11-10 14:51:47.989: E/AndroidRuntime(11194): java.lang.ClassCastException: java.lang.Integer cannot be cast to android.database.Cursor
11-10 14:51:47.989: E/AndroidRuntime(11194): at com.example.FragmentTab3$1.onItemClick(FragmentTab3.java:125)
you are getting the ClassCastException because you are overriding getItem
public Object getItem(int position) {
return position;
}
and in your case it is returning an int not the cursor. You can delete it and use the parent implementation of getItem (which should return the Cursor at position)
Exception is due to return int from getItem(..) as mentioned by blackbelt
This may also help you to get ID of the record - change getItemId(..) this way:
public long getItemId(int position) {
mCur.moveToPosition(position);
return mCur.getLong(mCur.getColumnIndex(BaseColumns._ID));
}

Delete an item from Array List contact to Custom List View always delteing the latest one

I have a custom list view, contains delete button and spinner (the spinner contain A-E characters).
And I have an issue with deleting the true row from my custom list view.
Custom list view code:
public class customListView extends BaseAdapter
{
public Activity context;
ArrayList<MyActivity.UserProperties> userPropertieses;
public String[] spinnerValues;
public LayoutInflater inflater;
public customListView(Activity context, ArrayList<MyActivity.UserProperties> userPropertieses, String[] spinnerArray)
{
super();
this.context = context;
this.userPropertieses = userPropertieses;
spinnerValues = spinnerArray;
this.inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() { return userPropertieses.size(); }
#Override
public Object getItem(int i) { return null; }
#Override
public long getItemId(int i) { return 0; }
class ViewHolder
{
Button btnRemove;
Spinner spinner;
}
#Override
public View getView(final int i, View view, ViewGroup viewGroup)
{
final ViewHolder holder;
if (view == null)
{
holder = new ViewHolder();
view = inflater.inflate(R.layout.custom_layout, null);
holder.spinner = (Spinner) view.findViewById(R.id.spinner);
holder.btnRemove = (Button) view.findViewById(R.id.bu_Remove);
// populate spinner
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>
(view.getContext(), android.R.layout.simple_spinner_item, spinnerValues);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
holder.spinner.setFocusable(true);
holder.spinner.requestFocus();
holder.spinner.setAdapter(dataAdapter);
view.setTag(holder);
// remove user implementation
holder.btnRemove.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.i("custom list view debug", "i = " + i); // debug. verify i value is correct
((MyActivity) context).deleteUser(i);
}
});
}
else
holder = (ViewHolder) view.getTag();
return view;
}
}
And my main activity code looks like this:
public class MyActivity extends Activity
{
ListView listView;
ArrayList<UserProperties> userProperties = new ArrayList<UserProperties>();
customListView adapter;
SensorManager sensorManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
for (int i = 0; i<5; i++) {
userProperties.add(new UserProperties());
}
listView = (ListView) findViewById(R.id.listView);
String[] spinnerValues = new String[] {"A", "B", "C", "D", "E"};
adapter = new customListView(MyActivity.this, userProperties, spinnerValues);
listView.setAdapter(adapter);
}
public void deleteUser (int index)
{
Log.i("debug", "Removing item " + index); // the index is really true and the true node deleting from the ArrayList but somehow the latest delete from the UI
userProperties.remove(index);
adapter.notifyDataSetChanged();
}
}
When I click on the Remove button deleteUser method called with the right index. but although the right node deleting from userProperties ArrayList somehow after notiftDataSetChanged is still alive
and the latest node delete.
So, How can I delete the right node/row (from the ArrayList and UI...)
Thank you!
EDIT:
Just to be clear, i variable contain true index. The true node deleted from the ArrayList. but something append after I called notify method.
I prefer to stay with BaseAdapter and not implement ArrayAdapter. Thank you!
EDIT 2:
After more debugging I found out my question was wrong. the true row really deleted just spinner values somehow update their values. I cannot close the question because it already answered. Thanks.
((MyActivity) context).deleteUser(i);
This line will always delete the first value from the ListView
You can use CAB (contextual action bar)
See if the code helps you(it's basically a ListActivity with a custom adapter to hold the status of checked items(+ different background)):
public class CABSelection extends ListActivity {
private ArrayList<String> mItems = new ArrayList<String>();
private SelectionAdapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
for (int i = 0; i < 24; i++) {
mItems.add("Name" + i);
}
// R.layout.adapters_cabselection_row is a LinearLayout(with green
// background(#99cc00)) that wraps an ImageView and a TextView
mAdapter = new SelectionAdapter(this,
R.layout.adapters_cabselection_row, R.id.the_text, mItems);
setListAdapter(mAdapter);
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
getListView().setMultiChoiceModeListener(new MultiChoiceModeListener() {
private int nr = 0;
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.cabselection_menu, menu);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
StringBuilder sb = new StringBuilder();
Set<Integer> positions = mAdapter.getCurrentCheckedPosition();
for (Integer pos : positions) {
sb.append(" " + pos + ",");
}
switch (item.getItemId()) {
case R.id.edit_entry:
Toast.makeText(CABSelection.this, "Edited entries: " + sb.toString(),
Toast.LENGTH_SHORT).show();
break;
case R.id.delete_entry:
Toast.makeText(CABSelection.this, "Deleted entries : " + sb.toString(),
Toast.LENGTH_SHORT).show();
break;
case R.id.finish_it:
nr = 0;
mAdapter.clearSelection();
Toast.makeText(CABSelection.this, "Finish the CAB!",
Toast.LENGTH_SHORT).show();
mode.finish();
}
return false;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
nr = 0;
mAdapter.clearSelection();
}
#Override
public void onItemCheckedStateChanged(ActionMode mode,
int position, long id, boolean checked) {
if (checked) {
nr++;
mAdapter.setNewSelection(position, checked);
} else {
nr--;
mAdapter.removeSelection(position);
}
mode.setTitle(nr + " rows selected!");
}
});
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
l.setItemChecked(position, !mAdapter.isPositionChecked(position));
}
private class SelectionAdapter extends ArrayAdapter<String> {
private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>();
public SelectionAdapter(Context context, int resource,
int textViewResourceId, List<String> objects) {
super(context, resource, textViewResourceId, objects);
}
public void setNewSelection(int position, boolean value) {
mSelection.put(position, value);
notifyDataSetChanged();
}
public boolean isPositionChecked(int position) {
Boolean result = mSelection.get(position);
return result == null ? false : result;
}
public Set<Integer> getCurrentCheckedPosition() {
return mSelection.keySet();
}
public void removeSelection(int position) {
mSelection.remove(position);
notifyDataSetChanged();
}
public void clearSelection() {
mSelection = new HashMap<Integer, Boolean>();
notifyDataSetChanged();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);//let the adapter handle setting up the row views
v.setBackgroundColor(Color.parseColor("#99cc00")); //default color
if (mSelection.get(position) != null) {
v.setBackgroundColor(Color.RED);// this is a selected position so make it red
}
return v;
}
}
}
Another way
adapter = new MyListAdapter(this);
lv = (ListView) findViewById(android.R.id.list);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
AlertDialog.Builder adb=new AlertDialog.Builder(MyActivity.this);
adb.setTitle("Delete?");
adb.setMessage("Are you sure you want to delete " + position);
final int positionToRemove = position;
adb.setNegativeButton("Cancel", null);
adb.setPositiveButton("Ok", new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
MyDataObject.remove(positionToRemove);
adapter.notifyDataSetChanged();
}});
adb.show();
}
});
getView(final int i,
Do not make i final. You did that to use i in onClick(). But that is not possible. So remove the final. Add:
holder.btnRemove.setTag(i);
And in onClick:
int position = v.getTag();
..deleteUser(position);
Maybe you have to cast something somewhere..
Remark: You have to set the tag always. So do it just before return view;.
Please do not use an i for position.

Get custom itemsAdapter id using cursor android

I'm trying to pass the item clicked to another activity i.e from A to B using a custom itemsAdapter with sqlite.
How can I achieve the following?
1)Get the item clicked position using cursor
2)Pass the item clicked to another activity
I'm trying to do similar to this example but use my own custom adapter
I have dome the following so far.
Activity A:
public void onListItemClick(ListView parent, View view, int position, long id) {
Intent intent = new Intent(this,F32Activity.class);
Cursor cursor = (Cursor) itemsAdapter.getItem(position);
intent.putExtra("PROPERTY_ID", cursor.getInt(cursor.getColumnIndex("_id")));
startActivity(intent);
return;
}
Activity B:
propertyId = getIntent().getIntExtra("PROPERTY_ID", 0);
System.out.println(employeeId);
SQLiteDatabase db = (new Helper(this)).getWritableDatabase();
Cursor cursor = db
.rawQuery("SELECT * from my_table WHERE pro._id = ?",
new String[] { "" + propertyId });
Added the Adapter
private void getItemId(int position) {
// TODO Auto-generated method stub
}
private void getDataAndPopulate() {
// TODO Auto-generated method stub
image = new ArrayList<byte[]>();
bedrooms= new ArrayList<String>();
address= new ArrayList<String>();
propType= new ArrayList<String>();
Cursor cursor = getEvents(" gall,properties where properties._id = gall._id " );
while (cursor.moveToNext()) {
//String temp_id = cursor.getString(0);
byte[] temp_image = cursor.getBlob(2);
String temp_identifier = cursor.getString(1);
String temp_price = cursor.getString(3);
String temp_bedrooms = cursor.getString(4);
String temp_address = cursor.getString(5);
String temp_propType = cursor.getString(6);
image.add(temp_image);
//System.out.println(image);
bedrooms.add(temp_bedrooms);
address.add(temp_address);
propType.add(temp_propType);
}
String[] identifierArray = (String[]) bedrooms.toArray(new String[bedrooms
.size()]);
itemsAdapter = new ItemsAdapter(PropertyResult.this,
cursor, R.layout.activity_f9, identifierArray);
setListAdapter(itemsAdapter);
}
private class ItemsAdapter extends BaseAdapter {
String[] items;
public ItemsAdapter(Context context, Cursor cursor,int textViewResourceId,
String[] items) {
this.items = items;
}
public View getView(final int POSITION, View convertView,
ViewGroup parent) {
TextView desc;
TextView cap;
TextView ident;
TextView pric;
TextView bedroom;
TextView addres;
TextView propertytyp;
View view = convertView;
ImageView img;
if (view == null) {
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = vi.inflate(R.layout.activity_f9, null);
}
img = (ImageView) view.findViewById(R.id.image);
bedroom = (TextView) view.findViewById(R.id.bedrooms);
addres = (TextView) view.findViewById(R.id.address);
propertytyp = (TextView) view.findViewById(R.id.propertytype);
bedroom.setText("£"+bedrooms.get(POSITION));
addres.setText(address.get(POSITION));
propertytyp.setText(propType.get(POSITION));
img.setImageBitmap(BitmapFactory.decodeByteArray(
image.get(POSITION), 0, image.get(POSITION).length));
return view;
}
public int getCount() {
return items.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
}
Please kindly give me a solution.
In the onListItemClick() you already have the row id from the cursor, is the 4th parameter, id(this only works for cursor adapters).
First of all also create and ArrayList that will hold long values(the row ids from the cursor):
ids = new ArrayList<Long>();
//...
while (cursor.moveToNext()) {
String temp_id = cursor.getString(0);// if 0 is your column containing the id(check it)
ids.add(temp_id);
//...
}
Then in your adapter override the method getItemId and return the long values from the ids ArrayList according to the position supplied:
public long getItemId(int position) {
return ids.get(position);
}
Then in your onListItemClick() simply use the id parameter:
public void onListItemClick(ListView parent, View view, int position, long id) {
Intent intent = new Intent(this,F32Activity.class);
intent.putExtra("PROPERTY_ID", id);
startActivity(intent);
}
Then in the receiving activity:
propertyId = getIntent().getLongExtra("PROPERTY_ID", 0);
Your on Item should like this
public void onItemClick(AdapterView<?> arg0, View arg1, int position,
long arg3) {
String strEventName, strEventDate;
int Id;
Cursor c = (Cursor) arg0.getAdapter().getItem(position);
intent.putExtra("PROPERTY_ID", cursor.getInt(cursor.getColumnIndex("_id")));
startActivity(intent);}

Changing the Adapter at runtime

I am using an adapter to display the result of a cursor on a separate screen in alphabetical order. The problem is I need to use an EditText field to filter the result.
When I do this with the filter adapter always gives error due to the index properties of each alphabetical letter which he must redo. So I thought I'd change the adapter to a simple, no alphabetical division only when the user makes the filter for the search field.
I leave the original adapter and the adapter without a filter to search I add the filter that will run another cursor. This exchange of Adapter at runtime given problem: when I change the X Adapter (without filterqueryprovider) for the Y-Adapter (with filterqueryprovider) works normal .. but when the reverse is true filterqueryprovider just running in the X Adapter and the result of the cursor does not appear. How to solve this problem?
See the code below the adapter and my Activity
Adapter:
/**
* CursorAdapter that uses an AlphabetIndexer widget to keep track of the section indicies.
* These are the positions where we want to show a section header showing the respective alphabet letter.
* #author Eric
*
*/
public class OrdemAlfabeticaAdapter extends SimpleCursorAdapter implements SectionIndexer{
private static final int TYPE_HEADER = 1;
private static final int TYPE_NORMAL = 0;
private static final int TYPE_COUNT = 2;
private AlphabetIndexer indexer;
private int[] usedSectionNumbers;
private Map<Integer, Integer> sectionToOffset;
private Map<Integer, Integer> sectionToPosition;
private Context context;
public OrdemAlfabeticaAdapter(Context context, int layout, Cursor c, String coluna,
String[] from, int[] to) {
super(context, layout, c, from, to);
this.context = context;
indexer = new AlphabetIndexer(c, c.getColumnIndexOrThrow(coluna), "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
sectionToPosition = new TreeMap<Integer, Integer>(); //use a TreeMap because we are going to iterate over its keys in sorted order
sectionToOffset = new HashMap<Integer, Integer>();
final int count = super.getCount();
int i;
//temporarily have a map alphabet section to first index it appears
//(this map is going to be doing somethine else later)
for (i = count - 1 ; i >= 0; i--){
sectionToPosition.put(indexer.getSectionForPosition(i), i);
}
i = 0;
usedSectionNumbers = new int[sectionToPosition.keySet().size()];
//note that for each section that appears before a position, we must offset our
//indices by 1, to make room for an alphabetical header in our list
for (Integer section : sectionToPosition.keySet()){
sectionToOffset.put(section, i);
usedSectionNumbers[i] = section;
i++;
}
//use offset to map the alphabet sections to their actual indicies in the list
for(Integer section: sectionToPosition.keySet()){
sectionToPosition.put(section, sectionToPosition.get(section) + sectionToOffset.get(section));
}
}
#Override
public int getCount() {
if (super.getCount() != 0){
//sometimes your data set gets invalidated. In this case getCount()
//should return 0 and not our adjusted count for the headers.
//The only way to know if data is invalidated is to check if
//super.getCount() is 0.
return super.getCount() + usedSectionNumbers.length;
}
return 0;
}
#Override
public Object getItem(int position) {
if (getItemViewType(position) == TYPE_NORMAL){//we define this function in the full code later
//if the list item is not a header, then we fetch the data set item with the same position
//off-setted by the number of headers that appear before the item in the list
return super.getItem(position - sectionToOffset.get(getSectionForPosition(position)) - 1);
}
return null;
}
#Override
public int getPositionForSection(int section) {
if (! sectionToOffset.containsKey(section)){
//This is only the case when the FastScroller is scrolling,
//and so this section doesn't appear in our data set. The implementation
//of Fastscroller requires that missing sections have the same index as the
//beginning of the next non-missing section (or the end of the the list if
//if the rest of the sections are missing).
//So, in pictorial example, the sections D and E would appear at position 9
//and G to Z appear in position 11.
int i = 0;
int maxLength = usedSectionNumbers.length;
//linear scan over the sections (constant number of these) that appear in the
//data set to find the first used section that is greater than the given section, so in the
//example D and E correspond to F
while (i < maxLength && section > usedSectionNumbers[i]){
i++;
}
if (i == maxLength) return getCount(); //the given section is past all our data
return indexer.getPositionForSection(usedSectionNumbers[i]) + sectionToOffset.get(usedSectionNumbers[i]);
}
return indexer.getPositionForSection(section) + sectionToOffset.get(section);
}
#Override
public int getSectionForPosition(int position) {
int i = 0;
int maxLength = usedSectionNumbers.length;
//linear scan over the used alphabetical sections' positions
//to find where the given section fits in
while (i < maxLength && position >= sectionToPosition.get(usedSectionNumbers[i])){
i++;
}
return usedSectionNumbers[i-1];
}
#Override
public Object[] getSections() {
return indexer.getSections();
}
//nothing much to this: headers have positions that the sectionIndexer manages.
#Override
public int getItemViewType(int position) {
if (position == getPositionForSection(getSectionForPosition(position))){
return TYPE_HEADER;
}
return TYPE_NORMAL;
}
#Override
public int getViewTypeCount() {
return TYPE_COUNT;
}
//return the header view, if it's in a section header position
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final int type = getItemViewType(position);
if (type == TYPE_HEADER){
if (convertView == null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
// convertView = getLayoutInflater().inflate(R.layout.header, parent, false);
convertView = inflater.inflate(R.layout.cabecalho_divisao_alfabetica, parent, false);
}
((TextView)convertView.findViewById(R.id.header)).setText((String)getSections()[getSectionForPosition(position)]);
return convertView;
}
return super.getView(position - sectionToOffset.get(getSectionForPosition(position)) - 1, convertView, parent);
}
//these two methods just disable the headers
#Override
public boolean areAllItemsEnabled() {
return false;
}
#Override
public boolean isEnabled(int position) {
if (getItemViewType(position) == TYPE_HEADER){
return false;
}
return true;
}
public AlphabetIndexer getIndexer() {
return indexer;
}
}
My Activity:
public class BuscaProprietarioActivity extends ListActivity {
private SimpleCursorAdapter adapter1;
private SimpleCursorAdapter adapter2;
private EditText filterEditText;
private LinearLayout viewNenhumRegistroEncontrado;
private LinearLayout viewResultado;
private final String[] colunas = new String[] { ProprietarioProvider.Columns.ID,
ProprietarioProvider.Columns.NOME, ProprietarioProvider.Columns.TELEFONE };
private Cursor cursor;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.proprietario_busca);
filterEditText = (EditText) findViewById(R.id.busca_proprietario_campo_busca);
ContentResolver cr = getContentResolver();
Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
String s = "'%" + query + "%'";
String selection = ProprietarioProvider.Columns.NOME + " LIKE " + s;
cursor = cr.query(ProprietarioProvider.CONTENT_URI, colunas, selection, null,
ProprietarioProvider.Columns.NOME + " COLLATE LOCALIZED ASC");
} else {
cursor = cr.query(ProprietarioProvider.CONTENT_URI, colunas, null, null,
ProprietarioProvider.Columns.NOME + " COLLATE LOCALIZED ASC");
}
if (cursor.moveToNext()) {
viewResultado = (LinearLayout) findViewById(R.id.busca_proprietario_resultado);
viewResultado.setVisibility(View.VISIBLE);
adapter1 = new OrdemAlfabeticaAdapter(this, R.layout.list_item_proprietario,
cursor, ProprietarioProvider.Columns.NOME, new String[]{ProprietarioProvider.Columns.NOME,
ProprietarioProvider.Columns.TELEFONE},
new int[]{R.id.list_item_proprietario_nome, R.id.list_item_proprietario_telefone});
setListAdapter(adapter1);
adapter2 = new SimpleCursorAdapter(getApplicationContext(),
R.layout.list_item_proprietario, cursor, new String[]{ProprietarioProvider.Columns.NOME,
ProprietarioProvider.Columns.TELEFONE},
new int[]{R.id.list_item_proprietario_nome, R.id.list_item_proprietario_telefone});
adapter2.setFilterQueryProvider(filterQueryProvider);
filterEditText = (EditText) findViewById(R.id.busca_proprietario_campo_busca);
filterEditText.addTextChangedListener(filterTextWatcher);
} else {
// mostra tela de registro nao encontrado
viewNenhumRegistroEncontrado = (LinearLayout) findViewById(R.id.busca_proprietario_nenhum_registro_encontrado);
viewNenhumRegistroEncontrado.setVisibility(View.VISIBLE);
}
}
private FilterQueryProvider filterQueryProvider = new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
String selection = ProprietarioProvider.Columns.NOME + " LIKE '"+constraint+"%'";
cursor = getContentResolver().query(ProprietarioProvider.CONTENT_URI, colunas, selection, null,
ProprietarioProvider.Columns.NOME + " COLLATE LOCALIZED ASC");
return cursor;
}
};
private TextWatcher filterTextWatcher = new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
if (s != null && s.length() > 0) {
setListAdapter(adapter2);
getListView().setTextFilterEnabled(true);
adapter2.getFilter().filter(s.toString());
getListView().setFastScrollEnabled(false);
} else {
setListAdapter(adapter1);
getListView().setFastScrollEnabled(true);
}
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
};
}
If you have already set your adapter, setting it again won't update the UI. you will need to use the adapter.notifyDataSetChanged()
https://stackoverflow.com/a/7920243/563306

Categories

Resources