Having trouble with switchbuttons in RecyclerView - android

I am new to Android Studio and Firebase-programming.
I am trying to write a simple shoplist-app with a RecyclerView where every item holds a TextView and a Switch-button.
If i add more than seven items to the RecyclerView the switchbuttons start to behave very strange and checks several other switchbuttons. I am aware of the recycling of every list item in RecyclerView and have tried to google this "problem" but haven't found a way to implement other peoples answers in to my code. I think I have screwed up the Adapter or ViewHolder in some way.
Here is my adapter:
public class ListAdapter extends RecyclerView.Adapter<ShoppingItemViewHolder> {
private ArrayList<ShoppingItem> mShoppingItems = new ArrayList<>();
#NonNull
#Override
public ShoppingItemViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
Context mContext = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(mContext);
View listItemView = inflater.inflate(R.layout.list_item, parent, false);
Switch boughtSwitch = listItemView.findViewById(R.id.boughtSwitchId);
TextView itemTextView = listItemView.findViewById(R.id.itemTextView);
return new ShoppingItemViewHolder(listItemView);
}
#Override
public void onBindViewHolder(#NonNull ShoppingItemViewHolder holder, int position) {
ShoppingItem shoppingItem = mShoppingItems.get(position);
holder.bind(shoppingItem);
}
#Override
public int getItemCount() {
return mShoppingItems.size();
}
public void addItem(ShoppingItem shoppingItem){
mShoppingItems.add(shoppingItem);
notifyDataSetChanged();
}
public void removeItem(ShoppingItem shoppingItem){
mShoppingItems.remove(shoppingItem);
notifyDataSetChanged();
}
#Override
public long getItemId(int position) {
return position;
}
And here is my 'ShoppingItem'ViewHolder (Separate file, if that is a problem?) :
class ShoppingItemViewHolder extends RecyclerView.ViewHolder {
private final TextView productName;
private final Switch boughtSwitch;
public static final String ITEMS_FIREBASE_KEY = "ItemsList";
DatabaseReference ref = FirebaseDatabase.getInstance().getReference(ITEMS_FIREBASE_KEY);
public ShoppingItemViewHolder(View view) {
super(view);
productName = view.findViewById(R.id.itemTextView);
boughtSwitch = view.findViewById(R.id.boughtSwitchId);
}
public void bind(final ShoppingItem shoppingItem){
productName.setText(shoppingItem.productName);
boughtSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
boughtSwitch.setText("Köpt!");
shoppingItem.bought = true;
ref.child(shoppingItem.pushKey).child("bought").setValue(true);
} else {
boughtSwitch.setText("Köpt?");
shoppingItem.bought = false;
ref.child(shoppingItem.pushKey).child("bought").setValue(false);
}
}
});
boughtSwitch.setChecked(shoppingItem.bought);
}
And my MainActivity:
public class MainActivity extends AppCompatActivity
implements ChildEventListener{
private ArrayList<ShoppingItem> shoppingItems = new ArrayList<>();
public static final String ITEMS_FIREBASE_KEY = "ItemsList";
FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance();
DatabaseReference ref = firebaseDatabase.getReference(ITEMS_FIREBASE_KEY);
private TextView itemText;
private RecyclerView itemList;
private ListAdapter itemAdapter;
private EditText itemEntry;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
itemList = findViewById(R.id.item_recycler_list);
itemList.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL, false));
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
itemText = findViewById(R.id.itemTextView);
itemEntry = findViewById(R.id.addItemEditText);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
// .setAction("Action", null).show();
pushToFirebase();
}
});
itemAdapter = new ListAdapter();
itemList.setAdapter(itemAdapter);
ref.addChildEventListener(this);
}
#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) {
removeItemsFromFirebase();
return true;
}
return super.onOptionsItemSelected(item);
}
private void pushToFirebase() {
String item = itemEntry.getText().toString();
boolean bought = false;
ShoppingItem shoppingItem = new ShoppingItem(item, bought);
shoppingItem.pushKey = ref.push().getKey();
ref.child(shoppingItem.pushKey).setValue(shoppingItem);
}
private void removeItemsFromFirebase() {
DatabaseReference queryRef = FirebaseDatabase.getInstance().getReference(ITEMS_FIREBASE_KEY);
Query boughtQuery = queryRef.child(ITEMS_FIREBASE_KEY).orderByChild("bought").equalTo(true);
boughtQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot querySnap : dataSnapshot.getChildren()){
querySnap.getRef().removeValue();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
ShoppingItem recievedShoppingItem = dataSnapshot.getValue(ShoppingItem.class);
itemAdapter.addItem(recievedShoppingItem);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
itemAdapter.clearItemList();
ShoppingItem recievedShoppingItem = dataSnapshot.getValue(ShoppingItem.class);
itemAdapter.addItem(recievedShoppingItem);
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
ShoppingItem recievedShoppingItem = dataSnapshot.getValue(ShoppingItem.class);
itemAdapter.removeItem(recievedShoppingItem);
itemAdapter.notifyDataSetChanged();
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
itemAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
EDIT:
Here is my "list_item.xml":
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/itemTextView"
android:layout_width="218dp"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="TextView"
android:textSize="20dp" />
<Switch
android:id="#+id/boughtSwitchId"
android:layout_width="113dp"
android:layout_height="49dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:text="#string/bought_switch_text" />
I know it's a lot to go through but I would really appreciate if someone tries to help me.

I managed to make it work using Firebase UI database.
That way i didn't have to write my own methods for the adapater on Childlisteners.
Can post code if someone wants to!

Related

Padding between Firebase RecyclerView items

I have been trying to get some padding between the Firebase RecyclerView items.I tried using ItemDecoration, but it works only with the first item of the RecyclerView.
Would be a great help if you could point out my mistake.
This is what I get
What I am trying to get is a layout where there is a padding between each recyclerview item so that I could see the shadow of each item.
Here's my Java code where I use the Firebase RecyclerView to load items.
public class CommunityFragment extends Fragment {
private static final String KEY_RECYCLER_STATE = "";
private RecyclerView mConvList;
private DatabaseReference mConvDatabase;
private DatabaseReference mUsersDatabase;
private DatabaseReference mMessageDatabase;
private Bundle mBundleRecyclerViewState;
private Parcelable mListState;
private static final String TAG = "ChatsFragment";
public CommunityFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View mMainView = inflater.inflate(R.layout.fragment_chats, container, false);
mConvList = (RecyclerView) mMainView.findViewById(R.id.conv_list);
FirebaseAuth mAuth = FirebaseAuth.getInstance();
String mCurrent_user_id = Objects.requireNonNull(mAuth.getCurrentUser()).getUid();
mConvDatabase = FirebaseDatabase.getInstance().getReference().child("Chat").child(mCurrent_user_id);
mConvDatabase.keepSynced(true);
mUsersDatabase = FirebaseDatabase.getInstance().getReference().child("Users");
mUsersDatabase.keepSynced(true);
mMessageDatabase = FirebaseDatabase.getInstance().getReference().child("messages").child(mCurrent_user_id);
mMessageDatabase.keepSynced(true);
mConvList = mMainView.findViewById(R.id.conv_list);
mConvList.setHasFixedSize(true);
mConvList.setLayoutManager(new LinearLayoutManager(getContext()));
// Inflate the layout for this fragment
return mMainView;
}
#Override
public void onStart() {
super.onStart();
Query conversationQuery = mConvDatabase.orderByChild("timestamp");
FirebaseRecyclerOptions<Conv> friendsFirebaseRecyclerOptions = new FirebaseRecyclerOptions.Builder<Conv>()
.setQuery(conversationQuery, Conv.class)
.build();
FirebaseRecyclerAdapter<Conv, ConvViewHolder> firebaseConvAdapter = new FirebaseRecyclerAdapter<Conv, ConvViewHolder>(friendsFirebaseRecyclerOptions) {
#Override
protected void onBindViewHolder(#NonNull final ConvViewHolder holder, int position, #NonNull final Conv model) {
final String list_user_id = getRef(position).getKey();
assert list_user_id != null;
Query lastMessageQuery = mMessageDatabase.child(list_user_id).limitToLast(1);
lastMessageQuery.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
String data = Objects.requireNonNull(dataSnapshot.child("message").getValue()).toString();
String seen_ = Objects.requireNonNull(dataSnapshot.child("seen").getValue()).toString();
holder.setMessage(data, Boolean.parseBoolean(seen_));
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
mUsersDatabase.child(list_user_id).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
final String userName = dataSnapshot.child("Name").getValue().toString();
holder.setName(userName);
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent chatIntent = new Intent(getContext(), ChatActivity.class);
chatIntent.putExtra("user_id", list_user_id);
chatIntent.putExtra("user_name",userName);
startActivity(chatIntent);
}
});
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
#NonNull
#Override
public ConvViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.single_q_layout, viewGroup, false);
return new ConvViewHolder(view);
}
};
mConvList.addItemDecoration(new PaddingItemDecoration(200));
firebaseConvAdapter.startListening();
mConvList.setAdapter(firebaseConvAdapter);
}
public void onPause(){
super.onPause();
mBundleRecyclerViewState = new Bundle();
mListState = mConvList.getLayoutManager().onSaveInstanceState();
mBundleRecyclerViewState.putParcelable(KEY_RECYCLER_STATE, mListState);
}
public void onResume(){
super.onResume();
if (mBundleRecyclerViewState != null) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
mListState = mBundleRecyclerViewState.getParcelable(KEY_RECYCLER_STATE);
mConvList.getLayoutManager().onRestoreInstanceState(mListState);
}
}, 50);
}
mConvList.setLayoutManager(new LinearLayoutManager(getContext()));
}
public class ConvViewHolder extends RecyclerView.ViewHolder {
View mView;
public ConvViewHolder(#NonNull View itemView) {
super(itemView);
mView = itemView;
}
public void setName(String name){
TextView userNameView = (TextView) mView.findViewById(R.id.question_title);
userNameView.setText(name);
}
public void setMessage(String message, boolean isSeen) {
TextView userStatusView = (TextView) mView.findViewById(R.id.question_catergory);
//Log.i("textData", "State is " + isSeen);
if(!isSeen){
userStatusView.setText("New Message");
userStatusView.setTypeface(userStatusView.getTypeface(), Typeface.BOLD);
}else{
userStatusView.setText("No New Messages");
userStatusView.setTypeface(userStatusView.getTypeface(), Typeface.NORMAL);
}
}
}
}
This is my PaddingItemDecoration class.
public class PaddingItemDecoration extends RecyclerView.ItemDecoration {
private final int size;
public PaddingItemDecoration(int size) {
this.size = size;
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
// Apply offset only to first item
if (parent.getChildAdapterPosition(view) == 0) {
outRect.top += size;
outRect.bottom += size;
}
}
And this is the XML file of my Adapter I use to load my RecyclerView items.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:id="#+id/relativeLayout3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/message_text_background"
android:elevation="4dp"
android:padding="10dp">
<TextView
android:id="#+id/question_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:padding="10dp"
android:text="Display Name"
android:textColor="#020202"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/question_catergory"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:text="catergory"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/question_title" />
<TextView
android:id="#+id/counter_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="counter"
app:layout_constraintEnd_toStartOf="#+id/answers_given"
app:layout_constraintTop_toBottomOf="#+id/question_title" />
<TextView
android:id="#+id/answers_given"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="answers"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/question_title" />
</androidx.constraintlayout.widget.ConstraintLayout>
Instead of using this PaddingItemDecoration, just add margin around your XML file of adapter.
As I can see you already added padding to the parent constraint layout (try margin), so just remove your decoration class and just try simply printing list to screen, you should be good to go.
Below image is an example of ListItem layout for adapter from my app, yours also should look like this one.
Try to add margin 10dp
If you aren't able to do so, try implementing the way shown in this article.

particular title(fetched from api) using searchview?

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

Implementing Heterogeneous RecyclerView using firebase

I am trying to implement multiple view or so called heterogeneous recyclerview using firebase realtime database. I found a example of heterogeneous recyclerview implementation on github.
I followed this to implement on firebase. But my code didn't work.
fragment_search.java (one of the fragment in my tabbed view) This is my fragment file which contains the main recyclerview which will hold multiple views
public class fragment_search extends Fragment {
RecyclerView recyclerViewSearch;
private static SingleSearchBannerModel singleSearchBannerModel;
private static SingleSearchType1Model singleSearchType1Model;
private static DatabaseReference databaseReference;
private List<Object> objects = new ArrayList<>();
private static SearchMainAdapter searchMainAdapter;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_search,null);
//Recycler view initialized and Properties Set.
recyclerViewSearch = view.findViewById(R.id.recyclerview_search);
recyclerViewSearch.setHasFixedSize(true);
recyclerViewSearch.setLayoutManager(new LinearLayoutManager(getContext()));
databaseReference = FirebaseDatabase.getInstance().getReference();
return view;
}
private List<Object> getObjects(){
objects.addAll(getBannerData());
objects.addAll(getType1Data());
return objects;
}
public static List<SingleSearchBannerModel> getBannerData(){
final List<SingleSearchBannerModel> singleSearchBannerModelList = new ArrayList<>();
databaseReference.child("Featured").addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
singleSearchBannerModel = dataSnapshot.getValue(SingleSearchBannerModel.class);
singleSearchBannerModelList.add(singleSearchBannerModel);
searchMainAdapter.notifyDataSetChanged();
System.out.println("this is image in getBanner == "+singleSearchBannerModel.getImage());
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return singleSearchBannerModelList;
}
public static List<SingleSearchType1Model> getType1Data(){
final List<SingleSearchType1Model> singleSearchType1ModelList = new ArrayList<>();
databaseReference.child("Featured").addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
singleSearchType1Model = dataSnapshot.getValue(SingleSearchType1Model.class);
singleSearchType1ModelList.add(singleSearchType1Model);
searchMainAdapter.notifyDataSetChanged();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return singleSearchType1ModelList;
}
#Override
public void onStart() {
super.onStart();
searchMainAdapter = new SearchMainAdapter(getContext(),getObjects());
System.out.println("this is getObject == "+getObjects());
System.out.println("this is getBanner == "+getBannerData());
System.out.println("this is getType1 == "+getType1Data());
recyclerViewSearch.setAdapter(searchMainAdapter);
}
}
fragment_home.xml this is the xml file of fragment which contains one recyclerview (My main recyclerview).
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview_search"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
Model files
*I have two model files. Basically getter and setters *
SingleSearchBannerModel.java My firsts model file.
public class SingleSearchBannerModel {
String Image;
public SingleSearchBannerModel() {
}
public SingleSearchBannerModel(String image) {
Image = image;
}
public String getImage() {
return Image;
}
public void setImage(String image) {
Image = image;
}
}
SingleSearchType1Model.java This is my second model file.
public class SingleSearchType1Model {
String Image;
public SingleSearchType1Model() {
}
public SingleSearchType1Model(String image) {
Image = image;
}
public String getImage() {
return Image;
}
public void setImage(String image) {
Image = image;
}
}
RecyclerView Adapters
Adapters are the ones used to set the value to the recyclerView. I have three Adapters as I'm trying to insert two views in one recyclerview. One is the MainAdapter which combines the other two Adapters. The MainAdapter is set to the the recyclerview of fragment_search.java (my main fragment)
SearchBannerAdapter.java This adapter is to generate the required layout file and populate the inflated layout file.
public class SearchBannerAdapter extends RecyclerView.Adapter<SearchBannerAdapter.TaskViewHolder>{
List<SingleSearchBannerModel> data;
public SearchBannerAdapter(List<SingleSearchBannerModel> data) {
this.data = data;
}
#NonNull
#Override
public TaskViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.search_single_banners,parent,false);
return new TaskViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull TaskViewHolder holder, int position) {
SingleSearchBannerModel singleSearchBannerModel = data.get(position);
Picasso.get().load(singleSearchBannerModel.getImage()).fit().into(holder.imageView);
}
#Override
public int getItemCount() {
return data.size();
}
public static class TaskViewHolder extends RecyclerView.ViewHolder{
View mView;
ImageView imageView;
public TaskViewHolder(View itemView) {
super(itemView);
mView = itemView;
imageView = mView.findViewById(R.id.search_banner_imgView);
}
}
}
search_single_banners.xml The xml file which is inflated in SearchBannerAdapter.java
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.v7.widget.CardView
android:layout_width="290dp"
android:layout_height="160dp"
android:id="#+id/longCard"
android:layout_marginTop="50dp"
android:layout_marginEnd="20dp"
app:cardCornerRadius="20sp"
app:cardElevation="#dimen/ten"
app:cardPreventCornerOverlap="false"
android:layout_centerHorizontal="true">
<ImageView
android:id="#+id/search_banner_imgView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/test1"/>
</android.support.v7.widget.CardView>
SearchType1Adapter.java This is the second adapter which inflates search_type_1.xml
public class SearchType1Adapter extends RecyclerView.Adapter<SearchType1Adapter.TaskViewHolder>{
List<SingleSearchType1Model> data;
public SearchType1Adapter(List<SingleSearchType1Model> data) {
this.data = data;
}
#NonNull
#Override
public TaskViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.search_type_1,parent,false);
return new TaskViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull TaskViewHolder holder, int position) {
SingleSearchType1Model singleSearchType1Model = data.get(position);
Picasso.get().load(singleSearchType1Model.getImage()).fit().into(holder.imageView);
}
#Override
public int getItemCount() {
return data.size();
}
public static class TaskViewHolder extends RecyclerView.ViewHolder{
View mView;
ImageView imageView;
public TaskViewHolder(View itemView) {
super(itemView);
mView = itemView;
imageView = mView.findViewById(R.id.search_single_type_1_imgView);
}
}
}
search_type_1.xml The file that is inflated in SearchType1Adapter.java
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.v7.widget.CardView
android:layout_width="290dp"
android:layout_height="160dp"
android:id="#+id/longCard"
android:layout_marginTop="50dp"
android:layout_marginEnd="20dp"
app:cardCornerRadius="20sp"
app:cardElevation="#dimen/ten"
app:cardPreventCornerOverlap="false"
android:layout_centerHorizontal="true">
<ImageView
android:id="#+id/search_single_type_1_imgView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/test1"/>
</android.support.v7.widget.CardView>
SearchMainAdapter.java This is the main adapter which is used in fragment_search to populate the main recyclerview.
public class SearchMainAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
private List<Object> items;
private final int BANNER = 1;
private final int TYPE1 = 2;
public SearchMainAdapter(Context context, List<Object> items) {
this.context = context;
this.items = items;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view;
RecyclerView.ViewHolder holder;
switch (viewType){
case BANNER:
view = inflater.inflate(R.layout.search_banners,parent,false);
holder = new BannerViewHolder(view);
break;
case TYPE1:
view = inflater.inflate(R.layout.search_type_1,parent,false);
holder = new Type1ViewHolder(view);
break;
default:
view = inflater.inflate(R.layout.search_banners,parent,false);
holder = new Type1ViewHolder(view);
break;
}
return holder;
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
if(holder.getItemViewType() == BANNER)
BannerView((BannerViewHolder) holder);
else if (holder.getItemViewType() == TYPE1)
Type1View((Type1ViewHolder) holder);
}
private void BannerView(BannerViewHolder holder){
SearchBannerAdapter searchBannerAdapter = new SearchBannerAdapter(getBannerData());
holder.recyclerView.setLayoutManager(new LinearLayoutManager(context,LinearLayoutManager.HORIZONTAL,false));
holder.recyclerView.setAdapter(searchBannerAdapter);
}
private void Type1View(Type1ViewHolder holder){
SearchType1Adapter searchType1Adapter = new SearchType1Adapter(getType1Data());
holder.recyclerView.setLayoutManager(new LinearLayoutManager(context,LinearLayoutManager.HORIZONTAL,false));
holder.recyclerView.setAdapter(searchType1Adapter);
}
#Override
public int getItemCount() {
return items.size();
}
#Override
public int getItemViewType(int position) {
if (items.get(position) instanceof SingleSearchBannerModel)
return BANNER;
if (items.get(position) instanceof SingleSearchType1Model)
return TYPE1;
return -1;
}
public static class BannerViewHolder extends RecyclerView.ViewHolder{
RecyclerView recyclerView;
public BannerViewHolder(View itemView) {
super(itemView);
recyclerView = itemView.findViewById(R.id.recyclerview_banners);
}
}
public static class Type1ViewHolder extends RecyclerView.ViewHolder{
RecyclerView recyclerView;
public Type1ViewHolder(View itemView) {
super(itemView);
recyclerView = itemView.findViewById(R.id.recyclerview_search_type_1);
}
}
}
search_banners.xml and search_type_1.xml have the same code
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview_banners"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
The above code is not working. I want to know where i went wrong. My main objective is to make an app something like google play store or hotstar (In terms of UI). So I assume they are using single recyclerview and multiple view within it.
Thanks for help.
I know this answer is a bit late but it might still help someone in future. Here is how I achived the goal
public class HeteroActivity extends AppCompatActivity {
private ArrayList<Object> objects = new ArrayList<>();
private static final String TAG = HeteroActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hetero);
RecyclerView recyclerView = findViewById(R.id.recycler_View);
MainAdapter adapter = new MainAdapter(this, getObject());
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
private ArrayList<Object> getObject() {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference().child("Data");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
objects.add(getVerticalData(dataSnapshot).get(0));
objects.add(getHorizontalData(dataSnapshot).get(0));
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
return objects;
}
public static ArrayList<SingleVertical> getVerticalData(DataSnapshot dataSnapshot) {
ArrayList<SingleVertical> singleVerticals = new ArrayList<>();
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
singleVerticals.add(new SingleVertical(
snapshot.child("price").getValue(String.class),
snapshot.child("location").getValue(String.class),
snapshot.child("image").getValue(String.class)
));
Log.e(TAG,"Text loaded");
}
return singleVerticals;
}
public static ArrayList<SingleHorizontal> getHorizontalData(DataSnapshot dataSnapshot) {
ArrayList<SingleHorizontal> singleHorizontals = new ArrayList<>();
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
singleHorizontals.add(new SingleHorizontal(
snapshot.child("price").getValue(String.class),
snapshot.child("location").getValue(String.class),
snapshot.child("image").getValue(String.class)
));
Log.e(TAG,"Horizontal data loaded");
}
return singleHorizontals;
}
}
Then in your main Adapter
do this:
private void verticalView(final VerticalViewHolder holder) {
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference().child("Data");
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
VerticalAdapter adapter1 = new VerticalAdapter(getVerticalData(dataSnapshot), context);
holder.recyclerView.setLayoutManager(new LinearLayoutManager(context));
holder.recyclerView.setAdapter(adapter1);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void horizontalView(final HorizontalViewHolder holder) {
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference().child("Data");
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
HorizontalAdapter adapter = new HorizontalAdapter(getHorizontalData(dataSnapshot),context);
holder.recyclerView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));
holder.recyclerView.setAdapter(adapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}

Update value on Recyclerview click listener

i develop app using firebase to upload files and view it in Recyclerview
when i click on any item should take me to another activity and view the file in webView the issue is when i click on any item take the first file uploaded to firebase , i need when i click in any item take the file for this item
public class postShows extends AppCompatActivity {
private RecyclerView postlist;
private DatabaseReference mdatabase;
private FirebaseAuth auth;
ImageView imagepostl;
TextView textname;
String ma,mmmmmm;
PostUtils m;
Context context;
public static String imageURL, fileType,fileNAme;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_post_shows);
mdatabase = FirebaseDatabase.getInstance().getReference().child(PostNew.item);
auth = FirebaseAuth.getInstance();
imagepostl = (ImageView) findViewById(R.id.imagefilesource);
textname = (TextView) findViewById(R.id.textfilename);
postlist = (RecyclerView) findViewById(R.id.postRecycle);
postlist.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
postlist.setLayoutManager(linearLayoutManager);
}
#Override
protected void onStart() {
super.onStart();
FirebaseRecyclerAdapter<PostUtils, PostViewHolder> firebaseRecyclerAdapter = new
FirebaseRecyclerAdapter<PostUtils, PostViewHolder>(
PostUtils.class,
R.layout.post_row,
PostViewHolder.class,
mdatabase
)
{
#Override
protected void populateViewHolder(PostViewHolder viewHolder, PostUtils m, int position) {
fileType = m.getfiletype();
fileNAme=m.getFileName();
// viewHolder.setDesc(m.getDescription());
if (m.getfiletype().equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document")) {
// imagepostl.setImageResource(R.drawable.word);
viewHolder.setFileName(m.getFileName());
viewHolder.setWord(imagepostl);
mmmmmm= viewHolder.setImageURL(ma,m);
} else if (m.getfiletype().equals("application/pdf")) {
viewHolder.setFileName(m.getFileName());
viewHolder.setPDF(imagepostl);
mmmmmm= viewHolder.setImageURL(ma,m);
} else if (m.getfiletype().contains("image")) {
viewHolder.setimage(imagepostl);
mmmmmm= viewHolder.setImageURL(ma,m);
} else {
viewHolder.setFileName(m.getFileName());
{
viewHolder.setimage(imagepostl);
}
}
}
#Override
public PostViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
PostViewHolder viewHolder = super.onCreateViewHolder(parent, viewType);
viewHolder.setOnClickListener(new PostViewHolder.ClickListener() {
#Override
public void onItemClick(View view, int position) {
Intent intent = new Intent(Kasittestbank.getAppContext(), Kasit.class);
intent.putExtra("imageURL",mmmmmm);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Kasittestbank.getAppContext().startActivity(intent);
}
#Override
public void onItemLongClick(View view, int position) {
Toast.makeText(Kasittestbank.getAppContext(), "Item long clicked at " + position, Toast.LENGTH_SHORT).show();
}
});
return viewHolder;
}
};
postlist.setAdapter(firebaseRecyclerAdapter);
}
public static class PostViewHolder extends RecyclerView.ViewHolder {
View mview;
Bitmap bitmap;
FileOpen fileOpen;
public PostViewHolder(View itemView) {
super(itemView);
mview = itemView;
mview.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mClickListener.onItemClick(v, getAdapterPosition());
}
});
}
private PostViewHolder.ClickListener mClickListener;
//Interface to send callbacks...
public interface ClickListener {
public void onItemClick(View view, int position);
public void onItemLongClick(View view, int position);
}
public void setOnClickListener(PostViewHolder.ClickListener clickListener) {
mClickListener = clickListener;
}
public void setFileName(String name) {
TextView textName = (TextView) mview.findViewById(R.id.textfilename);
textName.setText(name);
}
public void setWord(ImageView imageResourses) {
ImageView imageView = (ImageView) mview.findViewById(R.id.imagefilesource);
imageView.setImageResource(R.drawable.word);
}
public void setPDF(ImageView imageResourses) {
ImageView imageView = (ImageView) mview.findViewById(R.id.imagefilesource);
imageView.setImageResource(R.drawable.pdf);
}
public void setimage(ImageView imageResourses) {
ImageView imageView = (ImageView) mview.findViewById(R.id.imagefilesource);
imageView.setImageResource(R.drawable.image);
}
public String setImageURL(String url, PostUtils maa){
url=maa.getImageUrl();
return url;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.logut:
Logut();
startActivity(new Intent(getApplicationContext(), LoginActivity.class));
}
return super.onOptionsItemSelected(item);
}
public void Logut() {
auth.signOut();
finish();
}
}
When you define a recyclerView, one method you should override is onBindViewHolder. Inside of that method is where you define the content of each element of the recyclerView.
So if you want to each row can be clickable, think you need something like this:
#Override
public void onBindViewHolder(PostViewHolder postViewHolder, int i) {
postViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Definde what happend when the item is clicked
//To identify which row, you can use postViewHolder.getAdapterPosition();
}
});
}
Let me know if works.

Edittext in RecylerView start lossing data

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);
}

Categories

Resources