hii i am working in android application in which there is recycler view with each row is edittext, as i click on floating button new edittext is added in which user can enter email,my problem is that after say 9th position the previously enterd email values replaced with some position , i am calling notifydatasetchanged() method below is the code...if anyone know the way plese share..
1)Challenge Invite_other.java
/**
* Add custom workout detail
*/
public class ChallengeInviteOtherActivity extends GlobalAppCompactActivity implements ResponseListener {
private Gson gson;
private List<ChallengeParticipant> challengeParticipants;
private RecyclerView mRecyclerView;
private ChallengeInviteOtherAdapter adapter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.challenge_invite_other);
Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
initlization();
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.floating_add_custom_challenge);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
challengeParticipants.add(new ChallengeParticipant());
adapter.addAll(challengeParticipants);
}
});
setTitle(getString(R.string.nav_invite_participant));
//progressDialog = new ProgressDialog(this, R.style.CustomProgressDialog);
}
private void initlization() {
gson = CommonUtil.getGson();
challengeParticipants = new ArrayList<ChallengeParticipant>();
mRecyclerView = (RecyclerView) findViewById(R.id.challenge_list_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
challengeParticipants.add(new ChallengeParticipant());
adapter = new ChallengeInviteOtherAdapter(this);
adapter.addAll(challengeParticipants);
mRecyclerView.setAdapter(adapter);
}
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
return true;
}else if (item.getItemId() == R.id.action_bar_trace_friend) {
List<ChallengeParticipant> challengeParticipantList = new ArrayList<ChallengeParticipant>();
for (ChallengeParticipant participant : challengeParticipants) {
if (CommonUtil.isNotNull(participant.getEmailAddress()) || CommonUtil.isNotNull(participant.getContactNo())) {
participant.setChallengeId(CommonUtil.CHALLENGE.getId());
challengeParticipantList.add(participant);
}
}
if(challengeParticipantList.size()==0){
AlertMsg.showToast(this, getString(R.string.at_least_fill_one_contact));
}else{
Type listType = new TypeToken<ArrayList<ChallengeParticipant>>() {
}.getType();
String json = CommonUtil.getGson().toJson(challengeParticipantList, listType);
VolleyRequest volleyRequest = VolleyRequest.getInstance();
volleyRequest.sendRequest(VolleyRequest.INVITE_PARTICIPANTS, json, CommonUtil.getObject(this, this));
}
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.clear();
getMenuInflater().inflate(R.menu.challenge_invite_participant_memu, menu);
getMenuInflater().inflate(R.menu.common, menu);
return true;
}
#Override
public void onResponse(Object... result) {
AlertMsg.showToast(this, getString(R.string.invite_successfully));
finish();
}
//private ProgressDialog progressDialog;
}
2)Adapter class
private List<ChallengeParticipant> itemDetailsrrayList;
private LayoutInflater layoutInflater;
private Context mContext;
public ChallengeInviteOtherAdapter(Context context) {
mContext = context;
layoutInflater = LayoutInflater.from(context);
}
class MyViewHolder extends RecyclerView.ViewHolder {
private EditText email;
public MyViewHolder(View view) {
super(view);
email = (EditText) view.findViewById(R.id.email);
}
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = layoutInflater.inflate(R.layout.challenge_invite_other_item_detail, parent, false);
MyViewHolder myViewHolder = new MyViewHolder(view);
return myViewHolder;
}
#Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
final ChallengeParticipant c = itemDetailsrrayList.get(position);
holder.email.setText(c.getEmailAddress());
//holder.phone.setText(c.getContactNo());
//RecyclerView recyclerView = (RecyclerView) ((Activity) mContext).findViewById(R.id.price_listview);
//recyclerView.getLayoutParams().height = 150*itemDetailsrrayList.size();
holder.email.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(CommonUtil.isEmail(holder.email.getText().toString())){
c.setEmailAddress(holder.email.getText().toString());
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
/*holder.email.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean b) {
if (!b) {
}
}
});*/
/* holder.phone.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean b) {
if (!b) {
if(CommonUtil.isPhone(holder.phone.getText().toString())){
c.setContactNo(holder.phone.getText().toString());
}
}
}
});*/
}
public void addAll(List<ChallengeParticipant> list) {
itemDetailsrrayList = list;
notifyItemInserted(itemDetailsrrayList.size());
}
#Override
public int getItemCount() {
return itemDetailsrrayList.size();
}
}
3)xml layout of activity
<?xml version="1.0" encoding="utf-8"?>
<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:background="#color/dim_background"
android:focusableInTouchMode="true"
android:orientation="vertical">
<include layout="#layout/toolbar" />
<!--<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="#string/or"/>-->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:elevation="#dimen/general_elevation"
android:layout_margin="10dp"
android:background="#color/cardview_light_background">
<include layout="#layout/textview_no_record_found" />
<android.support.v7.widget.RecyclerView
android:id="#+id/challenge_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<android.support.design.widget.FloatingActionButton
android:id="#+id/floating_add_custom_challenge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|bottom"
android:layout_marginBottom="10dp"
android:layout_marginRight="10dp"
android:elevation="12dp"
android:src="#drawable/ic_add_white_24dp"
app:backgroundTint="#color/colorAccent"
app:borderWidth="0dp"
app:fabSize="normal"/>
</FrameLayout>
<include
layout="#layout/ad_system"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />
</LinearLayout>
When You add the new data to Array on which you set the adapter than Notify the adapter Add below lines after calling adapter.addAll(challengeParticipants);
adapter.notifyDataSetChanged();
adapter.notifyItemInserted(challengeParticipants.size());
Try this
public void addAll(List<ChallengeParticipant> list) {
itemDetailsrrayList = list;
notifyItemRangeChanged(0,challengeParticipants.size()-1);
}
Related
I want something like this:
so the thing is, what I exactly want is when user type particular topic name(if present in-app) in searchview it should able give suggestions and if found it should open that topic activity (just like Facebook, Instagram,...etc searches)..and those title are coming from API(which I have successfully displayed in other activities)..like this:
..what will the logic for it??? need help... Thanks
so I have just included searchview in XML like this-->
<SearchView
android:id="#+id/searchView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:queryHint="Search Here"
android:iconifiedByDefault="false"
android:layout_alignParentTop="true"
android:background="#drawable/search_bar"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="20dp"
android:pointerIcon="crosshair"
android:theme="#style/Widget.AppCompat.SearchView"
android:focusedByDefault="true"
/>
Need help..thanks in advance....
here is my json:
[{"id":"11","title":"TextView"},{"id":"10","title":"Edit Text"},{"id":"9","title":"ImageView"},{"id":"8","title":"Button "},{"id":"7","title":"CheckBox"},{"id":"6","title":"RadioButton & RadioGroup"},{"id":"5","title":"DatePicker"},{"id":"4","title":"TimePicker"},{"id":"3","title":"Switch"},{"id":"1","title":"Simple & Custom Toast"}]
here is my activity: for
public class StartLearning extends AppCompatActivity {
private RecyclerView recyclerView;
private SLAdapter slAdapter;
ProgressDialog progressDialog;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.startlearning_layout);
progressDialog = new ProgressDialog(StartLearning.this);
progressDialog.setMessage("Loading....");
progressDialog.show();
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
/*Create handle for the RetrofitInstance interface*/
SLApiSevice service = SLApiClient.getRetrofitInstance().create(SLApiSevice.class);
Call<List<SlModel>> call = service.getMySlmodel();
call.enqueue(new Callback<List<SlModel>>() {
#Override
public void onResponse(Call<List<SlModel>> call, Response<List<SlModel>> response) {
progressDialog.dismiss();
generateDataList(response.body());
Log.e("hello", String.valueOf(response.body()));
}
#Override
public void onFailure(Call<List<SlModel>> call, Throwable t) {
progressDialog.dismiss();
Toast.makeText(getApplicationContext(), "Something went wrong...Please try later!", Toast.LENGTH_SHORT).show();
}
});
}
}
private void generateDataList(List<SlModel> employeeList) {
recyclerView = findViewById(R.id.SLrecycle);
LinearLayoutManager manager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(manager);
recyclerView.setHasFixedSize(true);
slAdapter = new SLAdapter(getApplicationContext(),employeeList);
recyclerView.setAdapter(slAdapter);
}
adapter:
public class SLAdapter extends RecyclerView.Adapter<SLAdapter.CustomViewHolder> {
List<StartLearning.SlModel> Slmdel;
Context context;
public SLAdapter(Context context,List<StartLearning.SlModel> employees) {
this.Slmdel = employees;
this.context=context;
}
#Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.startlearning_item, parent, false);
return new CustomViewHolder(itemView);
}
#Override
public void onBindViewHolder(CustomViewHolder holder, int position) {
// TipsModel employee = employees.get(position);
//// holder.employeeName.setText(employees.get(position).getTips());
holder.textView.setText(String.valueOf(position+1)+". ");
holder.employeeName.setText(Slmdel.get(position).getTitle());
}
#Override
public int getItemCount() {
return Slmdel.size();
//return (employees == null) ? 0 : employees.size();
}
public class CustomViewHolder extends RecyclerView.ViewHolder {
public TextView employeeName;
TextView textView;
public CustomViewHolder(View view) {
super(view);
employeeName = (TextView) view.findViewById(R.id.Sl2);
textView=view.findViewById(R.id.Sl1);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context, NextSLactivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("title", Slmdel.get(getAdapterPosition()).getTitle());
intent.putExtra("idSLnext", Slmdel.get(getAdapterPosition()).getId());
//Log.e("ashwini",WAmdel.get(getAdapterPosition()).getId());
context.startActivity(intent);
}
});
}
}
onclick of item(example :textview)
activity:one of the items(example :textview)
public class JavaFragment extends Fragment {
private RecyclerView recyclerView;
private NextSLJavaAdapter adapter;
private NextSLModel DescriptList;
ProgressDialog progressDialog;
public JavaFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.nextsl_layout, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Toolbar toolbar = (Toolbar) getView().findViewById(R.id. toolbar );
// setSupportActionBar( toolbar );
//if (getSupportActionBar() != null) {
// getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// getSupportActionBar().setDisplayShowHomeEnabled(true);
//}
progressDialog = new ProgressDialog(getContext());
progressDialog.setMessage("Loading....");
progressDialog.show();
Intent intent = getActivity().getIntent();
String title = intent.getStringExtra("title");
//getSupportActionBar().setTitle(title);
String id = intent.getStringExtra("idSLnext");
Log.e("ashwini", String.valueOf(id));
/*Create handle for the RetrofitInstance interface*/
SLApiSevice service = SLApiClient.getRetrofitInstance().create(SLApiSevice.class);
Call<NextSLModel> call = service.getnextslmodel(id);
call.enqueue(new Callback<NextSLModel>() {
#Override
public void onResponse(Call<NextSLModel> call, Response<NextSLModel> response) {
progressDialog.dismiss();
DescriptList=response.body();
generateDataList(DescriptList);
}
#Override
public void onFailure(Call<NextSLModel> call, Throwable t) {
progressDialog.dismiss();
Toast.makeText(getContext(), "Something went wrong...Please try later!", Toast.LENGTH_SHORT).show();
}
});
}
private void generateDataList(NextSLModel photoList) {
recyclerView = getView().findViewById(R.id.nextSLrecycle);
LinearLayoutManager manager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(manager);
recyclerView.setHasFixedSize(true);
adapter = new NextSLJavaAdapter(getContext(),photoList);
recyclerView.setAdapter(adapter);
}
}
adapter:
public class NextSLJavaAdapter extends RecyclerView.Adapter<NextSLJavaAdapter.CustomViewHolder> {
NextSLModel Slmdel;
Context context;
public NextSLJavaAdapter(Context context, NextSLModel employees) {
this.Slmdel = employees;
this.context = context;
}
#Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.nextsl_item, parent, false);
return new CustomViewHolder(itemView);
}
#Override
public void onBindViewHolder(CustomViewHolder holder, int position) {
// TipsModel employee = employees.get(position);
//// holder.employeeName.setText(employees.get(position).getTips());
///////// holder.textView.setText(String.valueOf(position + 1) + ". ");
holder.employeeName.setText(Slmdel.getJava());
Log.e("sl",Slmdel.getJava());
}
#Override
public int getItemCount() {
return 1;
//return (employees == null) ? 0 : employees.size();
}
public class CustomViewHolder extends RecyclerView.ViewHolder {
public TextView employeeName;
TextView textView;
public CustomViewHolder(View view) {
super(view);
employeeName = (TextView) view.findViewById(R.id.detailsStartLearning);
textView = view.findViewById(R.id.Sl1);}}}
look at this search activity:
public class Search extends AppCompatActivity {
SearchView searchView;
RecyclerView recyclerView;
SearchAdapter slAdapter;
List<StartLearning.SlModel> movieList;
ChipGroup chipGroup;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
searchView=findViewById(R.id.searchView);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
searchForResults(newText);
return false;
}
});
//new code
chipGroup = findViewById(R.id. chipGroup);
searchView.onActionViewExpanded();
searchView.setIconified(true);
}
public void searchForResults(String search){
//here make an api call to get the results, complete the code here
SLApiSevice service = SLApiClient.getRetrofitInstance().create(SLApiSevice.class);
retrofit2.Call<List<StartLearning.SlModel>> call = service.getMySlmodel();
call.enqueue(new Callback<List<StartLearning.SlModel>>() {
#Override
public void onResponse(retrofit2.Call<List<StartLearning.SlModel>> call, Response<List<StartLearning.SlModel>> response) {
List<StartLearning.SlModel> list = response.body();
generateDataList(list);
addChips(list);
Log.d("TAG","Response = "+movieList);
slAdapter.setMovieList(getApplicationContext(),movieList);
}
#Override
public void onFailure(retrofit2.Call<List<StartLearning.SlModel>> call, Throwable t) {
Log.d("TAG","Response = "+t.toString());
}
});
}
private void generateDataList(List<StartLearning.SlModel> employeeList) {
recyclerView = findViewById(R.id.recyclerview);
LinearLayoutManager manager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(manager);
recyclerView.setHasFixedSize(true);
slAdapter = new SearchAdapter(getApplicationContext(),employeeList);
recyclerView.setAdapter(slAdapter);
}
public void addChips(List<StartLearning.SlModel> searchItems){
for (StartLearning.SlModel item : searchItems) {
Chip mChip = (Chip) this.getLayoutInflater().inflate(R.layout.item_chips, null, false);
mChip.setText(item.getTitle());
int paddingDp = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 10,
getResources().getDisplayMetrics()
);
mChip.setPadding(paddingDp, 0, paddingDp, 0);
mChip.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Handle the click here
}
});
chipGroup.removeAllViews();
chipGroup.addView(mChip);
}
}
#Override
public void onBackPressed() {
super.onBackPressed();
}
}
xml of search:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/colorPrimary"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" >
</androidx.appcompat.widget.Toolbar>
<SearchView
android:id="#+id/searchView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:queryHint="Search Here"
android:iconifiedByDefault="false"
android:layout_alignParentTop="true"
android:background="#drawable/search_bar"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="20dp"
android:pointerIcon="crosshair"
android:theme="#style/Widget.AppCompat.SearchView"
android:focusedByDefault="true"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp">
</androidx.recyclerview.widget.RecyclerView>
</LinearLayout>
<com.google.android.material.chip.ChipGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:id="#+id/chipGroup"
app:chipSpacing="25dp"/>
</LinearLayout>
Search adapter :
public class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.CustomViewHolder> implements Filterable {
List<StartLearning.SlModel> Slmdel;
List<StartLearning.SlModel> Slmdel1;
Context context;
public SearchAdapter() {
}
public void setMovieList(Context context, final List<StartLearning.SlModel> movieList){
this.context = context;
if(this.Slmdel == null){
this.Slmdel = movieList;
this.Slmdel1 = movieList;
notifyItemChanged(0, Slmdel1.size());
} else {
final DiffUtil.DiffResult result = DiffUtil.calculateDiff(new DiffUtil.Callback() {
#Override
public int getOldListSize() {
return SearchAdapter.this.Slmdel.size();
}
#Override
public int getNewListSize() {
// return movieList.size();
return (movieList == null) ? 0 : movieList.size();
}
#Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return SearchAdapter.this.Slmdel.get(oldItemPosition).getTitle() == movieList.get(newItemPosition).getTitle();
}
#Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
StartLearning.SlModel newMovie = SearchAdapter.this.Slmdel.get(oldItemPosition);
StartLearning.SlModel oldMovie = movieList.get(newItemPosition);
return newMovie.getTitle() == oldMovie.getTitle() ;
}
});
this.Slmdel = movieList;
this.Slmdel1 = movieList;
result.dispatchUpdatesTo(this);
}
}
public SearchAdapter(Context context,List<StartLearning.SlModel> employees) {
this.Slmdel = employees;
this.context=context;
}
#Override
public SearchAdapter.CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.startlearning_item, parent, false);
return new SearchAdapter.CustomViewHolder(itemView);
}
#Override
public void onBindViewHolder(SearchAdapter.CustomViewHolder holder, int position) {
holder.employeeName.setText(Slmdel.get(position).getTitle());
}
#Override
public int getItemCount() {
if(Slmdel != null){
return Slmdel1.size();
} else {
return 0;
}
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
final FilterResults oReturn = new FilterResults();
final List<StartLearning.SlModel> results = new ArrayList<StartLearning.SlModel>();
if (Slmdel1 == null)
Slmdel1 = Slmdel;
if (constraint != null) {
if (Slmdel1 != null & Slmdel1.size() > 0) {
for (final StartLearning.SlModel g : Slmdel1) {
if (g.getTitle().toLowerCase().contains(constraint.toString()))
results.add(g);
}
}
oReturn.values = results;
}
return oReturn;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
Slmdel1 = (ArrayList<StartLearning.SlModel>) results.values;
notifyDataSetChanged();
}
};}
public class CustomViewHolder extends RecyclerView.ViewHolder {
public TextView employeeName;
TextView textView;
public CustomViewHolder(View view) {
super(view);
employeeName = (TextView) view.findViewById(R.id.Sl2);
textView = view.findViewById(R.id.Sl1);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context, NextSLactivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("title", Slmdel.get(getAdapterPosition()).getTitle());
intent.putExtra("idSLnext", Slmdel.get(getAdapterPosition()).getId());
//Log.e("ashwini",WAmdel.get(getAdapterPosition()).getId());
context.startActivity(intent);
}
});
}
}
}
You can achieve suggestions related to your search query using recyclerview and adapters.
[1] Create new adapter and put your setMovieList() and getFilter() into it.
[2] Set that adapter into recyclerview of suggestions and notify adapter when you get your arraylist of suggestions.
check below code
public void onResponse(retrofit2.Call<List<StartLearning.SlModel>> call, Response<List<StartLearning.SlModel>> response) {
movieList = response.body();
if(movieList.size()!=0){
tvSuggestions.setVisibility(View.VISIBLE);
suggestionAdapter=new SuggestionAdapter(Search.this,movieList);
recyclerViewSuggestions.setAdapter(suggestionAdapter);
Log.e("TAG", "onResponse: size of movielist "+movieList);
suggestionAdapter.getFilter().filter(query);
suggestionAdapter.notifyDataSetChanged();
suggestionAdapter.setMovieList(Search.this,movieList);
}
else{
tvSuggestions.setVisibility(View.VISIBLE);
tvSuggestions.setText("No Suggestions Found");
}
/*generateDataList(movieList);
Log.d("TAG","Response = "+movieList);
slAdapter.setMovieList(getApplicationContext(),movieList);*/
}
There is a new Chip Material Component in android. Which can be used to fullfill the requirements. I belive you are currently using some recyclerview to display those search items instead of using this use ChiGroup to hold those values.a
Below is some sample code to do
First add this to your gradle for using the external libarary dependency
implementation 'com.google.android.material:material:1.0.0-alpha1'
Then in your desired layout below the search view place this xml code.
<com.google.android.material.chip.ChipGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:id="#+id/chipGroup"
app:chipSpacing="25dp"/>
The ChipGroup will hold the Chip items which will be added dynamically.
So now in your search activity/fragment just get a reference of this layout group.
public class Search extends AppCompatActivity {
SearchView searchView;
ChipGroup chipGroup;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
searchView = findViewById(R.id.searchView);
//new code
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
searchForResults(newText);
return false;
}
});
//new code
chipGroup = findViewById(R.id. chipGroup);
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
}
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
if (item.getItemId() ==android.R.id.home) {
finish();
}
return super.onOptionsItemSelected(item);
}
#Override
public void onBackPressed() {
super.onBackPressed();
}
//new code
public void searchForResults(String search){
//here make an api call to get the results, complete the code here
call.enqueue(new Callback<List<StartLearning.SlModel>>() {
#Override
public void onResponse(retrofit2.Call<List<StartLearning.SlModel>> call, Response<List<StartLearning.SlModel>> response) {
List<StartLearning.SlModel> list = response.body();
//after getting the results pass to addChips()
addChips(list)
Log.d("TAG","Response = "+movieList);
}
#Override
public void onFailure(retrofit2.Call<List<StartLearning.SlModel>> call, Throwable t) {
Log.d("TAG","Response = "+t.toString());
}
});
}
//just call this when you get the search result from the api with your custom model and where ever it is applicable.
public void addChips(List<StartLearning.SlModel> searchItems){
for (StartLearning.SlModel item : searchItems) {
Chip mChip = (Chip) this.getLayoutInflater().inflate(R.layout.item_chip, null, false);
mChip.setText(item.title);
int paddingDp = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 10,
getResources().getDisplayMetrics()
);
mChip.setPadding(paddingDp, 0, paddingDp, 0);
mChip.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
// Handle the click here
}
});
chipGroup.removeAllViews();
chipGroup.addView(mChip);
}
}
}
I can't find the relevant code in Search activity to give an example. but the general idea is as below.
1) You add a ChipGroup to hold the Chip Views which will be added dynamically in your search view xml.
2) User Search something and you get the api response and you create a model based list.
3) you then iterate over the list one by one and create the dynamic chips.
4) But first create an item_chip.xml file with below content.
<com.google.android.material.chip.Chip xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:id=#+id/smallChip
style="#style/Widget.MaterialComponents.Chip.Choice"
android:textAppearance="?android:attr/textAppearance"
android:textColor="#color/secondaryTextColor"
app:chipBackgroundColor="#color/colorAccent" />
5) Now we are going to just inflate this layout file and add this to ChipGroup in for loop which we received earlier.
6) so the sample code goes like this to add the dynamic chips to ChipGroup. Here im using String as search items for simplicity you can use your own model here.
public void addChips(ArrayList<String> searchItems){
for (String item : searchItems) {
Chip mChip = (Chip) this.getLayoutInflater().inflate(R.layout.item_chip, null, false);
mChip.setText(item);
int paddingDp = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 10,
getResources().getDisplayMetrics()
);
mChip.setPadding(paddingDp, 0, paddingDp, 0);
mChip.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
// Handle the click here
}
});
chipGroup.addView(mChip);
}
}
now we have just added the chips dynamically to chipGroup which we declared earlier in search view layout . But this can also be done using Recyclerview instead of using ChipGropup just add the Chip View inside the recyclerview items and get a reference and set the text as you do with text views nothing to change except in adapter and item layout.
Edit: 4/1/20
Place the ChipGrop into the below XML file with search view. The idea is that the search view input box will be on top and the suggestions from the search will be just below the search box to give changing search results just right there on same screen. so call the search-related API call in the Search activity itself and pass the results to the sample method addChips() I have mentioned above.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/colorPrimary"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" />
<SearchView
android:id="#+id/searchView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:queryHint="Search Here"
android:iconifiedByDefault="false"
android:layout_alignParentTop="true"
android:background="#drawable/search_bar"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="20dp"
android:pointerIcon="crosshair"
android:theme="#style/Widget.AppCompat.SearchView"
android:focusedByDefault="true"/>
<com.google.android.material.chip.ChipGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:id="#+id/chipGroup"
app:chipSpacing="25dp"/>
</LinearLayout>
For more info read below blogs:
Material Design Chips
How to use Chips Blog
How to add Chips to ChipsGroup
Add this library in your gradle
implementation 'com.google.android.material:material:1.2.0-alpha02'
Change parent of AppTheme to Theme.MaterialComponents.Light.NoActionBar in values/styles.xml .just like this
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
Now You need to add edittext and chipgroup to your xml.Just like this
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/search_edittext"/>
<com.google.android.material.chip.ChipGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/chipgroup"
app:singleSelection="true"
>
</com.google.android.material.chip.ChipGroup>
Now create method add chip to chipgroup
void setChip(List<String> list)
{
chipgroup.removeAllViews();
for (String item : list)
{
Chip chip =new Chip(this);
chip.setText(item);
// necessary to get single selection working
chip.setCheckable(true);
chip.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.e("OnCheckedChangeListener", "Called");
}
});
//on chip click
chipgroup.addView(chip);
}
}
Now add addTextChangedListener to your edittext
search_edittext.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable s) {}
#Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {}
#Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
List<String> tem=new ArrayList();
for (String item : list)
{
if (item.toString().toLowerCase().contains(s.toString().toLowerCase()))
tem.add(item);
}
setChip(tem);
}
});
And this done.
You can do this Chip View button you after spending little time i found this library will be more suitable in your case as you are trying to achieve with search view.
So Try this out :
Add this line to your module level build.gradle:
dependencies {
implementation "com.hootsuite.android:nachos:1.1.1"
}
Include a NachoTextView in your xml layout as follows:
<com.hootsuite.nachos.NachoTextView
android:id="#+id/nacho_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
You can look entire thing on github also as you want to achieve through search view look for this answer : SearchView query hint before clicking it
I wants to develop app in which user could choose multiple photos from gallery and can add caption like there is in whatsapp to add captions in multiple images
Anyone can help me in this.
If you looking for this,
You are on right place,
Here is the full solution I do for helping the beginners :
Layout UI Design
<ImageView
android:contentDescription="#string/app_name"
android:id="#+id/currentStreamImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"/>
<ImageView
android:id="#+id/selected_photo"
android:contentDescription="#string/app_name"
android:background="#null"
android:layout_margin="12dp"
android:layout_alignParentEnd="true"
android:src="#drawable/add_image_icon"
android:layout_width="40dp"
android:layout_height="40dp" />
<LinearLayout
android:layout_alignParentBottom="true"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:padding="10dp"
android:background="#drawable/fade_in_black"
android:id="#+id/captionArea"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/caption"
android:hint="#string/enter_caption_here"
android:textStyle="italic"
android:textColor="#android:color/white"
android:textColorHint="#android:color/white"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:src="#android:drawable/ic_menu_send" />
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="100dp"/>
</LinearLayout>
AddImageWithCaptionFragment
public class AddImageWithCaptionFragment extends Fragment implements ImageWithCaptionListener {
private ArrayList<ImgCap> imgCapArrayList = new ArrayList<>();
private PerfectAdapter adapter;
private RecyclerView recyclerView;
private ImageView select,mainStream;
private EditText captionEt;
private int mCurrentPosition;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.add_img_with_cap_layout, container, false);
recyclerView = (RecyclerView)view.findViewById(R.id.recyclerView);
select = (ImageView) view.findViewById(R.id.selected_photo);
mainStream = (ImageView) view.findViewById(R.id.currentStreamImage);
captionEt = (EditText) view.findViewById(R.id.caption);
select.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TedBottomPicker bottomSheetDialogFragment = new TedBottomPicker.Builder(getActivity())
.setOnMultiImageSelectedListener(new TedBottomPicker.OnMultiImageSelectedListener() {
#Override
public void onImagesSelected(ArrayList<Uri> uriList) {
imgCapArrayList.clear();
for (int i=0;i<uriList.size();i++) {
ImgCap imgCap = new ImgCap(i,"", uriList.get(i));
imgCapArrayList.add(imgCap);
}
adapter = new PerfectAdapter(getActivity(),imgCapArrayList,mainStream,AddImageWithCaptionFragment.this);
LinearLayoutManager mLayoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setAdapter(adapter);
}
})
.setPeekHeight(1600)
.showTitle(false)
.setCompleteButtonText("Done")
.setEmptySelectionText("No Select")
.create();
bottomSheetDialogFragment.show(getActivity().getSupportFragmentManager());
}
});
captionEt.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) {
imgCapArrayList.get(mCurrentPosition).setCaption(s.toString());
}
#Override
public void afterTextChanged(Editable s) {
}
});
return view;
}
#Override
public void imgCaptionCallBack(int position) {
mCurrentPosition = position;
captionEt.setText(imgCapArrayList.get(mCurrentPosition).getCaption());
}
}
Custom Adapter Class
public class PerfectAdapter extends RecyclerView.Adapter<PerfectAdapter.MyViewHolder>{
private LayoutInflater inflater;
private Context context;
private ArrayList<ImgCap> imgCapsList;
private ImageView mainStream;
private ImageWithCaptionListener mCallBack;
public PerfectAdapter(Context context,ArrayList<ImgCap> imgCapsList,ImageView mainStream,ImageWithCaptionListener mCallBack) {
inflater = LayoutInflater.from(context);
this.context = context;
this.imgCapsList = imgCapsList;
this.mainStream = mainStream;
this.mCallBack = mCallBack;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.image_item_layout, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(MyViewHolder holder,final int position) {
final ImgCap element = imgCapsList.get(holder.getAdapterPosition());
Glide.with(context).load(element.getImagePath()).into(holder.image);
Glide.with(context).load(imgCapsList.get(0).getImagePath()).into(mainStream);
holder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Glide.with(context).load(element.getImagePath()).into(mainStream);
mCallBack.imgCaptionCallBack(position);
}
});
}
#Override
public int getItemCount() {
return imgCapsList.size();
}
class MyViewHolder extends RecyclerView.ViewHolder
{
ImageView image;
public MyViewHolder(View itemView) {
super(itemView);
image = (ImageView) itemView.findViewById(R.id.image);
}
}
}
Listener Class For CallBack
public interface ImageWithCaptionListener {
void imgCaptionCallBack(int position);
}
Item layout
<RelativeLayout
android:background="#android:color/white"
android:padding="1dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:contentDescription="#string/app_name"
android:id="#+id/image"
android:scaleType="centerCrop"
android:layout_width="100dp"
android:layout_height="100dp" />
</RelativeLayout>
POJO Class
public class ImgCap {
private int position;
private String caption;
private Uri imagePath;
public ImgCap(int position, String caption, Uri imagePath) {
this.position = position;
this.caption = caption;
this.imagePath = imagePath;
}
public int getPosition() {
return position;
}
public String getCaption() {
return caption;
}
public Uri getImagePath() {
return imagePath;
}
public void setPosition(int position) {
this.position = position;
}
public void setCaption(String caption) {
this.caption = caption;
}
public void setImagePath(Uri imagePath) {
this.imagePath = imagePath;
}
}
Just Copy and Paste , Enjoy !!!
I have been working on an app in which recycler view is used. This is what I wish it to be looked:
but right now, my code is showing like this:
I have like stuck at this point where views are not properly created in recyclerview {like 3-4 blank tabs in starting) and i need my app to look better. I am attaching my code below:
MainActivity Code:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private CustomAdapter customAdapter;
ListView listView;
public Cursor cursor;
public StudentRepo studentRepo;
private final static String TAG = MainActivity.class.getName().toString();
private static final String TAG_BOOKMARKS="bookmarks";
private static final String TAG_ABOUT_US="about";
//recyclerView implementation
private List<TopSample> wordlist=new ArrayList<>();
private RecyclerView recyclerView;
private StudentAdapter studentAdapter;
//recyclerView implementation done
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
studentRepo = new StudentRepo(this);
recyclerView=(RecyclerView)findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
DatabaseAccess databaseAccess = DatabaseAccess.getInstance(this);
databaseAccess.open();
Cursor cursor= databaseAccess.getInfo();
cursor.moveToFirst();
do{
TopSample topSample=new TopSample(cursor.getString(0));
wordlist.add(topSample);
}while (cursor.moveToNext());
databaseAccess.close();
studentAdapter=new StudentAdapter(wordlist);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(studentAdapter);
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getApplicationContext(), recyclerView, new ClickListener() {
#Override
public void onClick(View view, int position) {
TopSample topSample= wordlist.get(position);
Intent intent = new Intent(MainActivity.this, SearchResult.class);
intent.putExtra(SearchResult.EXTRA_NO, (int) position);
startActivity(intent);
}
#Override
public void onLongClick(View view, int position) {
}
}));
//Done recyclerview implement
ImageView imageView=new ImageView(this);
imageView.setImageResource(R.drawable.button_action);
FloatingActionButton actionButton = new FloatingActionButton.Builder(this)
.setContentView(imageView)
.build();
ImageView Bookmarks=new ImageView(this);
Bookmarks.setImageResource(R.drawable.button_action);
ImageView Aboutus=new ImageView(this);
Aboutus.setImageResource(R.drawable.button_action);
SubActionButton.Builder itemBuilder = new SubActionButton.Builder(this);
SubActionButton buttonbookmark = itemBuilder.setContentView(Bookmarks).build();
SubActionButton buttonaboutus = itemBuilder.setContentView(Aboutus).build();
buttonbookmark.setOnClickListener(this);
buttonaboutus.setOnClickListener(this);
buttonbookmark.setTag(TAG_BOOKMARKS);
buttonaboutus.setTag(TAG_ABOUT_US);
FloatingActionMenu actionMenu = new FloatingActionMenu.Builder(this)
.addSubActionView(buttonbookmark)
.addSubActionView(buttonaboutus)
.attachTo(actionButton)
.build();
}
public interface ClickListener{
void onClick(View view, int position);
void onLongClick (View view, int position);
}
public static class RecyclerTouchListener implements RecyclerView.OnItemTouchListener{
private GestureDetector gestureDetector;
private MainActivity.ClickListener clickListener;
public RecyclerTouchListener(Context context, final RecyclerView recyclerView,final MainActivity.ClickListener clickListener){
this.clickListener = clickListener;
gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
#Override
public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null) {
clickListener.onLongClick(child, recyclerView.getChildPosition(child));
}
}
});
}
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
clickListener.onClick(child, rv.getChildPosition(child));
}
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
#Override
public void onResume() {
super.onResume();
}
#Override
///#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.options_menu, menu);
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
SearchManager manager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView search = (SearchView) menu.findItem(R.id.search).getActionView();
search.setSearchableInfo(manager.getSearchableInfo(getComponentName()));
search.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String s) {
Log.d(TAG, "onQueryTextSubmit ");
//cursor = studentRepo.getStudentListByKeyword(s);
// if (cursor == null) {
// Toast.makeText(MainActivity.this, "No records found!", Toast.LENGTH_LONG).show();
// } else {
// Toast.makeText(MainActivity.this, cursor.getCount() + " records found!", Toast.LENGTH_LONG).show();
// }/
//customAdapter.swapCursor(cursor);
return false;
}
#Override
public boolean onQueryTextChange(String s) {
Log.d(TAG, "onQueryTextChange ");
final List<TopSample>filteredmodellist=filter(wordlist,s);
studentAdapter.setFilter(filteredmodellist);
// cursor = studentRepo.getStudentListByKeyword(s);
// if (cursor != null) {
// customAdapter.swapCursor(cursor);
// }
return true;
}
private List<TopSample>filter(List<TopSample>models,String query){
query=query.toLowerCase();
final List<TopSample>fliterdModelList=new ArrayList<>();
for(TopSample model:models){
final String text=model.getVocab().toLowerCase();
if (text.contains(query)){
fliterdModelList.add(model);
}
}
return fliterdModelList;
}
});
return true;
}
#Override
public void onClick(View v) {
if (v.getTag().equals(TAG_BOOKMARKS)){
startActivity(new Intent(this,Bookmarks.class));
}
if (v.getTag().equals(TAG_ABOUT_US)){
}
}
}
StudentAdapter file:
public class StudentAdapter extends RecyclerView.Adapter<StudentAdapter.MyViewHolder> {
private List<TopSample> wordslist= Collections.emptyList();
public class MyViewHolder extends RecyclerView.ViewHolder{
public TextView sword;
public MyViewHolder(View view){
super(view);
sword=(TextView)view.findViewById(R.id.vocab);
}
}
public StudentAdapter(List<TopSample> wordslist){
this.wordslist=wordslist;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView=LayoutInflater.from(parent.getContext()).inflate(R.layout.dictionary_list_row,parent,false);
MyViewHolder vh=new MyViewHolder(itemView);
return vh;
//return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
TopSample sample=wordslist.get(position);
holder.sword.setText(sample.getVocab());
}
#Override
public int getItemCount() {
return wordslist.size();
}
//SearchinRecyclerview
public void setFilter(List<TopSample> mTopSamples){
wordslist=new ArrayList<>();
wordslist.addAll(mTopSamples);
notifyDataSetChanged();
}
//SearchinRecyclerview end
}
dictionary_list_row.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:clickable="true"
android:focusableInTouchMode="true"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/vocab"
android:textStyle="bold"
android:textSize="20sp"
/>
</LinearLayout>
content_main.xml
<RelativeLayout
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="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:showIn="#layout/activity_main"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
Update your dictionary_list_row.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="wrap_content"
android:layout_margin="20dp"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="vertical">
<TextView
android:id="#+id/vocab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Country Name"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Code"
android:textSize="20sp"
android:textStyle="bold" />
</LinearLayout>
Update:
Make some change here add if section
DatabaseAccess databaseAccess = DatabaseAccess.getInstance(this);
databaseAccess.open();
Cursor cursor= databaseAccess.getInfo();
cursor.moveToFirst();
do{
if(cursor.getString(0) != null){
TopSample topSample=new TopSample(cursor.getString(0));
wordlist.add(topSample);
}
}while (cursor.moveToNext());
databaseAccess.close();
I just moved into the android RecyclerView and CardViewand ... and realized recyclerview don't have an option for Onclick listner, but after implement this feature, i just don't see any result.
hear is my code and layouts:
MainActivity:
public class MainActivity extends AppCompatActivity {
//private usefulSites_RecyclerView_Adapter mAdapter;
final Context context = this;
private RecyclerView mRecyclerView;
private StaggeredGridLayoutManager mGridLayoutManager;
private RecyclerViewAdapter mAdapter;
private String[] mList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onBackPressed();
}
});
//使用CollapsingToolbarLayout必须把title设置到CollapsingToolbarLayout上,设置到Toolbar上则不会显示
CollapsingToolbarLayout mCollapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar_layout);
mCollapsingToolbarLayout.setTitle("test");
//通过CollapsingToolbarLayout修改字体颜色
mCollapsingToolbarLayout.setExpandedTitleColor(Color.WHITE);//设置还没收缩时状态下字体颜色
mCollapsingToolbarLayout.setCollapsedTitleTextColor(Color.GREEN);
//mList = getResources().getStringArray(R.array.numbers);
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
mGridLayoutManager = new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mRecyclerView.setLayoutManager(mGridLayoutManager);
mAdapter = new RecyclerViewAdapter(getApplicationContext());
mRecyclerView.setAdapter(mAdapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
RecyclerViewAdapter
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
private Context mContext;
private String [] mSiteTitle,mSiteLink;
private int [] mThumbnail;
public RecyclerViewAdapter(Context contexts, String[] list) {
this.mContext = contexts;
this.mSiteTitle = list;
}
public RecyclerViewAdapter(Context contexts) {
this.mContext = contexts;
initList();
}
private void initList(){
UsfulSite_init mInit=new UsfulSite_init();
mSiteTitle= mInit.initSiteTitle();
mSiteLink=mInit.initSiteLink();
mThumbnail=mInit.initThumbnail();
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View itemView = inflater.inflate(R.layout.usful_sites_card_view, parent, false);
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.sTitle.setText(mSiteTitle[position]);
holder.sLink.setText(mSiteTitle[position]);
holder.sImage.setImageResource(mThumbnail[position]);
holder.setClickListener(new ItemClickListener() {
#Override
public void onClick(View view, int position, boolean isLongClick) {
if (isLongClick) {
Toast.makeText(mContext, "#" + position + " - " + mSiteTitle[position] + " (Long click)", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(mContext, "#" + position + " - " + mSiteTitle[position], Toast.LENGTH_SHORT).show();
}
}
});
}
#Override
public int getItemCount() {
return mSiteTitle.length;
}
public static class ViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener, View.OnLongClickListener{
private TextView sTitle,sLink;
private ImageView sImage;
private ItemClickListener clickListener;
public ViewHolder(View itemView) {
super(itemView);
sTitle = (TextView)itemView.findViewById(R.id.useful_sites_Title);
sLink=(TextView)itemView.findViewById(R.id.useful_sites_Link);
sImage=(ImageView)itemView.findViewById(R.id.useful_sites_thumbnail);
itemView.setTag(itemView);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
}
public void setClickListener(ItemClickListener itemClickListener) {
this.clickListener = itemClickListener;
}
#Override
public void onClick(View view) {
clickListener.onClick(view, getPosition(), false);
}
#Override
public boolean onLongClick(View view) {
clickListener.onClick(view, getPosition(), true);
return true;
}
}
}
Activity_main.xml:
<android.support.design.widget.CoordinatorLayout
android:id="#+id/coordinatorLayout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="256dp"
android:fitsSystemWindows="true">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:contentScrim="#30469b"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="#drawable/a"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.7" />
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none" />
</LinearLayout>
CardView Layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_margin="5dp"
card_view:cardCornerRadius="5dp"
card_view:cardElevation="4dp"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/mainHolder"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/useful_sites_thumbnail"
android:layout_width="match_parent"
android:layout_height="100dp"
android:scaleType="centerCrop"
android:tint="#color/photo_tint"
android:layout_centerInParent="true"
/>
<TextView
android:id="#+id/useful_sites_Title"
android:gravity="center"
android:background="?android:selectableItemBackground"
android:focusable="true"
android:clickable="true"
android:layout_width="match_parent"
android:layout_height="100dp"
android:textSize="24sp"
android:layout_centerInParent="true"
android:textColor="#android:color/white"
/>
<TextView
android:id="#+id/useful_sites_Link"
android:gravity="center"
android:background="?android:selectableItemBackground"
android:focusable="true"
android:clickable="true"
android:layout_width="match_parent"
android:layout_height="100dp"
android:textSize="24sp"
android:layout_centerInParent="true"
android:textColor="#android:color/white"
android:visibility="gone"
/>
</RelativeLayout>
I tested another ways for clickListner in RV butT, i just stuck in this.
can some one look at my code and guide me, Little about this.
If you want to implement onClick for each cardview, you can do like this:
in your XML:
<android.support.v7.widget.CardView
android:id="#+id/card_view">
...
</android.support.v7.widget.CardView>
Then, in your adapter code:
public static class ViewHolder extends RecyclerView.ViewHolder {
private CardView cardView;
public ViewHolder(View itemView) {
super(itemView);
cardView = (CardView) itemView.findViewById(R.id.card_view);
}
}
...
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//implement onClick
System.out.println("Clicked");
}
});
}
}
You can pass listener from Adapter to ViewHolder, and listen events there, and you also can pass event from Adapter to your Activity or where you create this Adapter
public class AlbumAdapter extends RecyclerView.Adapter<AlbumAdapter.ViewHolder> {
private List<Album> albums;
private Context context;
public AlbumAdapterClickListener recListener;
public AlbumAdapter(List<Album> albums, Context context, AlbumAdapterClickListener recListener) {
this.albums = albums;
this.context = context;
this.recListener = recListener;
}
public interface AlbumAdapterClickListener {
void recyclerViewClick(String albumID);
}
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView title;
public TextView count;
public ImageView picture;
public String albumID;
public AlbumClickListener listener;
//listener passed to viewHolder
public interface AlbumClickListener {
void albumOnClick(String albumID);
}
public ViewHolder(View v, AlbumClickListener listener) {
super(v);
title = (TextView) v.findViewById(R.id.album_list_title);
count = (TextView) v.findViewById(R.id.album_list_count);
picture = (ImageView) v.findViewById(R.id.album_list_picture);
this.listener = listener;
v.setOnClickListener(this);
}
#Override
public void onClick(View v) {
listener.albumOnClick(this.albumID);
}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
return new ViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.album_list_item, viewGroup, false),
new ViewHolder.AlbumClickListener() {
#Override
public void albumOnClick(String albumID) {
//TODO show gridView with current albumID
Log.e("fdf", albumID);
// albumID going to Fragment
recListener.recyclerViewClick(albumID);
}
});
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
Album album = albums.get(i);
viewHolder.albumID = album.getId();
viewHolder.count.setText(album.getPhotoCount());
viewHolder.title.setText(album.getName());
Picasso.with(context).load(albums.get(i).getCoverURL()).placeholder(R.mipmap.fb_place_holder).resize(140, 140)
.centerCrop().into(viewHolder.picture);
}
#Override
public int getItemCount() {
return albums.size();
}
}
The answer from VLeong works great for me! But a little clarification. This :
holder.cardView.setOnClickListener(new View.OnClickListener() {
need to be changed to :
holder.itemView.setOnClickListener(new View.OnClickListener(){
You Can Add your listener into constructor of View Holder.
public ViewHolder(View v) {
super(v);
title = (TextView) v.findViewById(R.id.album_list_title);
count = (TextView) v.findViewById(R.id.album_list_count);
picture = (ImageView) v.findViewById(R.id.album_list_picture);
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Handel yout event here
}
});
}
I'm trying to implement a recyclerview that behaves like my sketch below:
The idea is that there is a parent list, when an list item in the parent list is tapped, that list item reveals a child list that contains it's own data. when a list item is tapped in the child list, the value of that child is reflected and updates the value of the parent in the parent list item.
I've tried to get it working for the past 3 days to no avail. I tried using the AdvancedReyclerview library but to a beginner like me, it was a giant mess of things that didn't make sense especially when passing in the data. I copied and pasted files that I needed to get a minimal working version but I had no idea how to pass my data into the recyclerview and how to update it with the newly selected value.
Is it even possible to do what I'm trying to do or am I way out of my depth here?
If it's still difficult to understand, I can explain it more.
EDIT: someone recommended that I do this with the ExpandableListView rather than the RecyclerView. Any thoughts on that?
1.ExpandableRecyclerAdapter.class
public abstract class ExpandableRecyclerAdapter<T extends ExpandableRecyclerAdapter.ListItem> extends RecyclerView.Adapter<ExpandableRecyclerAdapter.ViewHolder> {
protected Context mContext;
protected List<T> allItems = new ArrayList<>();
protected List<T> visibleItems = new ArrayList<>();
private List<Integer> indexList = new ArrayList<>();
private SparseIntArray expandMap = new SparseIntArray();
private int mode;
protected static final int TYPE_HEADER = 1000;
private static final int ARROW_ROTATION_DURATION = 150;
public static final int MODE_NORMAL = 0;
public static final int MODE_ACCORDION = 1;
public ExpandableRecyclerAdapter(Context context) {
mContext = context;
}
public static class ListItem {
public int ItemType;
public ListItem(int itemType) {
ItemType = itemType;
}
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public int getItemCount() {
return visibleItems == null ? 0 : visibleItems.size();
}
protected View inflate(int resourceID, ViewGroup viewGroup) {
return LayoutInflater.from(mContext).inflate(resourceID, viewGroup, false);
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View view) {
super(view);
}
}
public class HeaderViewHolder extends ViewHolder {
ImageView arrow;
public HeaderViewHolder(View view) {
super(view);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
toggleExpandedItems(getLayoutPosition(),false);
/*if(isExpanded(getLayoutPosition())){
collapseItems(getLayoutPosition(),false);
}else {
expandItems(getLayoutPosition(),true);
}*/
}
});
}
public HeaderViewHolder(View view, final ImageView arrow) {
super(view);
this.arrow = arrow;
arrow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
handleClick();
}
});
}
protected void handleClick() {
if (toggleExpandedItems(getLayoutPosition(), false)) {
openArrow(arrow);
} else {
closeArrow(arrow);
}
}
public void bind(int position) {
arrow.setRotation(isExpanded(position) ? 90 : 0);
}
}
public boolean toggleExpandedItems(int position, boolean notify) {
if (isExpanded(position)) {
collapseItems(position, notify);
return false;
} else {
expandItems(position, notify);
if (mode == MODE_ACCORDION) {
collapseAllExcept(position);
}
return true;
}
}
public void expandItems(int position, boolean notify) {
int count = 0;
int index = indexList.get(position);
int insert = position;
for (int i=index+1; i<allItems.size() && allItems.get(i).ItemType != TYPE_HEADER; i++) {
insert++;
count++;
visibleItems.add(insert, allItems.get(i));
indexList.add(insert, i);
}
notifyItemRangeInserted(position + 1, count);
int allItemsPosition = indexList.get(position);
expandMap.put(allItemsPosition, 1);
if (notify) {
notifyItemChanged(position);
}
}
public void collapseItems(int position, boolean notify) {
int count = 0;
int index = indexList.get(position);
for (int i=index+1; i<allItems.size() && allItems.get(i).ItemType != TYPE_HEADER; i++) {
count++;
visibleItems.remove(position + 1);
indexList.remove(position + 1);
}
notifyItemRangeRemoved(position + 1, count);
int allItemsPosition = indexList.get(position);
expandMap.delete(allItemsPosition);
if (notify) {
notifyItemChanged(position);
}
}
protected boolean isExpanded(int position) {
int allItemsPosition = indexList.get(position);
return expandMap.get(allItemsPosition, -1) >= 0;
}
#Override
public int getItemViewType(int position) {
return visibleItems.get(position).ItemType;
}
public void setItems(List<T> items) {
allItems = items;
List<T> visibleItems = new ArrayList<>();
expandMap.clear();
indexList.clear();
for (int i=0; i<items.size(); i++) {
if (items.get(i).ItemType == TYPE_HEADER) {
indexList.add(i);
visibleItems.add(items.get(i));
}
}
this.visibleItems = visibleItems;
notifyDataSetChanged();
}
protected void removeItemAt(int visiblePosition) {
int allItemsPosition = indexList.get(visiblePosition);
allItems.remove(allItemsPosition);
visibleItems.remove(visiblePosition);
incrementIndexList(allItemsPosition, visiblePosition, -1);
incrementExpandMapAfter(allItemsPosition, -1);
notifyItemRemoved(visiblePosition);
}
private void incrementExpandMapAfter(int position, int direction) {
SparseIntArray newExpandMap = new SparseIntArray();
for (int i=0; i<expandMap.size(); i++) {
int index = expandMap.keyAt(i);
newExpandMap.put(index < position ? index : index + direction, 1);
}
expandMap = newExpandMap;
}
private void incrementIndexList(int allItemsPosition, int visiblePosition, int direction) {
List<Integer> newIndexList = new ArrayList<>();
for (int i=0; i<indexList.size(); i++) {
if (i == visiblePosition) {
if (direction > 0) {
newIndexList.add(allItemsPosition);
}
}
int val = indexList.get(i);
newIndexList.add(val < allItemsPosition ? val : val + direction);
}
indexList = newIndexList;
}
public void collapseAll() {
collapseAllExcept(-1);
}
public void collapseAllExcept(int position) {
for (int i=visibleItems.size()-1; i>=0; i--) {
if (i != position && getItemViewType(i) == TYPE_HEADER) {
if (isExpanded(i)) {
collapseItems(i, true);
}
}
}
}
public void expandAll() {
for (int i=visibleItems.size()-1; i>=0; i--) {
if (getItemViewType(i) == TYPE_HEADER) {
if (!isExpanded(i)) {
expandItems(i, true);
}
}
}
}
public static void openArrow(View view) {
view.animate().setDuration(ARROW_ROTATION_DURATION).rotation(180);
}
public static void closeArrow(View view) {
view.animate().setDuration(ARROW_ROTATION_DURATION).rotation(0);
}
public int getMode() {
return mode;
}
public void setMode(int mode) {
this.mode = mode;
}
}
2.activity_main
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView android:id="#+id/main_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent" />
3.item_header
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="#dimen/standard_padding">
<LinearLayout
android:id="#+id/lnr_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true">
<TextView
android:id="#+id/txt_header_address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="#mipmap/ic_usa"
android:gravity="center"
android:text="Beverly Hills"
android:textStyle="bold" />
</LinearLayout>
<ImageView
android:id="#+id/img_arrow"
android:layout_width="#dimen/arrow_size"
android:layout_height="#dimen/arrow_size"
android:layout_alignParentRight="true"
android:src="#mipmap/arrow" />
<TextView
android:id="#+id/txt_header_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:text="Home"
android:textStyle="bold" />
4.item_content.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:id="#+id/rcl_header_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/btn_cancle" />
<Button
style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="#string/btn_save" />
</RelativeLayout>
<LinearLayout
android:id="#+id/lnr_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/rcl_header_btn"
android:gravity="center_vertical"
android:orientation="vertical">
<EditText
android:id="#+id/edt_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="DESCRIPTION" />
<EditText
android:id="#+id/edt_address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Address" />
<LinearLayout
android:id="#+id/lnr_child_1"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/edt_city"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="City" />
<EditText
android:id="#+id/edt_state"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="State" />
</LinearLayout>
<LinearLayout
android:id="#+id/lnr_child_2"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/edt_zipcode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="Zip Code" />
<EditText
android:id="#+id/edt_country"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="Country" />
</LinearLayout>
</LinearLayout>
<RelativeLayout
android:id="#+id/rcl_bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/lnr_parent">
<CheckBox
android:id="#+id/chk_marked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/txt_type" />
<TextView
android:id="#+id/txt_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/btn_delete"
android:layout_toRightOf="#+id/chk_marked"
android:gravity="center"
android:text="SET AS DEFAULT" />
<Button
android:id="#+id/btn_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="DELETE" />
</RelativeLayout>
5.Adapter
public class PeopleAdapter extends ExpandableRecyclerAdapter<PeopleAdapter.PeopleListItem> {
public static final int TYPE_PERSON = 1001;
public PeopleAdapter(Context context) {
super(context);
setItems(getSampleItems());
}
public static class PeopleListItem extends ExpandableRecyclerAdapter.ListItem {
public String Text;
public PeopleListItem(String group) {
super(TYPE_HEADER);
Text = group;
}
public PeopleListItem(String first, String last) {
super(TYPE_PERSON);
Text = first + " " + last;
}
}
public class HeaderViewHolder extends ExpandableRecyclerAdapter.HeaderViewHolder {
TextView name;
public HeaderViewHolder(View view) {
super(view, (ImageView) view.findViewById(R.id.img_arrow));
name = (TextView) view.findViewById(R.id.txt_header_name);
}
public void bind(int position) {
super.bind(position);
name.setText(visibleItems.get(position).Text);
}
}
public class PersonViewHolder extends ExpandableRecyclerAdapter.ViewHolder {
EditText name;
public PersonViewHolder(View view) {
super(view);
name = (EditText) view.findViewById(R.id.edt_description);
}
public void bind(int position) {
name.setText(name.getText());
}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_HEADER:
return new HeaderViewHolder(inflate(R.layout.item_header, parent));
case TYPE_PERSON:
default:
return new PersonViewHolder(inflate(R.layout.item_content, parent));
}
}
#Override
public void onBindViewHolder(ExpandableRecyclerAdapter.ViewHolder holder, int position) {
switch (getItemViewType(position)) {
case TYPE_HEADER:
((HeaderViewHolder) holder).bind(position);
break;
case TYPE_PERSON:
default:
((PersonViewHolder) holder).bind(position);
break;
}
}
private List<PeopleListItem> getSampleItems() {
List<PeopleListItem> items = new ArrayList<>();
items.add(new PeopleListItem("Friends"));
items.add(new PeopleListItem("", ""));
items.add(new PeopleListItem("Friends"));
items.add(new PeopleListItem("", ""));
return items;
}
}
6.MainActivity.java
public class MainActivity extends AppCompatActivity {
RecyclerView recycler;
PeopleAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
recycler = (RecyclerView) findViewById(R.id.main_recycler);
adapter = new PeopleAdapter(this);
adapter.setMode(ExpandableRecyclerAdapter.MODE_ACCORDION);
recycler.setLayoutManager(new LinearLayoutManager(this));
recycler.setAdapter(adapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_expand_all:
adapter.expandAll();
return true;
case R.id.action_collapse_all:
adapter.collapseAll();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
You can check my library in here
And create something like below code:
public class PurchaseItemRecyclerViewAdapter extends ExpandableRecyclerView.Adapter<PurchaseItemRecyclerViewAdapter.ChildViewHolder,ExpandableRecyclerView.SimpleGroupViewHolder,String,String>
{
List<ItemModel> itemModels;
public PurchaseItemRecyclerViewAdapter() {
this.itemModels = new ArrayList<>();
itemModels.add(new ItemModel("group 0",3,"subitem :"));
itemModels.add(new ItemModel("group 1",3,"subitem :"));
itemModels.add(new ItemModel("group 2",2,"subitem :"));
itemModels.add(new ItemModel("group 3",1,"subitem :"));
itemModels.add(new ItemModel("group 4",3,"subitem :"));
itemModels.add(new ItemModel("group 5",5,"subitem :"));
}
#Override
public int getGroupItemCount() {
return itemModels.size();
}
#Override
public int getChildItemCount(int i) {
return itemModels.get(i).getSubItemCount();
}
#Override
public String getGroupItem(int i) {
return itemModels.get(i).getParentName();
}
#Override
public String getChildItem(int group, int child) {
return itemModels.get(group).getSubItemPrefix() + child;
}
#Override
protected ExpandableRecyclerView.SimpleGroupViewHolder onCreateGroupViewHolder(ViewGroup parent)
{
return new ExpandableRecyclerView.SimpleGroupViewHolder(parent.getContext());
}
#Override
protected ChildViewHolder onCreateChildViewHolder(ViewGroup parent, int viewType)
{
View rootView = LayoutInflater.from(parent.getContext()).inflate(R.layout.purchase_list_content,parent,false);
return new ChildViewHolder(rootView);
}
#Override
public void onBindGroupViewHolder(ExpandableRecyclerView.SimpleGroupViewHolder holder, int group) {
super.onBindGroupViewHolder(holder, group);
holder.setText(getGroupItem(group));
}
#Override
public void onBindChildViewHolder(ChildViewHolder holder, final int group, int position)
{
super.onBindChildViewHolder(holder, group, position);
holder.name.setText(getChildItem(group, position));
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
itemModels.get(group).setParentName("edited Parent");
notifyItemChanged(group);
}
});
}
#Override
public int getChildItemViewType(int i, int i1) {
return 1;
}
public class ChildViewHolder extends RecyclerView.ViewHolder
{
private TextView name;
public ChildViewHolder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.item_name);
}
}
}
and this ItemModel class:
public class ItemModel {
String parentName;
int subItemCount;
String subItemPrefix;
public ItemModel(String parentName, int subItemCount, String subItemPrefix) {
this.parentName = parentName;
this.subItemCount = subItemCount;
this.subItemPrefix = subItemPrefix;
}
public String getParentName() {
return parentName;
}
public void setParentName(String parentName) {
this.parentName = parentName;
}
public int getSubItemCount() {
return subItemCount;
}
public void setSubItemCount(int subItemCount) {
this.subItemCount = subItemCount;
}
public String getSubItemPrefix() {
return subItemPrefix;
}
public void setSubItemPrefix(String subItemPrefix) {
this.subItemPrefix = subItemPrefix;
}
}
This is bit late but take a look on this advanced recyclerview library https://github.com/h6ah4i/android-advancedrecyclerview
In their documentation you can see Expandable item related classes/interfaces
check it out.
You can easily achieve it with this library, there is a full example here.
Basically you group your items into sections:
class MySection extends StatelessSection {
String header;
List<String> list;
boolean expanded = true;
public MySection(String header, List<String> list) {
// call constructor with layout resources for this Section header and items
super(R.layout.section_header, R.layout.section_item);
this.myHeader = header;
this.myList = list;
}
#Override
public int getContentItemsTotal() {
return expanded? list.size() : 0;
}
#Override
public RecyclerView.ViewHolder getHeaderViewHolder(View view) {
return new HeaderViewHolder(view);
}
#Override
public void onBindHeaderViewHolder(RecyclerView.ViewHolder holder) {
final HeaderViewHolder headerHolder = (HeaderViewHolder) holder;
headerHolder.tvTitle.setText(title);
headerHolder.rootView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
expanded = !expanded;
headerHolder.imgArrow.setImageResource(
expanded ? R.drawable.ic_keyboard_arrow_up_black_18dp : R.drawable.ic_keyboard_arrow_down_black_18dp
);
sectionAdapter.notifyDataSetChanged();
}
});
}
#Override
public RecyclerView.ViewHolder getItemViewHolder(View view) {
// return a custom instance of ViewHolder for the items of this section
return new MyItemViewHolder(view);
}
#Override
public void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position) {
MyItemViewHolder itemHolder = (MyItemViewHolder) holder;
// bind your view here
itemHolder.tvItem.setText(list.get(position));
}
}
Then create instance of your sections and set up your adapter:
// Create an instance of SectionedRecyclerViewAdapter
SectionedRecyclerViewAdapter sectionAdapter = new SectionedRecyclerViewAdapter();
// Add your Sections
sectionAdapter.addSection(new MySection("A", Arrays.asList(new String[] {"a", "b", "c" })));
sectionAdapter.addSection(new MySection("B", Arrays.asList(new String[] {"d", "e", "f" })));
// Set up your RecyclerView with the SectionedRecyclerViewAdapter
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(sectionAdapter);