Ultimately, I want to click an item in a ListView (eventually a recycler list view) and have it transfer an id to the next activity for retrieval from the db.
I have a ListView, fed by a CursorAdapter (subclassed). When I set a breakpoint in CursorAdapter.bindView(), the View passed in is of type TwoItemListItem, so I can't set the id on RecipeListItem, which I believe is what I need to do to pass info to the next activity via ListView.setOnItemClickListener().
In the source activity, I get the list view and set the adapter:
RecipeCursorAdapter adapter = new RecipeCursorAdapter(this, cur);
ListView listView = (ListView) findViewById(R.id.recipe_list_list);
listView.setAdapter(adapter);
RecipeCursorAdapter:
public class RecipeCursorAdapter extends CursorAdapter {
protected LayoutInflater cursorInflator;
public RecipeCursorAdapter(Context context, Cursor cursor){
super(context, cursor, 0);
this.cursorInflator = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
// The newView method is used to inflate a new view and return it,
// you don't bind any data to the view at this point.
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent){
return this.cursorInflator.inflate(R.layout.activity_recipe_list_item, parent, false);
}
#Override
public void bindView(View view, Context context, Cursor cursor){
// Find fields to populate in inflated template
TextView tvTitle = (TextView) view.findViewById(R.id.recipeListItemTitle);
TextView tvSubtitle = (TextView) view.findViewById(R.id.recipeListItemSubtitle);
// Extract properties from cursor
String name = cursor.getString(cursor.getColumnIndexOrThrow("name"));
String description = cursor.getString(cursor.getColumnIndexOrThrow("description"));
// Populate fields with extracted properties
tvTitle.setText(name);
tvSubtitle.setText(description);
}
}
activity_recip_list_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<TwoLineListItem xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/listPreferredItemHeight"
android:mode="twoLine"
android:orientation="horizontal"
tools:context="com.smadacm.reciperepo.RecipeListItem" >
<TextView
android:id="#+id/recipeListItemTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/recipeListItemSubtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_below="#id/recipeListItemTitle"
android:layout_alignStart="#id/recipeListItemTitle"
android:textColor="#color/colorListSecondary"
android:textAppearance="?android:attr/textAppearanceListItemSecondary" />
</TwoLineListItem>
RecipeListItem:
public class RecipeListItem extends AppCompatActivity {
protected int itemId;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recipe_list_item);
}
public void setItemId(int id){
this.itemId = id;
}
public int getItemId(){
return this.itemId;
}
}
I was able to stumble into something functional. I don't know if this is right, and I'm open to being corrected.
In my main activity, I added a listener:
RecipeCursorAdapter adapter = new RecipeCursorAdapter(this, cur);
ListView listView = (ListView) findViewById(R.id.recipe_list_list);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
int ii = 0; // A line on which I can set a breakpoint
}
});
I added a new class to extend LinearLayout. This mostly just calls the super class, but also adds methods to set and retrieve arbitrary data:
public class RecipeListItem extends LinearLayout {
protected int recipeId;
public RecipeListItem(Context context) {
super(context, (AttributeSet)null, 0, 0);
}
public RecipeListItem(Context context, AttributeSet attrs) {
super(context, attrs, 0, 0);
}
public RecipeListItem(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr, 0);
}
public RecipeListItem(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public void setRecipeId(int id){
this.recipeId = id;
}
public int getRecipeId(){
return this.recipeId;
}
}
I used the LinearLayout subclass to define the list items:
<com.smadacm.reciperepo.widget.RecipeListItem xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:context="com.smadacm.reciperepo.RecipeListItem" >
<TextView
android:id="#+id/recipeListItemTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/recipeListItemSubtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_below="#id/recipeListItemTitle"
android:layout_alignStart="#id/recipeListItemTitle"
android:textColor="#color/colorListSecondary"
android:textAppearance="?android:attr/textAppearanceListItemSecondary" />
</com.smadacm.reciperepo.widget.RecipeListItem>
Finally, in my CursorAdapter, I set the id by item:
#Override
public void bindView(View viewRaw, Context context, Cursor cursor){
RecipeListItem view = (RecipeListItem) viewRaw;
// Find fields to populate in inflated template
TextView tvTitle = (TextView) view.findViewById(R.id.recipeListItemTitle);
TextView tvSubtitle = (TextView) view.findViewById(R.id.recipeListItemSubtitle);
// Extract properties from cursor
String name = cursor.getString(cursor.getColumnIndexOrThrow("name"));
String description = cursor.getString(cursor.getColumnIndexOrThrow("description"));
int id = cursor.getInt(cursor.getColumnIndexOrThrow("_id"));
// Populate fields with extracted properties
tvTitle.setText(name);
tvSubtitle.setText(description);
view.setRecipeId(id);
}
Related
In the image above, I have shown that when the user touches the drop-down spinner it will call the web api for getting data for the spinner. Then, that moment, I want to show the loader only on the spinner view on the left or right somewhere on the view itself like in the image, rather than on whole screen when it is getting data from the web service dynamically and hide that progress bar later when web service completely hit at the end (Ignore that search bar in image).
Just create an custom adapter for your spinner. Follow the instructions found here How to create Spinner-list using CustomAdapter in android .
Put the loading view in the layout inflated in the getView method in the adapter, and manipulate it via a callback from your async task used for fetching the result.
In this i am showing loader on start button and hiding loader when stop button is pressed so you can use according to your need.So , for this i have made three class CustomSpinner,Spinner_Custom_adapter and Activity class for using it
In main layout file
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="vertical">
<www.your_packagename.com.spinnerwithloaderex.CustomSpinner
android:id="#+id/custm_spnr"
android:layout_width="120dp"
android:layout_height="40dp"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:background="#drawable/dropdown_create_sales"
android:paddingRight="15dp"
android:text="Hello World!" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp">
<Button
android:id="#+id/start_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start" />
<Button
android:id="#+id/stop_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Stop" />
</LinearLayout>
</LinearLayout>
CustomSpinner class
public class CustomSpinner extends android.support.v7.widget.AppCompatSpinner {
private Spinner_Custom_adapter spinner_custom_adapter;
public CustomSpinner(Context context) {
super(context);
}
public CustomSpinner(Context context, int mode) {
super(context, mode);
}
public CustomSpinner(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomSpinner(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public CustomSpinner(Context context, AttributeSet attrs, int defStyleAttr, int mode) {
super(context, attrs, defStyleAttr, mode);
}
public CustomSpinner(Context context, AttributeSet attrs, int defStyleAttr, int mode, Resources.Theme popupTheme) {
super(context, attrs, defStyleAttr, mode, popupTheme);
}
public void setItems(Activity activity, ArrayList<String> spnr_Arr) {
spinner_custom_adapter = new Spinner_Custom_adapter(activity, spnr_Arr);
setAdapter(spinner_custom_adapter);
}
public Spinner_Custom_adapter getSpinner_custom_adapter() {
return spinner_custom_adapter;
}
public void showLoader() {
setEnabled(false);
spinner_custom_adapter.showLoader(true, true);
}
public void dismissLoader() {
setEnabled(true);
spinner_custom_adapter.showLoader(false, true);
}
}
Custom_Adapter class
public class Spinner_Custom_adapter<T> extends ArrayAdapter<T> {
private LayoutInflater flater;
private ProgressBar spinner_progress;
private TextView txtTitle;
private Boolean showOrNot = false;
Spinner_Custom_adapter(Activity context, ArrayList<T> list) {
super(context, R.layout.loader_spinner_lt, R.id.title, list);
flater = context.getLayoutInflater();
}
#NonNull
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = flater.inflate(R.layout.loader_spinner_lt, parent, false);
}
Object object = getItem(position);
String rowItem = null;
if (object instanceof String) {
rowItem = (String) object;
}
TextView txtTitle = (TextView) convertView.findViewById(R.id.title);
txtTitle.setText(rowItem);
ProgressBar spinner_progress = (ProgressBar) convertView.findViewById(R.id.spinner_progress);
this.txtTitle = txtTitle;
this.spinner_progress = spinner_progress;
showLoader(showOrNot, false);
return convertView;
}
void showLoader(Boolean showOrNot, boolean notifyListOrNot) {
if (txtTitle != null && spinner_progress != null) {
this.showOrNot = showOrNot;
spinner_progress.setVisibility(showOrNot ? View.VISIBLE : View.GONE);
if (notifyListOrNot) {
notifyDataSetChanged();
}
}
}
}
Spinner single view layout xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:orientation="horizontal">
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/title"
style="?android:attr/spinnerDropDownItemStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toLeftOf="#+id/spinner_progress"
android:ellipsize="end"
android:singleLine="true"
android:text="Strawberry"
android:textColor="#CC0033"
android:textSize="16dp" />
<ProgressBar
android:id="#+id/spinner_progress"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:visibility="gone" />
</RelativeLayout>
and for using it
custm_spnr = (CustomSpinner) findViewById(R.id.custm_spnr);
ArrayList<String> items = new ArrayList<>();
items.add("Abcdefg");
items.add("hijklm");
items.add("nopqr");
items.add("stu");
items.add("vwxyza1b1c1");
items.add("d1e1f11g1h1");
custm_spnr.setItems(MainActivity.this, items);
findViewById(R.id.start_btn).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
custm_spnr.showLoader();
}
});
findViewById(R.id.stop_btn).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
custm_spnr.dismissLoader();
}
});
I have to show two section in AutoCompleteTextView (Something like this):
I have created a custom layout which have two CardViews and each CardView have three TextViews. Right now I am not distributing the section on the basis of type. The whole data is loaded into one section.
Activity
final AutocompleteLocalityAdapter adapterLocalities = new AutocompleteLocalityAdapter(context,
R.layout.support_simple_spinner_dropdown_item, new ArrayList<Locality>());
AutocompleteLocalityAdapter
public class AutocompleteLocalityAdapter extends ArrayAdapter<Locality> {
public AutocompleteLocalityAdapter(Context context, int layout, List<Locality> localities) {
super(context, layout, localities);
this.localities = localities;
updateList("");
}
In updateList method I am making a new network call to fill the data in Locality class.
What do I need to do to categories the search result as per given image? ArrayAdapter is not going to work here for sure.
The possible solution I am thinking here is:
Replace ArrayAdapter to RecyclerViewAdapter.
Any hint will be appreciable.
The possible makeshift to this solution is PopUpWindow. Inside the PopUpWindow I put two RecyclerView and populate them through network calls.
dashboard_profile_popup_window
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="#dimen/margin_low"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:id="#+id/locationCardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="#dimen/corner_radius"
app:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/landmark"
android:textStyle="bold" />
<ListView
android:id="#+id/localityView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:id="#+id/landmarkCardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="#dimen/corner_radius"
app:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/location"
android:textStyle="bold" />
<ListView
android:id="#+id/landmarkView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.v7.widget.CardView>
CustomWidget
public class CustomAutoCompleteView extends EditText {
private Context context;
TextListViewAdapter locationAdapter;
TextListViewAdapter landmarkAdaper;
PopupWindow pwindow;
ClickListener clickListener;
public CustomAutoCompleteView(Context context) {
super(context);
this.context = context;
setCustomization();
}
public void closeWindow(){
pwindow.dismiss();
}
public CustomAutoCompleteView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
setCustomization();
}
public CustomAutoCompleteView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
setCustomization();
}
public void updateList(List<LocalityEntity> locationList, List<LocalityEntity> landmarkList) {
if (pwindow == null) {
initPopupWindow();
}
locationAdapter.updateList(locationList);
landmarkAdaper.updateList(landmarkList);
}
public void initPopupWindow() {
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = layoutInflater.inflate(R.layout.dashboard_profile_popup_window, null);
ListView landmarkRecyclerView = (ListView) layout.findViewById(R.id.localityView);
ListView localityRecyclerView = (ListView) layout.findViewById(R.id.landmarkView);
landmarkRecyclerView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String text = ((TextView) view.findViewById(R.id.localityText)).getText().toString();
String gid = ((TextView) view.findViewById(R.id.localityGID)).getText().toString();
clickListener.placeSelected(gid);
}
});
localityRecyclerView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String text = ((TextView) view.findViewById(R.id.localityText)).getText().toString();
String gid = ((TextView) view.findViewById(R.id.localityGID)).getText().toString();
clickListener.placeSelected(gid);
}
});
landmarkRecyclerView.setAdapter(landmarkAdaper);
localityRecyclerView.setAdapter(locationAdapter);
pwindow = new PopupWindow(context);
pwindow.setContentView(layout);
pwindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
pwindow.setWidth(this.getWidth());
pwindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
pwindow.setFocusable(true);
pwindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
#Override
public void onDismiss() {
pwindow = null;
}
});
pwindow.showAsDropDown(this);
}
private void setCustomization() {
locationAdapter = new TextListViewAdapter(getContext());
landmarkAdaper = new TextListViewAdapter(getContext());
initPopupWindow();
}
public void setClickListener(ClickListener clickListener) {
this.clickListener = clickListener;
}
public interface ClickListener {
void placeSelected(String gid);
}
}
Now call this customViewWidget through following code:
place_pop_up.setClickListener(this);
place_pop_up.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
private Timer timer = new Timer();
private final long DELAY = 2000;
#Override
public void afterTextChanged(final Editable s) {
if (s.length() > 3) {
timer.cancel();
timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
getAutoCompleteSearchResult(s.toString());
}
}, DELAY);
}
}
});
In getAutoCompleteSearchResult make the network call and call place_pop_up.updateList(locality, landmark);
I make WearableListView list. Problem is that setting android:layout_height="20dp" doesn't help
How to set height in this case? In Android Wear sample projects Notifications and Timer they also just set atribute android:layout_height="80dp". But I tried to set in the projects android:layout_height="20dp" but it didn't help! (below is my project source code):
list_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<base.mobitee.com.mobiteewatch.adapter.HolesListItemLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="20dp"
android:gravity="center_vertical" >
<TextView
android:id="#+id/text_hole"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-light"
android:gravity="center"
android:textSize="#dimen/list_item_text_size" />
</base.mobitee.com.mobiteewatch.adapter.HolesListItemLayout>
HolesListItemLayout.java:
public class HolesListItemLayout extends LinearLayout
implements WearableListView.OnCenterProximityListener {
private TextView mName;
private final int mFadedTextColor;
private final int mChosenTextColor;
public HolesListItemLayout(Context context) {
this(context, null);
}
public HolesListItemLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public HolesListItemLayout(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
mFadedTextColor = getResources().getColor(R.color.grey);
mChosenTextColor = getResources().getColor(R.color.black);
}
// Get references to the icon and text in the item layout definition
#Override
protected void onFinishInflate() {
super.onFinishInflate();
mName = (TextView) findViewById(R.id.text_hole);
}
#Override
public void onCenterPosition(boolean animate) {
mName.setTextSize(18);
mName.setTextColor(mChosenTextColor);
}
#Override
public void onNonCenterPosition(boolean animate) {
mName.setTextColor(mFadedTextColor);
mName.setTextSize(14);
}
}
HolesListAdapter.java:
public class HolesListAdapter extends WearableListView.Adapter {
private final Context mContext;
private final LayoutInflater mInflater;
public HolesListAdapter(Context context) {
this.mContext = context;
mInflater = LayoutInflater.from(context);
}
#Override
public WearableListView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new WearableListView.ViewHolder(
mInflater.inflate(R.layout.list_item_hole, null));
}
#Override
public void onBindViewHolder(WearableListView.ViewHolder holder, int position) {
TextView text = (TextView) holder.itemView.findViewById(R.id.text_hole);
text.setText(mContext.getString(R.string.hole_list_item) + " " + (position + 1));
text.setTextColor(mContext.getResources().getColor(android.R.color.black));
holder.itemView.setTag(position);
}
#Override
public int getItemCount() {
return Preferences.HOLES;
}
}
The WearableListView is hard-coded to only display three items at a time - it measures the item height by dividing the list view's height by three ... so there isn't a practical way of doing what you want.
I suggest making the text font larger ...
I've got idea. Insert list into FrameLayout container. And by changing height of container list item height is changed. Result:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="90dp"
android:layout_centerInParent="true">
<android.support.wearable.view.WearableListView
android:id="#+id/wearable_list_game_options"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:dividerHeight="0dp"
android:scrollbars="none"/>
</FrameLayout>
</RelativeLayout>
Add one LinearLayout inside and set
android:layout_height="50dp"
android:layout_margin="5dp"
I followed several tutorials but I still can't populate my list view.
What am I doing wrong?
this is the layout spaced_list.xml
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mList"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
this is spaced_list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp"
android:background="#efefef">
<TextView
android:id="#+id/leftItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:gravity="left"
android:text="Left Text View" />
<TextView
android:id="#+id/rightItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:gravity="right"
android:text="Right Text View" />
</RelativeLayout>
and this is the class
public class AllCategoriesActivity extends BaseActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.spaced_list);
ListView lv = (ListView) findViewById(R.id.mList);
TextView abHeader = (TextView) findViewById(R.id.header);
abHeader.setText("Categories");
CategoryDataSource cDataSource = new CategoryDataSource(this);
ArrayList<Category> allCategories = cDataSource.getAllCategories();
CategoriesAdapter cAdapter = new CategoriesAdapter(this, allCategories);
lv.setAdapter(cAdapter);
}
public class CategoriesAdapter extends ArrayAdapter<Category>{
private Context context;
private ArrayList<Category> categories;
public CategoriesAdapter(Context context, ArrayList<Category> categories){
super(context, 0);
this.context = context;
this.categories = categories;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.spaced_list_item, parent, false);
}
Category c = categories.get(position);
TextView tvLeft = (TextView) convertView.findViewById(R.id.leftItem);
tvLeft.setText(c.getTitle());
return convertView;
}
}
}
And I made sure that I'm getting values from cDataSource.getAllCategories();
Change this:
public CategoriesAdapter(Context context, ArrayList<Category> categories){
super(context, 0); // <- Wrong constructor
this.context = context;
this.categories = categories;
}
To this:
public CategoriesAdapter(Context context, ArrayList<Category> categories){
super(context, 0, categories);
this.context = context;
this.categories = categories;
}
You are currently calling this constructor of the super class:
public ArrayAdapter(Context context, int textViewResourceId) {
init(context, textViewResourceId, 0, new ArrayList<T>());
}
Which will eventually create a new ArrayList and ignore the data you passed in.
The problem is in the constructor in your adapter. You need to provide your ArrayList<Category> when you call super(). Here is the code:
public CategoriesAdapter(Context context, ArrayList<Category> categories){
super(context, 0, categories); //Providing objects to represent in the ListView
this.context = context;
this.categories = categories;
}
This is the documentation with the reference for this ArrayAdapter constructor.
I have a ListView with EditText inside.
Actually, when i touch an element of the Listview, the EditText have the focus and the keyboard appeared. Good.
The problem is i wanna do something on this EditText throught the listView's onItemClickListener, but seems that my code never enter in this method.
I try some setDescendantFocusability to my Listview but don't solve the problem.
Thanks a lot.
public class NoteAdapter extends BaseAdapter {
private ArrayList<String> notes;
private LayoutInflater inflater;
private Context context;
public NoteAdapter(Context context, ArrayList<String> notes) {
inflater = LayoutInflater.from(context);
this.notes = notes;
this.context = context;
}
public int getCount() {
// TODO Auto-generated method stub
return notes.size();
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return notes.get(position);
}
public long getItemId(int id) {
// TODO Auto-generated method stub
return id;
}
private class ViewHolder {
EditText note;
}
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder;
if(convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.listenote, null);
holder.note = (EditText)convertView.findViewById(R.id.note);
convertView.setTag(holder);
}else {
holder= (ViewHolder) convertView.getTag();
}
holder.note.setText(notes.get(position));
return convertView;
}
}
my main activity
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
notes = new ArrayList<String>();
for(int i=0; i< 10; i++)
notes.add("note"+i);
EditTextSelected = null;
adapter = new NoteAdapter(this, notes);
lv1 = ((ListView)findViewById(R.id.listeNote));
lv1.setAdapter(adapter);
lv1.setClickable(true);
lv1.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
Toast t = Toast.makeText(FastItActivity.this, "hello", 200);
t.show();
}
});
listenote.xml
<?xml version="1.0" encoding="utf-8"?>
<TableLayout
android:id="#+id/widget1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<EditText
android:id="#+id/note"
android:textColor="#color/black"
android:textSize="12dp"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:padding="5dp"
android:inputType="textMultiLine"
android:scrollHorizontally="false"
android:gravity="top|left"
android:ems="10"
android:layout_margin="10dp"
android:background="#drawable/fond_note"
/>
</TableLayout>
main.xml
<?xml version="1.0" encoding="utf-8"?>
<TableLayout
android:id="#+id/widget1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#drawable/wooden_top"
>
<ListView
android:id="#+id/listeNote"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:background="#android:color/transparent"
android:cacheColorHint="#00000000"
android:isScrollContainer="false"
android:divider="#00000000"
>
</ListView>
</TableLayout>
Move your modifications from ListView's onItemClickListener to your EditText's onClickListener
In NoteAdapter's getView:
holder.note = (EditText)convertView.findViewById(R.id.note);
holder.note.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//do something
}
});
or try this:
holder.note.setOnFocusListener(new View.OnFocusListener(){
#Override
public void onFocus(){
//do something
}
}
getView method has position parameter so you'll be able to distinguish what EditText was clicked (if you need different actions with different EditTexts)
This article is pretty long but towards the middle/end he demonstrates an interactive listview which is exactly what you need. http://www.vogella.de/articles/AndroidListView/article.html
If you could post some code that would help.
I was trying to solve a similar problem: which item in a list was selected when you embed several views in list item?!
I refuse to create a new listener for each item in the list. I can't imagine that would scale well on such a resource constrained platform. But, I found you can solve this problem by specializing EditText to set and retrieve the selected index in onClick.
Define your specialization:
package userInterface;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.EditText;
public class IndexedEditText extends EditText {
public int listIndex;
public IndexedEditText(Context context) {
super(context);
}
public IndexedEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public IndexedEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
}
Replace your EditText for your specialized class in the list item XML declaration. Be sure to get the path to your new class right (in my case it's userInterface.IndexedEditText).
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<userInterface.IndexedEditText
android:id="#+id/et_first_item"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:hint="#string/select"
android:inputType="none" />
<!-- other views -->
</RelativeLayout>
Set listIndex in getView, and set your OnClickListener for each IndexedEditText instance:
public abstract class EditTextPairArrayAdapter <T> extends ArrayAdapter<T> {
LayoutInflater inflater;
static class ViewHolder {
private WeakReference<IndexedEditText> name;
private WeakReference<EditText> notes;
public ViewHolder(IndexedEditText tv, EditText et) {
name = new WeakReference<IndexedEditText>(tv);
notes = new WeakReference<EditText>(et);
}
}
int textViewId;
int editTextId;
int listItemId;
List<T> list = null;
WeakReference<Context> contextRef;
//context is Activity that instantiates this array adapter
//resourceId is the layout xml ID for your special row
//textViewResourceId is any TextView ID in your special row xml def
//editTextResourceId means nothing in this context
//objects is the initial list of objects to present in UI
public EditTextPairArrayAdapter(Context context, int resourceId, int textViewResourceId, int editTextResourceId, List<T> objects) {
super(context, resourceId, textViewResourceId, objects);
this.listItemId = resourceId;
this.textViewId = textViewResourceId;
this.editTextId= editTextResourceId;
this.list = objects;
this.contextRef = new WeakReference<Context>(context);
}
#Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
View view = null;
ViewHolder viewHolder = null;
if (convertView == null) {
if(inflater == null)
inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(listItemId, null);
IndexedEditText text = (IndexedEditText)view.findViewById(textViewId);
EditText notes = (EditText) view.findViewById(editTextId);
text.listIndex = position;
//Special sauce
if(contextRef != null && contextRef.get() != null && (contextRef.get() instanceof View.OnClickListener)) {
text.setOnClickListener((View.OnClickListener) contextRef.get());
}
viewHolder = new ViewHolder(text, notes);
view.setTag(viewHolder);
}
else {
view = convertView;
viewHolder = (ViewHolder) convertView.getTag();
}
Titem = this.getItem(position);
if(item != null) {
//special sauce
}
return view;
}
//add abstract methods for implementations to define special sauce
}
Finally, in your Activity that implements OnClickListener:
public void onClick(View v) {
if(v instanceof IndexedEditText) {
Object obj = myList.get(((IndexedEditText)v).listIndex);
//do stuff with obj
}
}
The solution I found is to superimpose an EditText with a TextView and alternate gone/visible on both so that the EditText stops inducing bugs when hidden.