I want to search for actors but I'm getting this error. I made it before but, now I'm trying a different adapter. It's probably so basic, but I couldnt fixed it. Please Help. Thanks.
public class Actors extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.movie_list);
ArrayList<Actor> actors = new ArrayList<Actor>();
actors.add(new Actor("jacknicholson",1,R.drawable.jacknicholson));
actors.add(new Actor("Marlon Brando",2,R.drawable.marlonbrando));
actors.add(new Actor("Robert De Niro",3,R.drawable.robertdeniro));
actors.add(new Actor("Al Pacino",4,R.drawable.alpacino));
actors.add(new Actor("Danel Day-Lewis",5,R.drawable.danielday));
actors.add(new Actor("Dustin Hoffman",6,R.drawable.dustinhoffman));
final MovieAdapter itemsAdapter = new MovieAdapter(this, actors);
ListView listView = (ListView) findViewById(R.id.list);
listView.setAdapter(itemsAdapter);
EditText theFilter =(EditText) findViewById(R.id.editt);
theFilter.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
//Here I'm getting an error
(Actors.this).itemsAdapter.getFilter().filter(charSequence);
}
#Override
public void afterTextChanged(Editable editable) {
}
});
}
}
Here is my movie adapter. In Actors class I can't use (Actors.this). I can't use it as itemsAdapter.getFilter().filter(char), but with this way it doesn't find anything.
public class MovieAdapter extends ArrayAdapter<Actor> {
public MovieAdapter(Activity context, ArrayList<Actor> words) {
super(context, 0, words);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View listItemView = convertView;
if (listItemView == null) {
listItemView = LayoutInflater.from(getContext()).inflate(
R.layout.list_item, parent, false);
}
Actor currentWord = getItem(position);
TextView songTextView = (TextView) listItemView.findViewById(R.id.Name_text_view);
songTextView.setText((currentWord.getmPopularity()));
final TextView singerTextView = (TextView) listItemView.findViewById(R.id.popularity_text_view);
singerTextView.setText(currentWord.getmActor());
ImageView iconView = (ImageView) listItemView.findViewById(R.id.list_item_icon);
iconView.setImageResource(currentWord.getImageResourceId());
return listItemView;
}
}
And here is the Actor Class
package com.example.aylin.movieapp;
import java.util.Comparator;
/**
* Created by Aylin on 2.04.2018.
*/
public class Actor {
private String mActor;
private double mPopularity;
private int mImageResourceId;
public Actor(String mActor, double mPopularity, int imageResourceId){
this.mActor = mActor;
this.mPopularity = mPopularity;
mImageResourceId = imageResourceId;
}
public String getmPopularity() {
String pop = Double.toString(mPopularity);
return pop; }
public String getmActor() { return mActor; }
public int getImageResourceId() { return mImageResourceId; }
/*Comparator for sorting the list by roll no*/
}
Ignore:afdsdgjhjgkıfgdsgjhsfdhfhafdgfhkjhılşdsfhljkipşdjlhişkdsfl
Just omit (Actors.this). entirely.
An anonymous inner class can reference all the final variables of the containing method.
I think the problem is that Actor doesn't override toString(). Of course, with the sh*tty documentation of ArrayAdapter.getFilter(), you'd either have to guess what the returned Filter does, or look at the source, which is what I did, and it calls toString() of the items the ArrayAdapter is responsible for. So overriding toString() in Actor so that it returns mActor might solve the problem.
Related
I already know how a recycler viewer works and a good understanding of interface listeners but I'm wondering why is it that we need to pass a listener to my recycler adapter called mAdapter = new GreenAdapter. In my MainActivity.java I have something like this
public class MainActivity extends AppCompatActivity implements GreenAdapter.ListItemClickListener {
private static final int NUM_LIST_ITEMS = 100;
private GreenAdapter mAdapter;
private RecyclerView mNumbersList;
private Toast mToast;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAdapter = new GreenAdapter(NUM_LIST_ITEMS, this);
mNumbersList.setAdapter(mAdapter);
}
#Override
public void onListItemClick(int clickedItemIndex) {
String toastMessage = "Item #" + clickedItemIndex + "clicked.";
mToast = Toast.makeText(this, toastMessage, Toast.LENGTH_LONG);
mToast.show();
}
In my GreenAdapter.java I understand that my Viewholder constructor will invoke my custom interface called ListItemClickedListener passing in the position of the clicked view and from there I can implement the code for what will happen when the user clicks it through my onListItemClick abstract method
public class GreenAdapter extends RecyclerView.Adapter<GreenAdapter.NumberViewHolder> {
private static final String TAG = GreenAdapter.class.getSimpleName();
private int mNumberItems;
final private ListItemClickListener mOnClickListener;
public interface ListItemClickListener{
void onListItemClick(int clickedItemIndex);
}
public GreenAdapter(int numberOfItems, ListItemClickListener listener) {
mNumberItems = numberOfItems;
mOnClickListener = listener;
}
#Override
public NumberViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
Context context = viewGroup.getContext();
int layoutIdForListItem = R.layout.number_list_item;
LayoutInflater inflater = LayoutInflater.from(context);
boolean shouldAttachToParentImmediately = false;
View view = inflater.inflate(layoutIdForListItem, viewGroup, shouldAttachToParentImmediately);
NumberViewHolder viewHolder = new NumberViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(NumberViewHolder holder, int position) {
Log.d(TAG, "#" + position);
holder.bind(position);
}
#Override
public int getItemCount() {
return mNumberItems;
}
class NumberViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView listItemNumberView;
public NumberViewHolder(View itemView) {
super(itemView);
listItemNumberView = (TextView) itemView.findViewById(R.id.tv_item_number);
itemView.setOnClickListener(this);
}
void bind(int listIndex) {
listItemNumberView.setText(String.valueOf(listIndex));
}
#Override
public void onClick(View view) {
int clickedPosition = getAdapterPosition();
mOnClickListener.onListItemClick(clickedPosition);
}
}
I'm just confuse why we need to pass this in my recycler adapter
By passing this you are actually passing the object of MainActivity.java which is implementing GreenAdapter.ListItemClickListener interface. Now when your user clicks on item you can let your activity know what item in the list was clicked by the user the rest of Business logic will then be written in the onListItemClick() method of MainActivity.
I'm trying to create an ExpandibleListView with intents that switch to new classes. When using only one switch, there is no problem, but when I want different parents to switch diffent classes, only one of them works, the other one stays like empty (Its arrows turn up and down but nothing happens). How can I make them work together?
Here is my codes:
ExpandibleListAdapter.java
import android.graphics.Typeface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import java.util.HashMap;
import java.util.List;
import android.content.Context;
import android.widget.TextView;
public class ExpandableListAdapter extends BaseExpandableListAdapter {
private Context context;
private List<String> listDataHeader;
private HashMap<String,List<String>> listHashMap;
public ExpandableListAdapter(Context context, List<String> listDataHeader, HashMap<String, List<String>> listHashMap) {
this.context = context;
this.listDataHeader = listDataHeader;
this.listHashMap = listHashMap;
}
#Override
public int getGroupCount() {
return listDataHeader.size();
}
#Override
public int getChildrenCount(int i) {
return listHashMap.get(listDataHeader.get(i)).size();
}
#Override
public Object getGroup(int i) {
return listDataHeader.get(i);
}
#Override
public Object getChild(int i, int i1) {
return listHashMap.get(listDataHeader.get(i)).get(i1); // i = group item , i1= ChildItem
}
#Override
public long getGroupId(int i) {
return i;
}
#Override
public long getChildId(int i, int i1) {
return i1;
}
#Override
public boolean hasStableIds() {
return false;
}
#Override
public View getGroupView(int i, boolean b, View view, ViewGroup ViewGroup) {
String headerTitle = (String)getGroup(i);
if(view == null)
{
LayoutInflater inflater = (LayoutInflater)this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.list_group,null);
}
TextView lblListHeader = (TextView)view.findViewById(R.id.lblListHeader);
lblListHeader.setTypeface(null, Typeface.BOLD);
lblListHeader.setText(headerTitle);
return view;
}
#Override
public View getChildView(int i, int i1, boolean b, View view, ViewGroup ViewGroup) {
final String childText = (String)getChild(i,i1);
if(view == null)
{
LayoutInflater inflater = (LayoutInflater)this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.list_item,null);
}
TextView txtListChild = (TextView)view.findViewById(R.id.lblListItem);
txtListChild.setText(childText);
return view;
}
#Override
public boolean isChildSelectable(int i, int i1) {
return true;
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity
{
private ExpandableListView listView;
private ExpandableListAdapter listAdapter;
private List<String> listDataHeader;
private HashMap<String,List<String>> listHash;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ExpandableListView)findViewById(R.id.lvExp);
initData();
listAdapter = new ExpandableListAdapter(this,listDataHeader,listHash);
listView.setAdapter(listAdapter);
}
private void initData() {
listDataHeader = new ArrayList<>();
listHash = new HashMap<>();
listDataHeader.add("Line One");
listDataHeader.add("Line Two");
List<String> genel = new ArrayList<>();
**//The problem starts here**
listView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
#Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
final String selected = (String) listAdapter.getGroup(groupPosition);
Intent intent;
switch (selected) {
case "Line One":
intent = new Intent(MainActivity.this,LineOne.class);
startActivity(intent);
break;
}
return false; //return true doesn't let the other parents to open.
}
});
List<String> terims = new ArrayList<>();
listView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
#Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
final String terims = (String) listAdapter.getGroup(groupPosition);
Intent niyet;//I used "intent" instead of "niyet" as same above but nothing has changed.
switch (terims) {
case "Line Two":
niyet = new Intent(MainActivity.this, LineTwo.class);
startActivity(niyet);
break;
}
return false;
}
});
listHash.put(listDataHeader.get(0),genel);
listHash.put(listDataHeader.get(1),terims);
}
}
You cannot set 2 OnGroupClickListeners. The second one cancels the first one. You should set one listener and then check for both sets of conditions in the one listener.
I'm trying to use recyclerview and I'm trying to design 'setText' method in viewholder use number in item parameter.
The problem is that when I put "item.getNumber()" in setText method app doesn't work. I don't know why when I put just string in method have no problem and put "item.getNumber()" have problem without error message.
adapter:
public class adapter extends RecyclerView.Adapter<adapter.ViewHolder> {
ArrayList<data> items=new ArrayList<data>();
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater=LayoutInflater.from(parent.getContext());
View itemView= inflater.inflate(R.layout.itemlayout, parent,false);
return new ViewHolder(itemView);
}
public void additem(data item){
items.add(item);
}
#Override
public void onBindViewHolder(#NonNull adapter.ViewHolder holder, int position) {
data item=items.get(position);
holder.setText(item);
}
#Override
public int getItemCount() {
return items.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
TextView textView;
EditText editText;
public ViewHolder(#NonNull View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.textView);
editText = itemView.findViewById(R.id.editText);
}
public void setText(data item) {
textView.setText(item.getNumber());
editText.setHint(item.getSentences());
}
}
}
mainActivity:
public class MainActivity extends AppCompatActivity {
static int num = 6;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = findViewById(R.id.recyclerview);
adapter adapter1 = new adapter();
for (int i = 0; i < num; i++) {
adapter1.additem(new data("sentences", i + 1));
}
recyclerView.setAdapter(adapter1);
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(layoutManager);
}
}
data.java:
public class data {
String sentences = null;
int number;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public data(String sentences, int number) {
this.sentences = sentences;
this.number = number;
}
public String getSentences() {
return sentences;
}
public void setSentences(String sentences) {
this.sentences = sentences;
}
}
The problem is that your getNumber() method returns int:
public int getNumber() {
return number;
}
There are two different versions of TextView.setText(), one that accepts a String and one that accepts an int. The version that accepts an int is expecting a string resource id (like R.string.foo), and it can't tell that you're just trying to display a number.
Change your setText() call so that it looks like this instead:
textView.setText("" + item.getNumber());
By using "" + item.getNumber(), you'll make sure that you're calling the version of setText() that accepts a String, and that will mean that you get to display the number you're expecting.
I'm trying to crate something that creates a new ListView item on button press, I thing I have somewhere some bug, but as I'm new to this topic I don't know where.
I've tried rewriting the code several times, I've tried to use notifyDataSetChanged(); - it does nothing
tried googling looking on other topics here...
Here is my MainActivity.java:
public Button btn;
private ListView lv;
private CustomeAdapter customeAdapter;
public ArrayList<EditModel> editModelArrayList;
int populateListMaxNum =3;
int listNumber = populateListMaxNum;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) findViewById(R.id.listView);
btn = (Button) findViewById(R.id.btn);
editModelArrayList = populateList();
customeAdapter = new CustomeAdapter(this,editModelArrayList);
lv.setAdapter(customeAdapter);
/* TODO activate button */
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
addToList();
Toast.makeText(getApplicationContext(), "button", Toast.LENGTH_LONG).show();
}
});
}
private ArrayList<EditModel> populateList(){ //this part works perfectly
ArrayList<EditModel> list = new ArrayList<>();
for(int i = 0; i < populateListMaxNum; i++){
EditModel editModel = new EditModel();
//editModel.setEditTextValue(String.valueOf(i));
list.add(editModel);
}
return list;
}
/*TODO make it work = expand */
private void addToList(){ // this part doesn't work nor it doesn't fail
EditModel editModel = new EditModel();
editModelArrayList.add(editModel);
customeAdapter.notifyDataSetChanged();
}
}
Here is my CustomeAdapter.java class:
public class CustomeAdapter extends BaseAdapter {
private Context context;
public static ArrayList<EditModel> editModelArrayList;
public CustomeAdapter(Context context, ArrayList<EditModel> editModelArrayList) {
this.context = context;
CustomeAdapter.editModelArrayList = editModelArrayList;
}
#Override
public int getViewTypeCount() {
return getCount();
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public int getCount() {
return editModelArrayList.size();
}
#Override
public Object getItem(int position) {
return editModelArrayList.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.lv_item, null, true);
holder.editText = convertView.findViewById(R.id.editid);
convertView.setTag(holder);
}else {
// the getTag returns the viewHolder object set as a tag to the view
holder = (ViewHolder)convertView.getTag();
}
holder.editText.setText(editModelArrayList.get(position).getEditTextValue());
holder.editText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
editModelArrayList.get(position).setEditTextValue(holder.editText.getText().toString());
}
#Override
public void afterTextChanged(Editable editable) {
}
});
return convertView;
}
private class ViewHolder {
protected EditText editText;
}
}
I expect to create a new list item (EditText + TextView) but nothing happens (except the Toast message)
(After some tweaks the app crashes due to arrayindexoutofboundsexception length=3 index=3 error, but not in this setting)
here are up to all files nessessary: https://gist.github.com/Atingas/52778a247a78131e5b8cb0239fa30965
Main linear layout in lv_item.xml has match_parent height. Try change it to wrap_content. It seems like one row is just taking whole screen.
I am trying to implement something similar to facebook's search system, where if a user starts typing in a name it brings autocomplete suggestions based on the letters typed, and with an additional option to search for more results. Each result is an object and not a string, and I have tried adding an extra result for search but every time I click on search or one of the objects a replace text occurs with the object as oppose to the name and I know it is a method of the autocomplete widget. Is there another way to go about it?
Here is my code:
private AutoCompleteTextView sx;
sx = (AutoCompleteTextView) findViewById(R.id.sx);
if(sadapter == null) {
sadapter = new Sadapter(PostActivity.this, usersFound);
sx.setAdapter(sadapter);
}
sx.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) {
if (sx.getText().toString().length() <= 3 && sadapter != null) {
usersFound.clear();
sadapter.notifyDataSetChanged();
}
if (sx.getText().toString().length() > 3) {
usersFound.clear();
sadapter.notifyDataSetChanged();
Log.d(Constants.DEBUG, "Changing text " + s);
sxname = s.toString();
testCreate();
sadapter.notifyDataSetChanged();
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
sx.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
DatabaseUser newAdd = usersFound.get(position);
if(position == searchServerIndex) {
sx.setText(sxname);
usersFound.clear();
sadapter.notifyDataSetChanged();
apiGetPossibleCandidates();
} else {
sx.setText("");
}
}
});
private void testCreate() {
DatabaseUser nuser1 = new DatabaseUser("userid", "pictureid", "Jon");
DatabaseUser nuser2 = new DatabaseUser("userid", "pictureid", "Jonny");
DatabaseUser nuser3 = new DatabaseUser("userid", "pictureid", "Jong");
DatabaseUser nuser4 = new DatabaseUser("userid", "pictureid", "Joan");
DatabaseUser searchServer = new DatabaseUser("SearchId", "pictureid", "Search " + sxname);
usersFound.add(nuser1);
usersFound.add(nuser2);
usersFound.add(nuser3);
usersFound.add(nuser4);
searchServerIndex = usersFound.size();
usersFound.add(searchServer);
if(sadapter != null) {
sadapter.notifyDataSetChanged();
}
}
This is the adapter:
public class Sadapter extends ArrayAdapter<DatabaseUser> {
private Context mContext;
private List<DatabaseUser> usersSearch;
private List<DatabaseUser> usersFiltered;
public Sadapter(Context context, List<DatabaseUser> usersAdded) {
super(context, 0, usersAdded);
mContext = context;
usersSearch = usersAdded;
}
#Override
public int getCount() {
return usersSearch.size();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.user_autosearch_item, null);
}
//helps for recycling
final ViewHolder holder = new ViewHolder();
holder.userTxt = (TextView) v.findViewById(R.id.userTxt);
v.setTag(holder);
String name = usersSearch.get(position).getName();
holder.userTxt.setText(name);
return v;
}
static class ViewHolder {
TextView userTxt;
}
}
you can override getItem() method in your adapater and return the object of DataBaseUser of particular position from the searchlist.. like
#Override public DatabaseUser getItem(int position) {
return usersSearch.get(position);
}
So from your onClick method you can call this method and it will give you DatabaseUser object from which you can retrive your text. I hope it helps you ..