My search view is working properly but I am trying to do a search such that all the "visible" search letters should be highlighted. I used the filter interface in my adapter for filtering data.
here is my adapter Class
public class myAdapter extends RecyclerView.Adapter<myAdapter.viewHolder> implements Filterable {
private List<Model> model;
// for search filtering
private ArrayList<Model> modelFull;
Context context;
public myAdapter(ArrayList<Model> model, Context context) {
this.model = model;
modelFull =new ArrayList<>(model);
this.context = context;
}
#NonNull
#Override
public viewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.template, parent, false);
return new viewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull viewHolder holder, int position) {
Model forPosition = model.get(position);
holder.image.setImageResource(forPosition.getImage());
holder.intro.setText(forPosition.getIntro());
}
#Override
public int getItemCount() {
return model.size();
}
public class viewHolder extends RecyclerView.ViewHolder {
TextView intro;
ImageView image;
public viewHolder(#NonNull View itemView) {
super(itemView);
intro= itemView.findViewById(R.id.introTxt);
image = itemView.findViewById(R.id.image);
}
}
#Override
public Filter getFilter() {
return generalFilter;
}
private Filter generalFilter =new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
List<Model> filteredModel =new ArrayList<>();
if(constraint ==null || constraint.length()==0) {
filteredModel.addAll(modelFull);
}
else {
String searchQuery= constraint.toString().toLowerCase().trim();
for(blogBigModel item : modelFull){
if(item.getBlogIntro().toLowerCase().contains(searchQuery)){
filteredModel.add(item);
}
}
}
FilterResults results =new FilterResults();
results.values = filteredModel;
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
model.clear();
model.addAll((List)results.values);
notifyDataSetChanged();
}
};
}
that's my class / Fragment where i used the above adapter
[what should i add to get the desired highlighted query when i search in the search bar like Whatsapp][1]
[1]: https://i.stack.imgur.com/Fdu2r.jpg
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.ic_home_search:enter code here
SearchView searchView = (SearchView) item.getActionView();
searchView.setQueryHint("Search....");
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setBackground(getResources().getDrawable(R.drawable.searchview_bg));
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return false;
}
});
}
}
return true;
});
Related
I want to filter Listview by Searchview
I use the following Adapter for the filter and it works if I haven't made any new additions to the adapter
When I add a new item to Listview, the search stops completely until I restart the program after adding, modifying or deleting it
full code
adapter class
Do you want to achieve the result like following GIF?
If you want to add the item to the listview, based on your adapter, you should item in the adapter like following code.
public class TableItemAdapter : BaseAdapter<TableItem>, IFilterable
{
public List<TableItem> _originalData;
public List<TableItem> _items;
private readonly Activity _context;
public TableItemAdapter(Activity activity, IEnumerable<TableItem> tableitems)
{
_items = tableitems.ToList();
_context = activity;
Filter = new TableItemFilter(this);
}
//Add data to the `_items`, listview will be updated, if add data in the activity,
//there are two different lists, so listview will not update.
public void AddData(TableItem tableItem)
{
_items.Add(tableItem);
NotifyDataSetChanged();
}
public override TableItem this[int position]
{
get { return _items[position]; }
}
public Filter Filter { get; private set; }
public override int Count
{
get { return _items.Count; }
}
public override long GetItemId(int position)
{
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
var item = _items[position];
View view = convertView;
if (view == null) // no view to re-use, create new
view = convertView ?? _context.LayoutInflater.Inflate(Resource.Layout.TableItem, null);
//view = _context.LayoutInflater.Inflate(Resource.Layout.TableItem, null);
view.FindViewById<TextView>(Resource.Id.Text1).Text = item.Heading;
view.FindViewById<TextView>(Resource.Id.Text2).Text = item.SubHeading;
return view;
}
public override void NotifyDataSetChanged()
{
// this.NotifyDataSetChanged();
base.NotifyDataSetChanged();
}
}
public class TableItemFilter :Filter
{
private readonly TableItemAdapter _adapter;
public TableItemFilter(TableItemAdapter adapter)
{
_adapter = adapter;
}
protected override FilterResults PerformFiltering(ICharSequence constraint)
{
var returnObj = new FilterResults();
var results = new List<TableItem>();
if (_adapter._originalData == null)
_adapter._originalData = _adapter._items;
if (constraint == null) return returnObj;
if (_adapter._originalData != null && _adapter._originalData.Any())
{
results.AddRange(
_adapter._originalData.Where(
item => item.SubHeading.ToLower().Contains(constraint.ToString()) | item.Heading.ToLower().Contains(constraint.ToString())));
}
returnObj.Values = FromArray(results.Select(r => r.ToJavaObject()).ToArray());
returnObj.Count = results.Count;
constraint.Dispose();
return returnObj;
}
protected override void PublishResults(ICharSequence constraint, FilterResults results)
{
using (var values = results.Values)
_adapter._items = values.ToArray<Java.Lang.Object>().Select(r => r.ToNetObject<TableItem>()).ToList();
_adapter.NotifyDataSetChanged();
// Don't do this and see GREF counts rising
constraint.Dispose();
results.Dispose();
}
}
public class JavaHolder : Java.Lang.Object
{
public readonly object Instance;
public JavaHolder(object instance)
{
Instance = instance;
}
}
public static class ObjectExtensions
{
public static TObject ToNetObject<TObject>(this Java.Lang.Object value)
{
if (value == null)
return default(TObject);
if (!(value is JavaHolder))
throw new InvalidOperationException("Unable to convert to .NET object. Only Java.Lang.Object created with .ToJavaObject() can be converted.");
TObject returnVal;
try { returnVal = (TObject)((JavaHolder)value).Instance; }
finally { value.Dispose(); }
return returnVal;
}
public static Java.Lang.Object ToJavaObject<TObject>(this TObject value)
{
if (Equals(value, default(TObject)) && !typeof(TObject).IsValueType)
return null;
var holder = new JavaHolder(value);
return holder;
}
}
}
Then in the activity, you add the data by adapter.
private void Button1_Click(object sender, System.EventArgs e)
{
tableItemAdapter.AddData(new TableItem() { Heading = "test1222", SubHeading = "sub Test" });
}
Here is my demo, you can download it.
https://github.com/851265601/Xamarin.Android_ListviewSelect/blob/master/XAListViewSearchDemo.zip
Attempt to invoke interface method 'void com.example.imovie.adapter.MovieItemClickListener.onMovieClick(com.example.imovie.models.Movie, android.widget.ImageView)' on a null object reference
public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.MyViewHolder> {
Context context ;
List<Movie> mData;
MovieItemClickListener movieItemClickListener;
public MovieAdapter(Context context, List<Movie> mData, MovieItemClickListener listener) {
this.context = context;
this.mData = mData;
movieItemClickListener = listener;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(context).inflate(R.layout.item_movie,viewGroup,false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder myViewHolder, int i) {
myViewHolder.TvTitle.setText(mData.get(i).getTitle());
myViewHolder.ImgMovie.setImageResource(mData.get(i).getThumbnail());
}
#Override
public int getItemCount() {
return mData.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
private TextView TvTitle;
private ImageView ImgMovie;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
TvTitle = itemView.findViewById(R.id.item_movie_title);
ImgMovie = itemView.findViewById(R.id.item_movie_img);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
movieItemClickListener.onMovieClick(mData.get(getAdapterPosition()),ImgMovie);//i have a null object reference
}
});
}
}
}
public class HomeFragment extends Fragment implements MovieItemClickListener {
private HomeViewModel homeViewModel;
private List<Slide> listSlides;
private ViewPager slidePager;
private TabLayout indicator;
private RecyclerView moviesRV;
private RecyclerView moviesRV2;
private MovieItemClickListener movieItemClickListener;
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
homeViewModel =
ViewModelProviders.of(this).get(HomeViewModel.class);
View root = inflater.inflate(R.layout.fragment_home, container, false);
slidePager = root.findViewById(R.id.slider_pager);
indicator = root.findViewById(R.id.indicator);
moviesRV = root.findViewById(R.id.rsViewMovies);
moviesRV2 = root.findViewById(R.id.rsViewMovies2);
iniSlider();
final SliderPagerAdapter sliderPagerAdapteradapter = new SliderPagerAdapter(getContext(), listSlides);
final MovieAdapter movieAdapter = new MovieAdapter(getContext(), DateSource.getPopularMovies(), movieItemClickListener);
final Timer timer = new Timer();
timer.scheduleAtFixedRate(new SliderTimer(), 4000, 6000);
homeViewModel.getText().observe(this, new Observer<String>() {
#Override
public void onChanged(#Nullable String s) {
slidePager.setAdapter(sliderPagerAdapteradapter);
indicator.setupWithViewPager(slidePager, true);
moviesRV.setAdapter(movieAdapter);
moviesRV.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
moviesRV2.setAdapter(movieAdapter);
moviesRV2.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
}
});
return root;
}
#Override
public void onMovieClick(Movie movie, ImageView imageView) {
Intent intent = new Intent(getContext(), MovieDetailActivity.class);
intent.putExtra("title", movie.getTitle());
intent.putExtra("imgURL", movie.getThumbnail());
intent.putExtra("imgCover", movie.getCoverPhoto());
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(getActivity(),
imageView, "sharedName");
startActivity(intent, options.toBundle());
Toast.makeText(getContext(), "item clicked : " + movie.getTitle(), Toast.LENGTH_LONG).show();
}
class SliderTimer extends TimerTask {
#Override
public void run() {
if (getActivity() != null) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
if (slidePager.getCurrentItem() < listSlides.size() - 1) {
slidePager.setCurrentItem(slidePager.getCurrentItem() + 1);
} else {
slidePager.setCurrentItem(0);
}
}
});
}
}
}
private void iniSlider() {
listSlides = new ArrayList<>();
listSlides.add(new Slide(R.drawable.a, "slide title \n movie title"));
listSlides.add(new Slide(R.drawable.b, "slide title"));
listSlides.add(new Slide(R.drawable.a, "slide title \n movie title"));
listSlides.add(new Slide(R.drawable.b, "slide title"));
}
}
If I'm not wrong, HomeFragment.movieItemClickListener is never initialized.
You may want to make the following changes in HomeFragment:
1. Delete the line
private MovieItemClickListener movieItemClickListener;
2. In this line
final MovieAdapter movieAdapter = new MovieAdapter(getContext(), DateSource.getPopularMovies(), movieItemClickListener);
change movieItemClickListener to this, because HomeFragment implements MovieItemClickListener.
That should fix the NullPointerException.
I have a list of webview to show different pdf's, I need to show it in a horizontal RecyclerView, but the problem is that when I scroll it horizontally then the coming webview just goes on top of the current one and the current one instead of shifting to the left hand side, it remains at its position. It looks a little weird.
This is my RecyclerViewAdapter
public class HorizontalManual extends RecyclerView
.Adapter {
Context context;
private ArrayList<String> list;
public class DataObjectHolder extends RecyclerView.ViewHolder {
ImageView imgUploaded;ProgressBar loader; WebView webViewManual;
public DataObjectHolder(View itemView) {
super(itemView);
webViewManual = (WebView) itemView.findViewById(R.id.pdf_manual_webView);
}
}
public HorizontalManual(Context context, ArrayList<String> list) {
this.context = context;
this.list = list;
}
#Override
public DataObjectHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View view = null;
try {
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.horz_pdf, parent, false);
if (view.getLayoutParams ().width == RecyclerView.LayoutParams.MATCH_PARENT)
view.getLayoutParams ().width = parent.getWidth ();
} catch (Exception e) {
e.printStackTrace();
}
return new DataObjectHolder(view);
}
#Override
public void onBindViewHolder(final DataObjectHolder holder, final int position) {
String url = "http://docs.google.com/gview?embedded=true&url=" + list.get(position);
Log.e("pdf",url);
WebSettings websettings = holder.webViewManual.getSettings();
websettings.setJavaScriptEnabled(true);
holder.webViewManual.loadUrl(url);
holder.webViewManual.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return false;
}
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
holder.webViewManual.loadUrl("javascript:(function() { " +
"document.getElementsByClassName('ndfHFb-c4YZDc-GSQQnc-LgbsSe ndfHFb-c4YZDc-to915-LgbsSe VIpgJd-TzA9Ye-eEGnhe ndfHFb-c4YZDc-LgbsSe')[0].style.display='none'; })()");
}
});
holder.webViewManual.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
holder.webViewManual.setHorizontalScrollBarEnabled(false);
}
#Override
public int getItemCount() {
return list.size();
}
}
I'm setting the HorizontalList in my Fragment like this:
mRecyclerViewManual.setHasFixedSize(true);
rLayoutManagerManual = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false); mRecyclerViewManual.setLayoutManager(rLayoutManagerManual);
//Setting adapter
HorizontalManual setUploadsListAdapterManual = new HorizontalManual(context, list); mRecyclerViewManual.setAdapter(setUploadsListAdapterManual);
Load you google doc url using iframe tag as shown below.
String frameVideo = "<html><body>Youtube video .. <br> <iframe width=\"320\" height=\"315\" src=\"https://docs.google.com/gview?embedded=true&url=http://Dealerapp.ebunch.ca/upload/wl/manuals/7.pdf\" frameborder=\"0\" allowfullscreen></iframe></body></html>";
holder.webView.loadData(frameVideo, "text/html", "utf-8");
I am working for quiz app project. I've got a RecyclerView, each of them contains TextView, two Checkbox and EditText. What I want is when i checked the second Checkbox it will enable the EditText. I have already make this work. but the problem is if I Checked the Checkbox and Type something in the EditText on the first row, when I scroll down some of the others are mirroring the EditText state even I am not Checked the Checkbox to enable EditText of that row.
here is my adapter code:
public class StudentAdapter extends RecyclerView.Adapter<StudentAdapter.StudentViewHolder> {
private LayoutInflater inflator;
private int status;
Typeface typeface;
List<Student> students = Collections.emptyList();
public StudentAdapter(Context context, List<Student> students, String Font) {
inflator = LayoutInflater.from(context);
this.students = students;
typeface = Typeface.createFromAsset(context.getAssets(), Font);
}
#Override
public StudentViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflator.inflate(R.layout.student_row, parent, false);
StudentViewHolder studentViewHolder = new StudentViewHolder(view);
return studentViewHolder;
}
#Override
public void onBindViewHolder(final StudentViewHolder holder, final int position) {
final Student currentStudent = students.get(position);
holder.studentName.setText(currentStudent.student);
holder.chbIllegal.setTag(students.get(position));
holder.editText.setTag(students.get(position));
holder.chbIllegal.setChecked(students.get(position).isSelected());
holder.chbIllegal.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CheckBox cb = (CheckBox) v;
final Student contact = (Student) cb.getTag();
contact.setSelected(cb.isChecked());
students.get(position).setSelected(cb.isChecked());
// this will enable editText if checkbox is checked
if (cb.isChecked()) {
holder.editText.setEnabled(true);
holder.editText.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) {
}
#Override
public void afterTextChanged(Editable s) {
String Illegal = holder.editText.getText().toString();
contact.setAgaints_rule(Illegal);
Log.d("GExam", currentStudent.student + " " + Illegal);
}
});
holder.chbIllegal.setOnClickListener(null);
holder.chbIllegal.setTag(students.get(position));
} else {
holder.editText.setEnabled(false);
}
}
});
if (currentStudent.getStatus() == 1) {
holder.chbPresent.setChecked(true);
} else if (currentStudent.getStatus() == 0) {
holder.chbPresent.setChecked(false);
}
}
#Override
public int getItemCount() {
return students.size();
}
class StudentViewHolder extends RecyclerView.ViewHolder {
TextView studentName;
CheckBox chbPresent, chbIllegal;
EditText editText;
public StudentViewHolder(View itemView) {
super(itemView);
studentName = (TextView) itemView.findViewById(R.id.StudentlistText);
this.studentName.setTypeface(typeface);
editText = (EditText) itemView.findViewById(R.id.edtAgaintsRule);
chbPresent = (CheckBox) itemView.findViewById(R.id.chbPresent);
// chbIllegal will handle the editText
chbIllegal = (CheckBox) itemView.findViewById(R.id.chbIllegal);
editText.setEnabled(false);
}
}
public List<Student> getStudentList() {
return students;
}
}
How can I only enable EditText of the row that checkbox is checked?
Finally I've been able to solve my problem by my teacher helped. what I have changed is I move the listener from onBindViewHolder to my ViewHolder class like this:
public class StudentAdapter extends RecyclerView.Adapter<StudentAdapter.StudentViewHolder> {
private LayoutInflater inflator;
private int status;
Typeface typeface;
List<Student> students = Collections.emptyList();
public StudentAdapter(Context context, List<Student> students, String Font) {
inflator = LayoutInflater.from(context);
this.students = students;
typeface = Typeface.createFromAsset(context.getAssets(), Font);
}
#Override
public StudentViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflator.inflate(R.layout.student_row, parent, false);
StudentViewHolder studentViewHolder = new StudentViewHolder(view);
return studentViewHolder;
}
#Override
public void onBindViewHolder(final StudentViewHolder holder, final int position) {
final Student currentStudent = students.get(position);
holder.studentName.setText(currentStudent.student);
holder.chbIllegal.setTag(students.get(position));
holder.editText.setTag(students.get(position));
holder.editText.setText(currentStudent.getAgaints_rule());
if (currentStudent.isSelected()) {
holder.editText.setEnabled(true);
}else{
holder.editText.setEnabled(false);
}
holder.chbIllegal.setChecked(students.get(position).isSelected());
if (currentStudent.getStatus() == 1) {
holder.chbPresent.setChecked(true);
} else if (currentStudent.getStatus() == 0) {
holder.chbPresent.setChecked(false);
}
}
#Override
public int getItemCount() {
return students.size();
}
class StudentViewHolder extends RecyclerView.ViewHolder {
TextView studentName;
CheckBox chbPresent, chbIllegal;
EditText editText;
public StudentViewHolder(View itemView) {
super(itemView);
studentName = (TextView) itemView.findViewById(R.id.StudentlistText);
this.studentName.setTypeface(typeface);
editText = (EditText) itemView.findViewById(R.id.edtAgaintsRule);
chbPresent = (CheckBox) itemView.findViewById(R.id.chbPresent);
chbIllegal = (CheckBox) itemView.findViewById(R.id.chbIllegal);
chbIllegal.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CheckBox cb = (CheckBox) v;
Student s = (Student) v.getTag();
Log.e("GExam", String.valueOf(cb.isChecked()));
s.setSelected(cb.isChecked());
StudentViewHolder.this.editText.setEnabled(cb.isChecked());
}
});
editText.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) {
}
#Override
public void afterTextChanged(Editable s) {
Student student = (Student) StudentViewHolder.this.editText.getTag();
student.setAgaints_rule(s.toString());
}
});
}
}
public List<Student> getStudentList() {
return students;
}
}
Could anyone explain me one thing? Is it possible to use Vaadin TreeTable with LazyQueryContainer? I've alredy tried but it doesn't work. Actually, there is no any lazy loading. The method loadItems of org.vaadin.addons.lazyquerycontainer.Query is called until all data are loaded. For instanse, if batch size for the container = 100 and I have 500 rows then this method will be called 5 times. Here is my code:
public class LazyHierarchicalQueryContainer extends LazyQueryContainer implements Container.Hierarchical {
private String parentProperty = "parent";
public LazyHierarchicalQueryContainer(QueryFactory queryFactory, Object idPropertyId, int batchSize,
boolean compositeItems) {
super(queryFactory, idPropertyId, batchSize, compositeItems);
}
public LazyHierarchicalQueryContainer(QueryDefinition queryDefinition, QueryFactory queryFactory) {
super(queryDefinition, queryFactory);
}
public LazyHierarchicalQueryContainer(QueryView queryView) {
super(queryView);
}
public String getParentProperty() {
return parentProperty;
}
public void setParentProperty(String parentProperty) {
this.parentProperty = parentProperty;
}
#Override
public Collection<?> getChildren(Object itemId) {
return Collections.emptyList();
}
#Override
public Object getParent(Object itemId) {
return null;
}
#Override
public Collection<?> rootItemIds() {
ArrayList arrayList = new ArrayList();
for (Object workItem : getItemIds()) {
if (isRoot(workItem)) {
arrayList.add(workItem);
}
}
return arrayList;
}
#Override
public boolean setParent(Object itemId, Object newParentId) throws UnsupportedOperationException {
if (getItem(newParentId) != null) {
getItem(itemId).getItemProperty(getParentProperty()).setValue(newParentId);
} else {
getItem(itemId).getItemProperty(getParentProperty()).setValue(null);
}
return true;
}
#Override
public boolean areChildrenAllowed(Object itemId) {
return true;
}
#Override
public boolean setChildrenAllowed(Object itemId, boolean areChildrenAllowed) throws UnsupportedOperationException {
return false;
}
#Override
public boolean isRoot(Object itemId) {
return getItem(itemId).getItemProperty(parentProperty).getValue() == null;
}
#Override
public boolean hasChildren(Object itemId) {
return false;
}
}
Thanks in advance.
It seems your implementation of rootItemIds() loads all items to filter out the root items. This may cause the whole container to be read in the first go.