GetChildView gets not called - android-listview

I have searched similar threads but they didn't help me and they were light different or they still are unanswered, so I'll describe my trouble.
I have an ExpandableListView with a custom ExpandableListAdapter and I can show my Groups but not my Children. GetChildView don't get called anyway.
I would thank you for your Help.
EDIT:
If I log this section
...
client = (ExpandableListView)row.findViewById(R.id.field_expandable_list);
client.setFocusable(false);
client_adapter = new ClientAdapter(context, titles, allFields);
client.setAdapter(client_adapter);
Log.i("TAG", "WmsMApActivity::doClient:: Adapter #children: "+client_adapter.getChildrenCount(0)+
" ExpListView #children: "+client.getChildCount());
...
, then I get that
I/TAG(692): WmsMApActivity::doClient::0 Adapter #children: 13 ExpListView #children: 0
So, my Adapter gets Data but the variable client (ExpandableListView) don't realize, it has data although I properly set it.
My code is the following
Main Code
// view = Item of my ListView. We come from a OnClickItem Method
private void doClient(View view) {
ArrayList<String> titles = new ArrayList<String>();
titles.add("fields");
ArrayList allFields = transformFarmsResult(parentItems);
final Context context = getApplicationContext();
RelativeLayout mainLayout = (RelativeLayout) view.findViewById(R.id.relLayoutDrawer);
// We check whether the first item (0th position) is expanded
View lin_layout_field_list = view.findViewById(R.id.lin_layout_field_list);
if ( lin_layout_field_list != null ) { // Hide Field_list Layout
((ViewGroup) view).removeView(lin_layout_field_list);
} else {
mainLayout = (RelativeLayout) view.findViewById(R.id.relLayoutDrawer);
// ----------- Inflating ExpandableListView "Fields"
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.field_list, null);
client = (ExpandableListView)row.findViewById(R.id.field_expandable_list);
// Adapter Population
client_adapter = new ClientAdapter(context, titles, allFields);
client.setAdapter(client_adapter);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
TextView title_tv = (TextView)view.findViewById(R.id.title);
params.addRule(RelativeLayout.ALIGN_LEFT, title_tv.getId() );
params.addRule(RelativeLayout.BELOW, title_tv.getId());
mainLayout.addView(row, params);
// Listview Group click listener
client.setOnGroupClickListener(new OnGroupClickListener() {
#Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
Toast.makeText(context, "Group Clicked " + groupPosition, Toast.LENGTH_SHORT).show();
return false;
}
});
// Listview Group expanded listener
client.setOnGroupExpandListener(new OnGroupExpandListener() {
#Override
public void onGroupExpand(int groupPosition) {
Toast.makeText(context, "Group " + groupPosition + " Expanded", Toast.LENGTH_SHORT).show();
}
});
// Listview Group collasped listener
client.setOnGroupCollapseListener(new OnGroupCollapseListener() {
#Override
public void onGroupCollapse(int groupPosition) {
Toast.makeText(context, "Group " + groupPosition + " Collapsed", Toast.LENGTH_SHORT).show();;
}
});
// Listview on child click listener
client.setOnChildClickListener(new OnChildClickListener() {
#Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
// TODO Auto-generated method stub
Toast.makeText(context, "Group " + groupPosition + " : Child " + childPosition, Toast.LENGTH_SHORT).show();
return false;
}
});
}
}
Adapter
public class ClientAdapter extends BaseExpandableListAdapter{
private Context context;
//private String header_title;
private ArrayList<String> headers;
private ArrayList fields;
private int groupPosition = 0;
private LayoutInflater inflater;
public ClientAdapter(Context context, ArrayList<String> headers, ArrayList fields) {
this.context = context;
this.headers = headers;
this.fields = fields;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// Just to check, whether I get correct ArrayList "fields"
Log.i("TAG","ClientAdapter::Constructor:: fields.size: "+fields.size());
for (int i=0;i<fields.size();i++)
Log.i("TAG","ClientAdapter::Constructor:: field["+i+"]: "+fields.get(i).toString());
}
#Override
public int getGroupCount() {
// Just 1 Group
return headers.size();
}
#Override
public String getGroup(int groupPosition) {
return headers.get(groupPosition);
}
#Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
#Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View view = convertView;
GroupHolder holder=null;
String title_item = getGroup(groupPosition);
if ( view == null ) {
holder = new GroupHolder();
view = inflater.inflate(R.layout.group_client, null);
holder.title = (TextView) view.findViewById(R.id.client_group_title);
view.setTag(holder);
} else {
holder = (GroupHolder) view.getTag();
}
holder.title.setText(title_item);
return view;
}
// Children
#Override
public int getChildrenCount(int groupPosition) {
return fields.size();
}
#Override
public Object getChild(int groupPosition, int childPosition) {
// TODO Auto-generated method stub
return fields.get(childPosition);
}
#Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
#Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View view = convertView;
ChildHolder holder;
Log.i("TAG", "ClientAdapter::getChildView:: 0 - parent.id: "+parent.getId());
final HashMap<String,Object> field = (HashMap<String,Object>) getChild(groupPosition, childPosition);
if (view == null) {
holder = new ChildHolder();
view = inflater.inflate(R.layout.child_client, null);
holder.title = (TextView) view.findViewById(R.id.client_child_title);
holder.map_icon = (ImageView) view.findViewById(R.id.client_child_icon);
holder.contour = (CheckBox) view.findViewById(R.id.client_child_checkbox);
convertView.setTag(holder);
} else {
holder = (ChildHolder) view.getTag();
}
// Handling of Title
String temp =(String)field.get(Constants._FIELDNAME);
Log.i("TAG", "ClientAdapter::getChildView:: title: "+temp);
holder.title.setText((String)field.get(Constants._FIELDNAME));
// Handling of Contour - If it exists!
if ( field.containsKey(Constants._BOUNDARY)) {
holder.contour.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (((CheckBox)v).isChecked()) {
Toast.makeText(context, "Contour enabled", Toast.LENGTH_LONG).show();
// TODO : Fade-in Contour in Graphics
} else {
Toast.makeText(context, "Contour disabled", Toast.LENGTH_LONG).show();
// TODO : Fade-in Contour in Graphics
}
}
});
} else { // If there is no Contour, remains the checkbox but it's not clickable, so, it's grey!
holder.contour.setFocusable(false);
holder.contour.setClickable(false);
}
// Handling of Map Icon
Bitmap bitmap_icon = BitmapFactory.decodeResource(context.getResources(), R.drawable.gmaps_icon_24);
holder.map_icon.setImageBitmap(bitmap_icon);
// Applying gray filter if not referentiable
if ( !field.containsKey(Constants._LATITUDE) || !field.containsKey(Constants._LONGITUDE))
holder.map_icon.setColorFilter(Color.GRAY);
holder.map_icon.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if ( field.containsKey(Constants._LATITUDE) && field.containsKey(Constants._LONGITUDE)) {
Toast.makeText(context, "Center in Field Position", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(context, Constants.NOT_CENTRED, Toast.LENGTH_LONG).show();
}
}
});
return view;
}
#Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
// TODO Auto-generated method stub
return true;
}
#Override
public boolean hasStableIds() {
return true;
}
/** Events **/
/** Holder Classes **/
private static class ChildHolder {
TextView title;
ImageView map_icon;
CheckBox contour;
}
private static class GroupHolder {
TextView title;
}
}
My Layouts.
Main xml. field_list.xml -> Layout for ExpandableListView
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/lin_layout_field_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ExpandableListView
android:id="#+id/field_expandable_list"
android:layout_width="match_parent"
android:layout_height="0dp" <- That's a SO advice, in order that children won't be croped. Originally wrap_content
android:layout_weight="1"
android:headerDividersEnabled="true"
android:divider="#color/metallic_silver"
android:dividerHeight="1dp">
</ExpandableListView>
</LinearLayout>
Group_client.xml -> Layout for each Group Item
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/lin_layout_client_group"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/client_group_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="30dp"
android:text="Something"
android:textColor="#android:color/white"
android:textSize="16dp"
android:textStyle="normal" />
</LinearLayout>
</LinearLayout>
child_client.xml -> Layout for each Child Item
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/lin_layout_client_child"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<CheckBox
android:id="#+id/client_child_checkbox"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="0.05"
android:checked="true"
android:gravity="center_vertical|center" />
<TextView
android:id="#+id/client_child_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:padding="10dp"
android:text="FIELD_NAME"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#android:color/white"
android:layout_weight="0.90" />
<ImageView
android:id="#+id/client_child_icon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="0.05"
android:layout_margin="5dp"
android:gravity="center_vertical|center"
android:src="#drawable/gmaps_icon_24" />
</LinearLayout>
</LinearLayout>
EDIT(2):
As said, it's no problem cause of Layouts or ClientAdapter, so that it works fine in this example
public class ClientActivity2 extends Activity{
private ExpandableListView client;
private ClientAdapter client_adapter;
private ArrayList children;
private ArrayList<String> groups;
private LayoutInflater inflater;
private LinearLayout lin_layout_probe;
private Context context;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.field_list);
context = getApplicationContext();
prepareData();
ExpandableListView client = (ExpandableListView)findViewById(R.id.field_expandable_list);
client_adapter = new ClientAdapter(context, groups, children);
client.setAdapter(client_adapter);
client.expandGroup(0);
}
private void prepareData() {
children = new ArrayList();
HashMap<String,Object> hm1 = new HashMap<String,Object>();
hm1.put(Constants._FIELDNAME,"Child1");
children.add(hm1);
HashMap<String,Object> hm2 = new HashMap<String,Object>();
hm2.put(Constants._FIELDNAME,"Child2");
children.add(hm2);
HashMap<String,Object> hm3 = new HashMap<String,Object>();
hm3.put(Constants._FIELDNAME,"Child3");
children.add(hm3);
groups = new ArrayList<String>();
groups.add("Group1");
}
}
Now it comes what confuses me...
If I test all(Adapter and the same calls) with a simple Activity, which has a clickable TextView at its main layout then works fine!
If I click this TextView then the ExpandableListView prompts with properly populated Group and Children and they are expandable/collapsable.
If I test like my last post hier,(ExpandableListView embedded in a ListView Item) so, the ExpandableListView prompts, if I click that the ExpandableListView of that Item
then the groups are populated but not the children. GetChildView gets never called!!!(I used LogCat, so I'm completely sure)
I have seen, many people had troubles with clicks in ExpandableListViews in ListViewItems, my case is different, I can perform that, my trouble is understanding, why with a TextView works fine that ExpandableListView Population via my custom BaseExpandableListAdapter but not in a ListView Item.

Solved
In my first level Adapter (An adapter for the first level ExpandableListView) I modified the getChildView Method
...
// Member Field
private ExpandableListView expandable_field_list;
...
#Override
public View getChildView(int groupPosition, int childPosition,boolean isLastChild, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
if ( groupPosition == 1 ) {
if ( expandable_field_list == null ) {
expandable_field_list = new CustomExpandableListView(context);
// Here I initialize the second and third Level
client_adapter = new ClientAdapter(context, groups, children);
expandable_field_list.setAdapter(client_adapter);
} else {
client_adapter.notifyDataSetChanged();
}
convertView = expandable_field_list;
}
return convertView;
}
...
And CustomExpandableListView looks like this
public class CustomExpandableListView extends ExpandableListView {
private boolean expanded = true;
public CustomExpandableListView(Context context) {
super(context);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (isExpanded()) {
// View.MEASURED_SIZE_MASK represents the largest height possible.
int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
#Override
protected void onDetachedFromWindow() {
try {
super.onDetachedFromWindow();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
public void setIsExpanded(boolean expanded) {
this.expanded = expanded;
}
public boolean isExpanded() {
return expanded;
}
}
That is its aspect now as desired

Related

Delete data from database and listview on button click in android

I am trying to delete a record trough listview from database. I am somehow got suceed in removing the record from list but didn't find any help to delete it from database.
Below is the code of my adapter. Any help will be appreciated.
Thanks in advance.
public class Row_keyskill extends BaseAdapter implements View.OnClickListener {
private ArrayList<String> listName=new ArrayList<String>();
private Activity activity;
private Context context;
String id;
SQLiteDatabase db;
int position,position1;
public Row_keyskill(Activity activity, ArrayList<String> listName) {
super();
this.listName = listName;
this.activity = activity;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return listName.size();
}
#Override
public String getItem(int position) {
// TODO Auto-generated method stub
return listName.get(position);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public void onClick(View v) {
Toast.makeText(context,"row item clicked"+listName.get(position),Toast.LENGTH_LONG).show();
/* int position = (Integer) v.getTag();
id = listName.get(position);
// listName.remove(position);
Log.e("Row_keyskill", "position id: "+id);
position1=position+1;
Log.e("Row_keyskill", "position1 id: "+position1);
db.execSQL("DELETE FROM USER_SKILLS WHERE U_SKILL_NAME ='" + id + "'");
// itemDelete();*/
}
public static class ViewHolder
{
public TextView txtName;
public ImageView btn_delete;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder view;
LayoutInflater inflator = activity.getLayoutInflater();
if(convertView==null)
{
view = new ViewHolder();
convertView = inflator.inflate(R.layout.rowdata_keyskill,null);
view.txtName = (TextView) convertView.findViewById(R.id.keyskill_row);
// view.btn_delete=(ImageView)convertView.findViewById(R.id.btn_delete);
// view.btn_delete.setTag(position);
convertView.setTag(view);
}
else
{
view = (ViewHolder) convertView.getTag();
}
view.txtName.setText(listName.get(position));
//view.btn_delete.setOnClickListener(this);
ImageView btn_delete=(ImageView)convertView.findViewById(R.id.btn_delete);
btn_delete.setTag(position);
btn_delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//do something
int position = (Integer) v.getTag();
// SQLiteDatabase db = context.openOrCreateDatabase("JOB_PORTAL", Context.MODE_PRIVATE, null);
id = listName.get(position);
// listName.remove(position);
Log.e("Row_keyskill", "position id: " + id);
position1=position+1;
Log.e("Row_keyskill", "position1 id: "+position1);
listName.remove(position);
itemDelete(id);
//
//id = listName.get(position);
// db.execSQL("DELETE * FROM USER_SKILLS WHERE U_SKILL_NAME ='" + position + "'");
// db.delete("USER_SKILLS", new String("U_SKILL_NAME=?"), new String[]{id});
//or some other task*/
notifyDataSetChanged();
}
});
return convertView;
}
}
private void itemDelete(String id) {
//db = null;
try {
// db = context.openOrCreateDatabase("JOB_PORTAL", Context.MODE_PRIVATE,null);
// db.delete("USER_SKILLS", new String("U_SKILL_ID=?"), new String[]{id});
db.execSQL("DELETE FROM USER_SKILLS WHERE U_SKILL_NAME ='" + id + "'");
} catch (SQLException se) {
Toast.makeText(context, "Database error: " + se, Toast.LENGTH_LONG).show();
}
}

Passing Text From Listview to another Activity when I click action item of the listview

I have a listview in my main activity.In each row i have a image view,when i click that image view QuickAction(Like popover in ios) will appears.My request is, I want to setText the text from listview to the another Activity's edittext when i click the action item in the quick action.Please help..
Here is my Main Activity
public class ExampleActivity extends Activity {
private static final int ID_UP = 1;
private static final int ID_DOWN = 2;
private static final int ID_SEARCH = 3;
private static final int ID_INFO = 4;
private QuickAction quickAction;
private ActionItem nextItem;
private ActionItem prevItem;
private ActionItem searchItem;
private ListView view;
private ContactsAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
view = (ListView) findViewById(R.id.listView1);
final Weather weather_data[] = new Weather[] { new Weather(R.drawable.icon, "Cloudy"),
new Weather(R.drawable.icon, "Showers"),
new Weather(R.drawable.icon, "Snow"),
new Weather(R.drawable.icon, "Storm"),
new Weather(R.drawable.icon, "Sunny")
};
adapter = new ContactsAdapter(this, R.layout.main1,
weather_data);
}
void functiontorun(View view1) {
quickAction = new QuickAction(this,QuickAction.HORIZONTAL);
nextItem = new ActionItem(ID_DOWN, "Next", getResources().getDrawable(
R.drawable.menu_down_arrow));
prevItem = new ActionItem(ID_UP, "Prev", getResources().getDrawable(
R.drawable.menu_up_arrow));
searchItem = new ActionItem(ID_SEARCH, "Find", getResources()
.getDrawable(R.drawable.menu_search));
// use setSticky(true) to disable QuickAction dialog being dismissed
// after an item is clicked
prevItem.setSticky(true);
nextItem.setSticky(true);
// add action items into QuickAction
quickAction.addActionItem(nextItem);
quickAction.addActionItem(prevItem);
quickAction.addActionItem(searchItem);
// Set listener for action item clicked
final int position1 = view.getPositionForView(view1);
quickAction
.setOnActionItemClickListener(new QuickAction.OnActionItemClickListener() {
#Override
public void onItemClick(QuickAction source, int pos,
int actionId) {
ActionItem actionItem = quickAction.getActionItem(pos);
if (actionId == ID_SEARCH) {
Intent i=new Intent(ExampleActivity.this,Second.class);
i.putExtra("position",position1 );
Log.v("position","po" +position1);
startActivity(i);
} else if (actionId == ID_INFO) {
Toast.makeText(getApplicationContext(),
"I have no info this time",
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(),
actionItem.getTitle() + " selected",
Toast.LENGTH_SHORT).show();
}
}
});
quickAction.show(view1);
}
}
And my another activity
public class Second extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);
EditText d1=(EditText) findViewById(R.id.editText1);
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
final int position = (Integer) bundle.get("position");
Log.v("position","po1 " +position);
ArrayList<Weather> array = new ArrayList<Weather>();
Log.v("position","po1 " +array);
}
}
}
contacts adapter:
public class ContactsAdapter extends ArrayAdapter{
Context context;
int layoutResourceId;
Weather data[] = null;
public ContactsAdapter(Context context, int layoutResourceId, Weather[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
WeatherHolder holder = null;
if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new WeatherHolder();
holder.imgIcon = (ImageView)row.findViewById(R.id.imageView1);
holder.imgIcon.findViewById(R.id.imageView1).setOnClickListener(mBuyButtonClickListener);
holder.txtTitle = (TextView)row.findViewById(R.id.textView1);
//((ImageView) row.findViewById(R.id.im)).setOnClickListener(mBuyButtonClickListener);
row.setTag(holder);
}
else
{
holder = (WeatherHolder)row.getTag();
}
Weather weather = data[position];
holder.txtTitle.setText(weather.title);
holder.imgIcon.setImageResource(weather.icon);
return row;
}
static class WeatherHolder
{
ImageView imgIcon;
TextView txtTitle;
}
private OnClickListener mBuyButtonClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
((ExampleActivity) context).functiontorun(v);
}
};
}
private OnClickListener mBuyButtonClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
WeatherHolder holder = (WeatherHolder) v.getTag;
String string = holder.txtTitle .getText();
((ExampleActivity) context).functiontorun(string);
}
};
just pass the string to your activity and change the parameter of the functiontorun as string

Autocomplete textbox highlighting the typed character in the suggestion list

I have been working on AutoCompleteTextView. I was able to get the suggestion and all in the drop down list as we type.
My question is: Can we highlight the typed character in the suggestion drop down list?
I have achieved the functionality. The solution is as follows:
AutoCompleteAdapter.java
public class AutoCompleteAdapter extends ArrayAdapter<String> implements
Filterable {
private ArrayList<String> fullList;
private ArrayList<String> mOriginalValues;
private ArrayFilter mFilter;
LayoutInflater inflater;
String text = "";
public AutoCompleteAdapter(Context context, int resource,
int textViewResourceId, List<String> objects) {
super(context, resource, textViewResourceId, objects);
fullList = (ArrayList<String>) objects;
mOriginalValues = new ArrayList<String>(fullList);
inflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return fullList.size();
}
#Override
public String getItem(int position) {
return fullList.get(position);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
// tvViewResourceId = (TextView) view.findViewById(android.R.id.text1);
String item = getItem(position);
Log.d("item", "" + item);
if (convertView == null) {
convertView = view = inflater.inflate(
android.R.layout.simple_dropdown_item_1line, null);
}
// Lookup view for data population
TextView myTv = (TextView) convertView.findViewById(android.R.id.text1);
myTv.setText(highlight(text, item));
return view;
}
#Override
public Filter getFilter() {
if (mFilter == null) {
mFilter = new ArrayFilter();
}
return mFilter;
}
private class ArrayFilter extends Filter {
private Object lock;
#Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (prefix != null) {
text = prefix.toString();
}
if (mOriginalValues == null) {
synchronized (lock) {
mOriginalValues = new ArrayList<String>(fullList);
}
}
if (prefix == null || prefix.length() == 0) {
synchronized (lock) {
ArrayList<String> list = new ArrayList<String>(
mOriginalValues);
results.values = list;
results.count = list.size();
}
} else {
final String prefixString = prefix.toString().toLowerCase();
ArrayList<String> values = mOriginalValues;
int count = values.size();
ArrayList<String> newValues = new ArrayList<String>(count);
for (int i = 0; i < count; i++) {
String item = values.get(i);
if (item.toLowerCase().contains(prefixString)) {
newValues.add(item);
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
if (results.values != null) {
fullList = (ArrayList<String>) results.values;
} else {
fullList = new ArrayList<String>();
}
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
public static CharSequence highlight(String search, String originalText) {
// ignore case and accents
// the same thing should have been done for the search text
String normalizedText = Normalizer
.normalize(originalText, Normalizer.Form.NFD)
.replaceAll("\\p{InCombiningDiacriticalMarks}+", "")
.toLowerCase(Locale.ENGLISH);
int start = normalizedText.indexOf(search.toLowerCase(Locale.ENGLISH));
if (start < 0) {
// not found, nothing to to
return originalText;
} else {
// highlight each appearance in the original text
// while searching in normalized text
Spannable highlighted = new SpannableString(originalText);
while (start >= 0) {
int spanStart = Math.min(start, originalText.length());
int spanEnd = Math.min(start + search.length(),
originalText.length());
highlighted.setSpan(new ForegroundColorSpan(Color.BLUE),
spanStart, spanEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
start = normalizedText.indexOf(search, spanEnd);
}
return highlighted;
}
}
}
MainActivity.java
public class MainActivity extends Activity {
String[] languages = { "C", "C++", "Java", "C#", "PHP", "JavaScript",
"jQuery", "AJAX", "JSON" };
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
List<String> wordList = new ArrayList<String>();
Collections.addAll(wordList, languages);
AutoCompleteAdapter adapter = new AutoCompleteAdapter(this,
android.R.layout.simple_dropdown_item_1line,
android.R.id.text1,wordList);
AutoCompleteTextView acTextView = (AutoCompleteTextView) findViewById(R.id.languages);
acTextView.setThreshold(1);
acTextView.setAdapter(adapter);
}
}
Working like charm!
Enjoy!
I reckon that should be possible, provided you know the index/indices of the character(s) the user typed last. You can then use a SpannableStringBuilder and set a ForegroundColorSpan and BackgroundColorSpan to give the character(s) the appearance of a highlight.
The idea looks somewhat like this:
// start & end of the highlight
int start = ...;
int end = ...;
SpannableStringBuilder builder = new SpannableStringBuilder(suggestionText);
// set foreground color (text color) - optional, you may not want to change the text color too
builder.setSpan(new ForegroundColorSpan(Color.RED), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// set background color
builder.setSpan(new BackgroundColorSpan(Color.YELLOW), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// set result to AutoCompleteTextView
autocompleteTextview.setText(builder);
Note that the 'highlight' will remain as long as you don't type another character. You may want to remove the highlight when e.g. the user changes the cursor position in the AutoCompleteTextView, but I'll leave that up to you.
I know it's to late for answering this question , But as I personally battled to find the answer , finally I wrote it myself (with the help of the answer from #MH. ofcourse), so here it is :
First , You have to create a Custom ArrayAdapter :
public class AdapterAustocomplete extends ArrayAdapter<String> {
private static final String TAG = "AdapterAustocomplete";
String q = "";
public AdapterAustocomplete(Context context, int resource, List objects) {
super(context, resource, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
String item = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
if (convertView == null) {
convertView =
// I'll use a custom view for each Item , this way I can customize it also!
G.inflater.from(getContext()).inflate(R.layout.textview_autocomplete, parent, false);
}
// Lookup view for data population
TextView myTv = (TextView) convertView.findViewById(R.id.txt_autocomplete);
int start = item.indexOf(q);
int end = q.length()+start;
SpannableStringBuilder builder = new SpannableStringBuilder(item);
builder.setSpan(new ForegroundColorSpan(Color.RED), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
myTv.setText(builder);
return convertView;
}
public void setQ(String q) {
this.q = q;
}
}
And in the Code that you want to set the adapter for AutoCompleteTextView ;
AutoCompleteTextView myAutoComplete = findViewById(its_id);
AdapterAustocomplete adapter_autoComplete = new AdapterAustocomplete(getActivity(), 0, items); // items is an arrayList of Strings
adapter_autoComplete.setQ(q);
myAutoComplete.setAdapter(adapter_autoComplete);
Thanks to vadher jitendra I wrote the same and fixed some bugs.
Changed a dropdown layout to own.
Added showing a full list when clicking inside AutoCompleteTextView.
Fixed a bug of freezing the list when showing (added a check for empty string in highlight).
row_dropdown.xml (item layout):
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/text1"
style="?android:attr/dropDownItemStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:ellipsize="marquee"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:singleLine="true"
android:textColor="#333333"
android:textSize="15sp"
tools:text="text"
tools:textAppearance="?android:attr/textAppearanceLargePopupMenu" />
To filter a list when typing we should implement ArrayAdapter. It depends on items (T class). You can later use AutoCompleteAdapter<String> or any data class you like.
AutoCompleteAdapter:
import android.content.Context;
import android.graphics.Typeface;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.StyleSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;
import androidx.annotation.IdRes;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.text.Normalizer;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class AutoCompleteAdapter<T> extends ArrayAdapter<T> implements Filterable {
private Context context;
#LayoutRes
private int layoutRes;
#IdRes
private int textViewResId;
private ArrayList<T> fullList;
private ArrayList<T> originalValues;
private ArrayFilter filter;
private LayoutInflater inflater;
private String query = "";
public AutoCompleteAdapter(#NonNull Context context, #LayoutRes int resource, #IdRes int textViewResourceId, #NonNull List<T> objects) {
super(context, resource, textViewResourceId, objects);
this.context = context;
layoutRes = resource;
textViewResId = textViewResourceId;
fullList = (ArrayList<T>) objects;
originalValues = new ArrayList<>(fullList);
inflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return fullList.size();
}
#Override
public T getItem(int position) {
return fullList.get(position);
}
/**
* You can use either
* vadher jitendra method (getView)
* or get the method from ArrayAdapter.java.
*/
// #NotNull
// #Override
// public View getView(int position, View convertView, ViewGroup parent) {
// View view = convertView;
// T item = getItem(position);
// Log.d("item", "" + item);
// if (convertView == null) {
// convertView = view = inflater.inflate(layoutRes, null);
// }
// // Lookup view for data population
// TextView myTv = convertView.findViewById(textViewResId);
// myTv.setText(highlight(query, item));
// return view;
// }
#Override
public #NonNull
View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
return createViewFromResource(inflater, position, convertView, parent, layoutRes);
}
private #NonNull
View createViewFromResource(#NonNull LayoutInflater inflater, int position,
#Nullable View convertView, #NonNull ViewGroup parent, int resource) {
final View view;
final TextView text;
if (convertView == null) {
view = inflater.inflate(resource, parent, false);
} else {
view = convertView;
}
try {
if (textViewResId == 0) {
// If no custom field is assigned, assume the whole resource is a TextView
text = (TextView) view;
} else {
// Otherwise, find the TextView field within the layout
text = view.findViewById(textViewResId);
if (text == null) {
throw new RuntimeException("Failed to find view with ID "
+ context.getResources().getResourceName(textViewResId)
+ " in item layout");
}
}
} catch (ClassCastException e) {
Log.e("ArrayAdapter", "You must supply a resource ID for a TextView");
throw new IllegalStateException(
"ArrayAdapter requires the resource ID to be a TextView", e);
}
final T item = getItem(position);
text.setText(highlight(query, item.toString()));
// if (item instanceof CharSequence) {
// text.setText(highlight(query, (CharSequence) item));
// } else {
// text.setText(item.toString());
// }
return view;
}
#Override
public #NonNull
Filter getFilter() {
if (filter == null) {
filter = new ArrayFilter();
}
return filter;
}
private class ArrayFilter extends Filter {
private final Object lock = new Object();
#Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (prefix == null) {
query = "";
} else {
query = prefix.toString();
}
if (originalValues == null) {
synchronized (lock) {
originalValues = new ArrayList<>(fullList);
}
}
if (prefix == null || prefix.length() == 0) {
synchronized (lock) {
ArrayList<T> list = new ArrayList<>(originalValues);
results.values = list;
results.count = list.size();
}
} else {
final String prefixString = prefix.toString().toLowerCase();
ArrayList<T> values = originalValues;
int count = values.size();
ArrayList<T> newValues = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
T item = values.get(i);
if (item.toString().toLowerCase().contains(prefixString)) {
newValues.add(item);
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results.values != null) {
fullList = (ArrayList<T>) results.values;
} else {
fullList = new ArrayList<>();
}
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
private static CharSequence highlight(#NonNull String search, #NonNull CharSequence originalText) {
if (search.isEmpty())
return originalText;
// ignore case and accents
// the same thing should have been done for the search text
String normalizedText = Normalizer
.normalize(originalText, Normalizer.Form.NFD)
.replaceAll("\\p{InCombiningDiacriticalMarks}+", "")
.toLowerCase(Locale.ENGLISH);
int start = normalizedText.indexOf(search.toLowerCase(Locale.ENGLISH));
if (start < 0) {
// not found, nothing to do
return originalText;
} else {
// highlight each appearance in the original text
// while searching in normalized text
Spannable highlighted = new SpannableString(originalText);
while (start >= 0) {
int spanStart = Math.min(start, originalText.length());
int spanEnd = Math.min(start + search.length(),
originalText.length());
highlighted.setSpan(new StyleSpan(Typeface.BOLD), spanStart, spanEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
start = normalizedText.indexOf(search, spanEnd);
}
return highlighted;
}
}
}
In order to show dropdown list when clicked inside AutoCompleteTextView we need to override setOnTouchListener as described in https://stackoverflow.com/a/26036902/2914140. Lint also prints warnings, so we have to write a custom view:
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import androidx.appcompat.widget.AppCompatAutoCompleteTextView;
/*
Avoids a warning "Custom view `AutoCompleteTextView` has setOnTouchListener called on it but does not override performClick".
*/
public class AutoCompleteTV extends AppCompatAutoCompleteTextView {
public AutoCompleteTV(Context context) {
super(context);
}
public AutoCompleteTV(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AutoCompleteTV(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
performClick();
}
return super.onTouchEvent(event);
}
#Override
public boolean performClick() {
super.performClick();
return true;
}
}
Then use it in activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.textfield.TextInputLayout
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.example.autocompletetextview1.AutoCompleteTV
android:id="#+id/languages"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:completionThreshold="1"
android:hint="language"
android:imeOptions="actionNext"
android:maxLines="1"
android:paddingLeft="10dp"
android:paddingTop="15dp"
android:paddingRight="10dp"
android:paddingBottom="15dp"
android:singleLine="true"
android:textColor="#333333"
android:textColorHint="#808080"
android:textSize="12sp" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
I use TextInputLayout here for better decoration, in this case we have to add Material Design Components:
in build.gradle:
implementation 'com.google.android.material:material:1.3.0-alpha01'
and in styles.xml:
<style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
...
MainActivity:
import android.os.Bundle;
import android.view.MotionEvent;
import android.widget.AutoCompleteTextView;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
String[] items = {"C", "C++", "Java", "C#", "PHP", "JavaScript", "jQuery", "AJAX", "JSON"};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<DataClass> wordList = new ArrayList<>();
for (int i = 0; i < items.length; i++) {
DataClass data = new DataClass(i, items[i]);
wordList.add(data);
}
AutoCompleteAdapter<DataClass> adapter = new AutoCompleteAdapter<>(this,
R.layout.row_dropdown, R.id.text1, wordList);
//adapter.setDropDownViewResource(R.layout.row_dropdown);
AutoCompleteTV acTextView = findViewById(R.id.languages);
acTextView.setThreshold(1);
acTextView.setAdapter(adapter);
acTextView.setText("Java");
acTextView.setOnTouchListener((v, event) -> {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
((AutoCompleteTextView) v).showDropDown();
v.requestFocus();
v.performClick(); // Added to avoid warning "onTouch lambda should call View#performClick when a click is detected".
}
return false;
}
);
}
}

setOnItemClickListener in customized listview

Here is the activity ShowData.java where i am setting up customized listview.. Now i need to click view on that listview and need to display another activity but throws force close.. It throws error on listview.setAdapter(adapter);
public class ShowData extends Activity
{
ListView listview;
Intent intent;
ArrayList<BeanClass> datalist;
CustomAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
listview = (ListView) findViewById(R.id.listView1);
Intent intent = getIntent();
datalist = (ArrayList<BeanClass>) intent.getSerializableExtra("list");
Log.i("Size of ArrayList", "is " +datalist.size());
adapter = new CustomAdapter(ShowData.this, R.layout.customrow , datalist);
listview.setAdapter(adapter);
listview.setOnItemClickListener(new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3)
{
Intent i = new Intent(ShowData.this,DetailActivity.class);
i.putExtra("datalist", datalist);
i.putExtra("position", arg2);
startActivity(i);
}
}
}
Here is the CustomAdapter.java
public class CustomAdapter extends ArrayAdapter<BeanClass>
{
Context context;
int layoutResourceId;
BeanClass bc;
ArrayList<BeanClass> vbc;
public CustomAdapter(Context context, int layoutResourceId, ArrayList<BeanClass> vbc)
{
super(context, layoutResourceId, vbc);
this.context=context;
this.layoutResourceId=layoutResourceId;
this.vbc=vbc;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
View row = convertView;
StringReaderHolder holder;
if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent,false);
holder= new StringReaderHolder();
holder.mytext1 = (TextView) row.findViewById(R.id.textView1);
holder.mytext2 = (TextView) row.findViewById(R.id.textView2);
holder.mytext3 = (TextView) row.findViewById(R.id.textView3);
row.setTag(holder);
}
else
{
holder = (StringReaderHolder) row.getTag();
}
BeanClass bsObject = vbc.get(position);
holder.mytext1.setText(bsObject.name);
holder.mytext2.setText(bsObject.address);
holder.mytext3.setText(bsObject.phone);
return row;
}
static class StringReaderHolder
{
TextView mytext1,mytext2,mytext3;
}
}
How should i use setOnItemClickListener...??? Thanks...
In Your getView Method try:
row.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent i = new Intent(context,DetailActivity.class);
i.putExtra("datalist", vbc);
i.putExtra("position", position);
startActivity(i);
}
});

What's the problems when I use ".getText().toString();"

#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
EditText nameText = (EditText) findViewById(R.id.editText1);
name = nameText.getText().toString();
nameText.setText("");
EditText numberText = (EditText) findViewById(R.id.editText2);
number = numberText.getText().toString();
numberText.setText("");
person = new Person(name, number);
order.add(person);
PersonAdapter pa = new PersonAdapter(con, R.layout.row, order);
setListAdapter(pa);
}
});
}
#Override
protected void onListItemClick(ListView l, View v, final int position, long id) {
// TODO Auto-generated method stub
final int index = position;
AlertDialog.Builder aDialog = new AlertDialog.Builder(this);
aDialog.setTitle("What do you want??");
aDialog.setPositiveButton("Delete",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
order.remove(index);
PersonAdapter pa = new PersonAdapter(con, R.layout.row,
order);
setListAdapter(pa);
}
});
aDialog.setNeutralButton("Edit", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
LayoutInflater inflater = (LayoutInflater) con.getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.custom_dialog, (ViewGroup)findViewById(R.id.root_layout));
builder = new AlertDialog.Builder(con);
builder.setView(layout);
builder.setTitle("Fill EditText");
builder.setIcon(R.drawable.icon);
editNum = (EditText)findViewById(R.id.editNum);
editName = (EditText)findViewById(R.id.editName);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
name = editName.getText().toString();
number = editNum.getText().toString();
order.set(position, new Person(name,number));
PersonAdapter pa = new PersonAdapter(con, R.layout.row, order);
setListAdapter(pa);
}
});
builder.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
alertDialog = builder.create();
alertDialog.show();
}
});
aDialog.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
AlertDialog ad = aDialog.create();
ad.show();
}
public PersonAdapter(Context context, int textViewResourceId,
ArrayList<Person> items) {
super(context, textViewResourceId, items);
this.items = items;
}
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.row, null);
}
Person p = items.get(position);
if (p != null) {
TextView tt = (TextView) v.findViewById(R.id.android_toptext);
TextView bt = (TextView) v.findViewById(R.id.android_bottomtext);
if (tt != null) {
tt.setText(p.getName());
}
if (bt != null) {
bt.setText("TEL : " + p.getNumber());
}
}
return v;
}
private String name;
private String number;
public Person(String name, String number) {
this.name = name;
this.number = number;
}
public String getName() {
return name;
}
public String getNumber() {
return number;
}
}
I am practicing Widget(exactly I am making custom dialog) and Listener In android . But I stop now because ".getText().toString();" makes error ... I can't understand.. T^T Please Help me... why it makes error?? I think It doesn't have problem
You should declare your EditText globally
EditText editName;
EditText editNum;
#Override
public void onCreate(Bundle savedInstanceState) {
...
}
.....
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
LayoutInflater inflater = (LayoutInflater) con.getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.custom_dialog, (ViewGroup)findViewById(R.id.root_layout));
builder = new AlertDialog.Builder(con);
builder.setView(layout);
builder.setTitle("Fill EditText modificated");
builder.setIcon(R.drawable.icon);
editName = (EditText)findViewById(R.id.editName);
editNum = (EditText)findViewById(R.id.editNum);