I'm trying to replace a ListView with a RecyclerView. The click listeners I had set up for it look like this (this is from the Activity):
//Road Trip selection
roadTripList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
RoadTrip trip = trips.get(i);
Intent intent= new Intent(RoadTripListActivity.this, RoadTripActivity.class);
intent.putExtra("startLocation", trip.getStart());
intent.putExtra("endLocation", trip.getEnd());
intent.putExtra("routeType", trip.getType());
setResult(RoadTripActivity.ROADTRIP_LIST_INTENT_RESULT, intent);
finish();
overridePendingTransition(R.anim.in_right, R.anim.out_left);
}
});
//Road Trip deletion
roadTripList.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, final int i, long l) {
new AlertDialog.Builder(RoadTripListActivity.this)
.setTitle("Delete this Road Trip?")
.setMessage("Are you sure you want to delete this road trip from your saved trips?")
.setCancelable(true)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
trips.remove(i);
tripStrings.remove(i);
tinyDB.putListString("roadtrips", tripStrings);
//roadTripList.setAdapter(adapter);
adapter.updateAdapter(trips);
}
}).setNegativeButton("Cancel", null)
.create().show();
return true;
}
});
Adapter looks like this:
public class RoadTripListAdapter extends RecyclerView.Adapter<RoadTripListAdapter.ViewHolder> {
protected ArrayList<RoadTrip> trips;
protected Context context;
public RoadTripListAdapter(Context context, ArrayList<RoadTrip> trips) {
this.context = context;
this.trips = trips;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
private final TextView startTextView;
private final TextView endTextView;
private final ImageView imageView;
private final LinearLayout itemLayout;
public ViewHolder(View v) {
super(v);
startTextView = (TextView) v.findViewById(R.id.roadtrip_list_start);
endTextView = (TextView) v.findViewById(R.id.roadtrip_list_end);
imageView = (ImageView) v.findViewById(R.id.roadtrip_list_icon);
itemLayout = (LinearLayout) v.findViewById(R.id.roadtrip_list_item_layout);
}
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
//Get the corresponding step
final RoadTrip trip = trips.get(position);
holder.startTextView.setText(trip.getStart());
holder.endTextView.setText(trip.getEnd());
if (trip.getType().equals(SearchType.walking.name())) {
holder.imageView.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_directions_walk_24dp));
} else {
holder.imageView.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_directions_car_24dp));
}
}
#Override
public int getItemCount() {
return trips.size();
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.road_trip_list_item, parent, false);
return new ViewHolder(v);
}
public void updateAdapter(ArrayList<RoadTrip> trips) {
this.trips = trips;
this.notifyDataSetChanged();
}
}
And the list item xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/roadtrip_list_item_layout"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/roadtrip_list_icon"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="center_vertical"
android:layout_margin="5dp"
android:src="#drawable/ic_directions_car_24dp"/>
<LinearLayout
android:layout_width="wrap_content"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:id="#+id/roadtrip_list_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textColor="#color/black"
android:text="Start: "/>
<TextView
android:id="#+id/roadtrip_list_end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textColor="#color/black"
android:text="End: "/>
</LinearLayout>
</LinearLayout>
How can I set up the equivalent for a RecyclerView? Everything I can find on the subject says to set it up inside the adapter, but that won't work in this case... Is there a way to set it up in the Activity?
In onBindViewHolder, add OnClickListener and OnLongClickListener like this :
itemLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
RoadTrip trip = trips.get(position);
Intent intent= new Intent(RoadTripListActivity.this, RoadTripActivity.class);
intent.putExtra("startLocation", trip.getStart());
intent.putExtra("endLocation", trip.getEnd());
intent.putExtra("routeType", trip.getType());
setResult(RoadTripActivity.ROADTRIP_LIST_INTENT_RESULT, intent);
finish();
overridePendingTransition(R.anim.in_right, R.anim.out_left);
}
});
//Road Trip deletion
itemLayout.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
new AlertDialog.Builder(RoadTripListActivity.this)
.setTitle("Delete this Road Trip?")
.setMessage("Are you sure you want to delete this road trip from your saved trips?")
.setCancelable(true)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
trips.remove(position);
tripStrings.remove(position);
tinyDB.putListString("roadtrips", tripStrings);
notifyItemRemoved(position);
notifyItemRangeChanged(position, trips.size());
}
}).setNegativeButton("Cancel", null)
.create().show();
return true;
}
});
I figured it out:
((Activity) context).setResult(RoadTripActivity.ROADTRIP_LIST_INTENT_RESULT, intent);
((Activity) context).finish();
((Activity) context).overridePendingTransition(R.anim.in_right, R.anim.out_left);
I had been using getApplicationContext to pass as the context for the adapter, so I changed it to
adapter = new RoadTripListAdapter(this, trips);
in the activity.
out_marginLeft="50dp"
android:layout_marginTop="50dp"
android:layout_marginRight="50dp"
android:gravity="center"
android:orientation="vertical">
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/txtProgress"
android:layout_centerHorizontal="true"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:progress="50"
android:progressTint="#android:color/black" />
<TextView
android:id="#+id/txtProgress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Progress"
android:textColor="#android:color/black" />
</LinearLayout>
Java
Related
ok, I have a custom adapter which will display exercise, time, and whether the exercise is selected or not. When the user clicks on the clock icon inside every element in the adapter a dialogbox will show up, in which the user can modify the time for exercise. Once the time is entered the arraylist containing objects of type exercise will be updated. so the exerciseTime for that exercise object inside the list will be updated. Then the list will be refresh and the new exercise time will be displayed. but that is not the case. I can get the time to be updated. when I first create the arraylist of exercises, which I get from string.xml resource file, the default exercise time is 30min. but after the user updates, is still reflecting the time. any help apprciated.
entry_item.xml for custom adapter
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/backroundColor">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="3dp"
android:layout_marginBottom="3dp">
<ImageView
android:id="#+id/item_icon_imageview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.10"
android:src="#drawable/ic_running_exercise"/>
<TextView
android:id="#+id/exercise_textview"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.40"
android:textSize="20sp"
android:textColor="#color/textColor"
android:text="Running"/>
<TextView
android:id="#+id/exercise_time_textview"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.20"
android:textSize="18sp"
android:textColor="#color/textColor"
android:text="30 min"/>
<ImageView
android:layout_gravity="center"
android:id="#+id/set_time_imagview"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.20"
android:src="#drawable/ic_timer_black_24dp"/>
<CheckBox
android:id="#+id/exercise_checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.05"
android:buttonTint="#color/textColor"/>
</LinearLayout>
</RelativeLayout>
custom adapter
public class WorkoutAdapter extends ArrayAdapter<Exercise> {
public WorkoutAdapter(Context context, int num, ArrayList<Exercise> exerciseList) {
super(context, 0, exerciseList);
// allExercises = exerciseList;
}
#NonNull
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
// Get the data item for this position
final Exercise exercise = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.entry_item, parent, false);
}
// Lookup view for data population
ImageView exerciseImageview = convertView.findViewById(R.id.item_icon_imageview);
TextView exerciseNameTextview = convertView.findViewById(R.id.exercise_textview);
TextView exerTimeTextview = convertView.findViewById(R.id.exercise_time_textview);
final ImageView setTimeImageview = convertView.findViewById(R.id.set_time_imagview);
final CheckBox exerciseCheckbox = convertView.findViewById(R.id.exercise_checkBox);
exerciseNameTextview.setText(exercise.getExerciseName());
exerciseImageview.setImageResource(exercise.getExerciseImage());
//selected exercise checkbox
exerciseCheckbox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(exerciseCheckbox.isChecked()) {
exercise.setSelected(true);
}
else {
exercise.setSelected(false);
}
}
});
setTimeImageview.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
setTimerDialogBox(position);
Toast.makeText(getContext(), position+"", Toast.LENGTH_LONG).show();
}
});
return convertView;
}
/**
* alert dialogbox for add new item to listview
*/
private void setTimerDialogBox(final int position) {
// Creating alert Dialog with one Button
final AlertDialog.Builder alertDialog = new AlertDialog.Builder(getContext(), R.style.dialogBox);
alertDialog.setTitle("Set Time");
final EditText input = new EditText(getContext());
alertDialog.setView(input);
alertDialog.setIcon(R.drawable.ic_timer_black_24dp1);
alertDialog.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int which) {
long time = Long.parseLong(input.getText().toString());
Workout.exerciseList.get(position).setExerciseTime(time);
notifyDataSetChanged();
Toast.makeText(getContext(),"Time added", Toast.LENGTH_SHORT).show();
}
}).create();
alertDialog.setNegativeButton("CANCEL",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
}).create();
alertDialog.show();
}
}
I designed dialog and assigned it a file named XML layout with a set of elements and then created a function to show it from within fragment. It appeared on the emulator screen well but it did not appear the same on the device.
What are the appropriate adjustments to be shown on the device well?
// layout xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="260dp"
android:layout_height="260dp"
android:orientation="vertical"
android:background="#f71717">
<LinearLayout
android:id="#+id/l_layout"
android:paddingTop="10dp"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
tools:ignore="ObsoleteLayoutParam">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
tools:ignore="ExtraText">
<RadioGroup
android:id="#+id/radioSex"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:ignore="UselessParent">
<RadioButton
android:id="#+id/second2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:button="#null"
android:layoutDirection="rtl"
android:textAlignment="textStart"
android:layout_gravity="start"
android:textDirection="rtl"
android:drawablePadding="10dp"
android:drawableRight="#android:drawable/btn_radio"
android:text="رفض"
android:textColor="#ffffff"
android:textSize="20dp"
tools:ignore="HardcodedText,RtlHardcoded,SpUsage" />
<RadioButton
android:id="#+id/second"
android:checked="true"
android:layoutDirection="rtl"
android:textDirection="rtl"
android:textAlignment="textStart"
android:layout_gravity="start"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:button="#null"
android:drawablePadding="10dp"
android:drawableRight="#android:drawable/btn_radio"
android:text="قبول"
android:textColor="#ffffff"
android:textSize="20dp"
tools:ignore="HardcodedText,RtlHardcoded,SpUsage" />
</RadioGroup>
/>
</LinearLayout>
<TextView
android:id="#+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="#ffffff"
android:text="وقت التسليم"
android:textSize="20dp"
tools:ignore="HardcodedText,SpUsage" />
<Spinner
android:id="#+id/tex"
android:layout_width="172dp"
android:paddingRight="40dp"
android:layout_height="wrap_content"
android:layout_below="#+id/tv_title"
android:drawSelectorOnTop="true"
android:popupBackground="#fff78c"
style="#style/spinner_style"
tools:ignore="HardcodedText,RtlHardcoded,RtlSymmetry,SpUsage"
android:entries="#array/day_"/>
</LinearLayout>
<RelativeLayout
android:id="#+id/rl"
android:layout_width="250dp"
android:layout_height="129dp"
android:layout_below="#+id/l_layout"
android:background="#f71717"
android:layout_marginTop="0dp"
tools:ignore="ObsoleteLayoutParam">
<TextView
android:id="#+id/tv_h"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toStartOf="#+id/spinner_minutes2"
android:paddingLeft="10dp"
android:text="ساعة"
android:textColor="#ffffff"
tools:ignore="HardcodedText,RtlHardcoded,RtlSymmetry" />
<TextView
android:id="#+id/tv_m"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/spinner_minutes2"
android:layout_alignBottom="#+id/spinner_minutes2"
android:layout_alignStart="#+id/button_holder"
android:paddingLeft="10dp"
android:text="دق"
android:textColor="#ffffff"
tools:ignore="HardcodedText,RtlHardcoded,RtlSymmetry" />
<TextView
android:id="#+id/tv_pam"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/spinner_minutes"
android:layout_alignBottom="#+id/spinner_minutes"
android:layout_alignEnd="#+id/spinner_minutes3"
android:layout_marginEnd="12dp"
android:paddingLeft="30dp"
android:text="ص/م"
android:textColor="#ffffff"
tools:ignore="HardcodedText,RtlHardcoded,RtlSymmetry" />
<Spinner
android:id="#+id/spinner_minutes"
android:layout_width="85dip"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
style="#style/spinner_style"
android:popupBackground="#fff78c"
android:layout_alignStart="#+id/spinner_minutes2"
android:entries="#array/hour_" />
<Spinner
android:id="#+id/spinner_minutes2"
android:layout_width="85dip"
android:layout_height="wrap_content"
android:layout_below="#+id/spinner_minutes"
android:layout_marginStart="16dp"
android:popupBackground="#fff78c"
style="#style/spinner_style"
android:layout_toEndOf="#+id/tv_m"
android:entries="#array/hour_" />
<Spinner
android:id="#+id/spinner_minutes3"
android:layout_width="85dip"
android:layout_height="wrap_content"
style="#style/spinner_style"
android:paddingRight="20dp"
android:entries="#array/apm"
android:popupBackground="#fff78c"
tools:ignore="RtlHardcoded,RtlSymmetry"
android:layout_alignBaseline="#+id/spinner_minutes2"
android:layout_alignBottom="#+id/spinner_minutes2"
android:layout_toEndOf="#+id/spinner_minutes" />
<TextView
android:id="#+id/text_timer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:textAppearance="?android:attr/textAppearanceMedium"
android:visibility="gone" />
<LinearLayout
android:id="#+id/button_holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/spinner_minutes"
android:layout_centerHorizontal="true"
android:paddingTop="10dp"
android:layout_marginTop="20dip">
<Button
android:id="#+id/button_set"
android:layout_width="100dip"
android:layout_height="wrap_content"
android:layout_marginBottom="5dip"
android:layout_marginLeft="10dip"
android:text="الغاء"
tools:ignore="ButtonStyle,HardcodedText,RtlHardcoded" />
<Button
android:id="#+id/button_cancel"
android:layout_width="100dip"
android:layout_height="wrap_content"
android:layout_marginBottom="5dip"
android:layout_marginRight="10dip"
android:text="إرسال"
tools:ignore="ButtonOrder,ButtonStyle,HardcodedText,RtlHardcoded" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
//calss Fragment:
public class Page_6Fragment extends android.support.v4.app.Fragment implements AdapterView.OnItemSelectedListener {
TextView t1,t2,t3,t4;
Spinner spin ,spin2,spin3,spin4;
Dialog dialog;
RecyclerView recyclerView;
List<Customer> customers;
CustomerAdapter adapter;
View rootView;
String TAG = "MainActivity - ";
Context context;
API api;
Activity a;
public static Page_6Fragment newInstance() {
Page_6Fragment fragment = new Page_6Fragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.activity_customer, container, false);
// View rootView = inflater.inflate(R.xml.pref, container, false);
// Intent intent = new Intent(PreferenceDemoActivity.this,PrefsActivity.class);
// startActivity(intent);
this.context = getActivity();
recyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
customers = new ArrayList<>();
adapter = new CustomerAdapter(context, customers);
adapter.setLoadMoreListener(new CustomerAdapter.OnLoadMoreListener(){
#Override
public void onLoadMore() {
recyclerView.post(new Runnable() {
#Override
public void run() {
int index = customers.size() - 1;
loadMore(index);
}
});
//Calling loadMore function in Runnable to fix the
// java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling error
}
});
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(context));
//recyclerView.addItemDecoration(new VerticalLineDecorator(2));
recyclerView.setAdapter(adapter);
api = ServiceGenerator.createService(API.class);
load(0);
return rootView;
}
private void load(int index){
Call<List<Customer>> call = api.getCustomer(index);
call.enqueue(new Callback<List<Customer>>(){
#Override
public void onResponse(Call<List<Customer>> call, Response<List<Customer>> response){
// Toast.makeText(getActivity(), "tost "+response.body().get(0).post_writer, Toast.LENGTH_LONG).show();
// Log.i("TRUE_TRUE","Yes"+response.body().get(0).title);
if(response.isSuccessful()){
customers.addAll(response.body());
adapter.notifyDataChanged();
// Toast.makeText(MainActivity.this, "tost "+response.body().get(0).post_writer, Toast.LENGTH_LONG).show();
}else{
Log.e(TAG," Response Error "+String.valueOf(response.code()));
}
}
#Override
public void onFailure(Call<List<Customer>> call, Throwable t) {
Log.e(TAG," Response Error "+t.getMessage());
}
});
}
private void loadMore(int index){
//add loading progress view
customers.add(new Customer("load"));
adapter.notifyItemInserted(customers.size()-1);
Call<List<Customer>>call = api.getCustomer(index);
call.enqueue(new Callback<List<Customer>>(){
#Override
public void onResponse(Call<List<Customer>> call, Response<List<Customer>>response) {
if(response.isSuccessful()){
// remove loading view .......
customers.remove(customers.size()-1);
List<Customer>result=response.body();
if(result.size()>0){
// add loaded data
customers.addAll(result);
}else{//result size 0 means there is no more data available at server
adapter.setMoreDataAvailable(false);
//telling adapter to stop calling load more as no more server data available
Toast.makeText(context,"No More Data Available",Toast.LENGTH_LONG).show();
}
adapter.notifyDataChanged();
}else{
Log.e(TAG," Load More Response Error "+String.valueOf(response.code()));
}
}
#Override
public void onFailure(Call<List<Customer>>call,Throwable t) {
Log.e(TAG," Load More Response Error "+t.getMessage());
}
});
}
public void showDialog(Context context){
dialog = new Dialog(context);
dialog.setCancelable(true);
dialog.setContentView(R.layout.layout);
dialog.show();
String[] bankNames = {
"BO","SB","HD","PN","Bj"
};
t1= (TextView)dialog.findViewById(R.id.tv_h);
t2= (TextView)dialog.findViewById(R.id.tv_m);
t3= (TextView)dialog.findViewById(R.id.tv_title);
t4= (TextView)dialog.findViewById(R.id.tv_pam);
spin =(Spinner)dialog.findViewById(R.id.spinner_minutes);
spin2 =(Spinner)dialog.findViewById(R.id.spinner_minutes2);
spin3 =(Spinner)dialog.findViewById(R.id.spinner_minutes3);
spin4 =(Spinner)dialog.findViewById(R.id.tex);
spin.setOnItemSelectedListener(this);
spin2.setOnItemSelectedListener(this);
spin3.setOnItemSelectedListener(this);
spin4.setOnItemSelectedListener(this);
RadioButton radioButton2 = (RadioButton)dialog.findViewById(R.id.second2);
RadioButton radioButton = (RadioButton)dialog.findViewById(R.id.second);
RadioGroup radioGroup = (RadioGroup)dialog.findViewById(R.id.radioSex);
ArrayAdapter<String> a = new ArrayAdapter<String>(context,R.layout.spinner_item,bankNames);
//ArrayAdapter b = new ArrayAdapter(this,android.R.layout.simple_spinner_item,bankNames2);
a.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spin.setAdapter(a);
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
RadioButton radioButton = (RadioButton)dialog.findViewById(checkedId);
if (checkedId == R.id.second2) {
RadioYes();
} else if (checkedId == R.id.second) {
RadioNo();
}
}
});
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
((TextView) parent.getChildAt(0)).setTextColor(Color.WHITE);
((TextView) parent.getChildAt(0)).setTextColor(Color.WHITE);
((TextView) parent.getChildAt(0)).setTextSize(16);
// Toast.makeText(getApplicationContext(),"" +spin2.getSelectedItem(), Toast.LENGTH_LONG).show();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
public void RadioNo(){
spin.setVisibility(View.VISIBLE);
spin2.setVisibility(View.VISIBLE);
spin3.setVisibility(View.VISIBLE);
spin4.setVisibility(View.VISIBLE);
t1.setVisibility(View.VISIBLE);
t2.setVisibility(View.VISIBLE);
t3.setVisibility(View.VISIBLE);
t4.setVisibility(View.VISIBLE);
}
public void RadioYes(){
spin.setVisibility(View.GONE);
spin2.setVisibility(View.GONE);
spin3.setVisibility(View.GONE);
spin4.setVisibility(View.GONE);
t1.setVisibility(View.GONE);
t2.setVisibility(View.GONE);
t3.setVisibility(View.GONE);
t4.setVisibility(View.GONE);
}
}
// class to call function show dailoge
public class CustomerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public final int TYPE_MOVIE = 0;
public final int TYPE_LOAD = 1;
static Context context;
List<Customer> customers;
OnLoadMoreListener loadMoreListener;
boolean isLoading = false, isMoreDataAvailable = true;
public CustomerAdapter(Context context, List<Customer> customers) {
this.context = context;
this.customers = customers;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
if(viewType==TYPE_MOVIE){
return new CustomerHolder(inflater.inflate(R.layout.row_movie,parent,false));
}else{
return new LoadHolder(inflater.inflate(R.layout.row_load,parent,false));
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
if(position>=getItemCount()-1 && isMoreDataAvailable && !isLoading && loadMoreListener!=null){
isLoading = true;
loadMoreListener.onLoadMore();
}
if(getItemViewType(position)==TYPE_MOVIE){
((CustomerHolder)holder).bindData(customers.get(position));
if(((CustomerHolder)holder).buttonViewOption != null)((CustomerHolder)holder).buttonViewOption.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Page_6Fragment.newInstance().showDialog(context);
}
});
}
}
#Override
public int getItemViewType(int position) {
if(customers.get(position).type.equals("movie")){
return TYPE_MOVIE;
}else{
return TYPE_LOAD;
}
}
#Override
public int getItemCount(){
return customers.size();
}
/* VIEW HOLDERS */
static class CustomerHolder extends RecyclerView.ViewHolder{
TextView tvTitle;
TextView tvRating;
Button buttonViewOption;
public CustomerHolder(View itemView) {
super(itemView);
tvTitle=(TextView)itemView.findViewById(R.id.title);
tvRating=(TextView)itemView.findViewById(R.id.rating);
buttonViewOption = (Button) itemView.findViewById(R.id.textViewOptions);
}
void bindData(Customer cust){
tvTitle.setText(cust.name);
tvRating.setText(cust.title);
}
}
static class LoadHolder extends RecyclerView.ViewHolder{
public LoadHolder(View itemView) {
super(itemView);
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
/* notifyDataSetChanged is final method so we can't override it
call adapter.notifyDataChanged(); after update the list
*/
public void notifyDataChanged(){
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener{
void onLoadMore();
}
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
}
I'm trying to show an additional CardView that contains a different layout but have got lost with my code. I'm also unsure of how to to show the array of strings within a GridView for the CardView itself. Does anyone know where I may have gone wrong & what can be done so that the following can be achieved?:
Place the CardView containing the GridView wherever I want within the RecyclerView.
Show the array of strings in a GridView within a CardView
What I want to add to the RecyclerView (above the Item A CardView)
RecyclerView current contents
Fragment class
public class MyFragment extends android.support.v4.app.Fragment {
private MonRecyclerAdapterWithGrid adapterG;
static final String[] frenchVowels = new String[]{
"a", "e", "i", "o", "u", "y"
};
public MyFragment() {}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_rv, container, false);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
View v = getView();
assert v != null;
recyclerView = v.findViewById(R.id.my_recyclerview);
linearLayoutManager = new LinearLayoutManager(getActivity());
MyRecyclerAdapter adapter = new MyRecyclerAdapter(getContext(), getHeader(), getListItemsG(), getListItemsT());
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setAdapter(adapter);
super.onActivityCreated(savedInstanceState);
}
RecyclerView recyclerView;
LinearLayoutManager linearLayoutManager;
public RecyclerViewHeader getHeader()
{
return new RecyclerViewHeader();
}
public List<RecyclerViewItemGV> getListItemsG() {
List<RecyclerViewItemGV> rvItemsG = new ArrayList<>();
RecyclerViewItemGV itemG = new RecyclerViewItemGV();
itemG.setTitleGV("Item A");
itemG.setVowelsGV(adapterG);
for (String fVowels : frenchVowels) {
// ?????? Still not working :-(
adapterG.addAdapterItem(new MyFragment.AdapterItem(frenchVowels));
}
rvItemsG.add(itemG);
return rvItemsG;
}
public List<RecyclerViewItemTV> getListItemsT()
{
List<RecyclerViewItemTV> rvItemsT = new ArrayList<>();
RecyclerViewItemTV itemA = new RecyclerViewItemTV();
itemA.setTitleTV("Item A");
itemA.setDescriptionTV("Feature A1");
rvItemsT.add(itemA);
RecyclerViewItemTV itemB = new RecyclerViewItemTV();
itemB.setTitleTV("Item B");
itemB.setDescriptionTV("Feature B1\nFeature B2");
rvItemsT.add(itemB);
RecyclerViewItemTV itemC = new RecyclerViewItemTV();
itemC.setTitleTV("Item C");
itemC.setDescriptionTV("Feature C1\nFeature C2\nFeature C3");
rvItemsT.add(itemC);
return rvItemsT;
}
}
RecyclerView adapter class
public class MyRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int TYPE_HEADER = 0;
private static final int TYPE_ITEMG = 1;
private static final int TYPE_ITEMT = 2;
private Context mContext;
RecyclerViewHeader header;
List<RecyclerViewItemGV> listItemsG;
List<RecyclerViewItemTV> listItemsT;
ValueAnimator mAnimator;
public MyRecyclerAdapter(Context context, RecyclerViewHeader header, List<RecyclerViewItemGV> listItemsG, List<RecyclerViewItemTV> listItemsT)
{
this.mContext = context;
this.header = header;
this.listItemsG = listItemsG;
this.listItemsT = listItemsT;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType == TYPE_HEADER)
{
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_header_expandcollapsebuttons, parent, false);
return new MyRecyclerAdapter.VHHeader(v);
}
else if(viewType == TYPE_ITEMG)
{
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_item_gv, parent, false);
return new MyRecyclerAdapter.VHItemG(v);
}
else if(viewType == TYPE_ITEMT)
{
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_item_tv, parent, false);
return new MyRecyclerAdapter.VHItemT(v);
}
throw new RuntimeException("there is no type that matches the type " + viewType + " + make sure your using types correctly");
}
private RecyclerViewItemGV getItemG(int position)
{
return listItemsG.get(position);
}
private RecyclerViewItemTV getItemT(int position)
{
return listItemsT.get(position);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final Typeface iconFont = FontManager.getTypeface(mContext, FontManager.FONTAWESOME);
if (holder instanceof MyRecyclerAdapter.VHHeader)
{
final MyRecyclerAdapter.VHHeader vhHeader = (MyRecyclerAdapter.VHHeader)holder;
}
else if (holder instanceof MyRecyclerAdapter.VHItemG){
RecyclerViewItemGV currentItemG = getItemG(position-1);
final MonRecyclerAdapterWithGrid.VHItemG vhItemG = (MyRecyclerAdapter.VHItemG)holder;
vhItemG.txtAG.setText(currentItemG.getTitleGV());
vhItemG.mGridViewG.setVisibility(View.GONE);
vhItemG.txtExpandCollapseG.setText(R.string.fa_icon_chevron_down);
vhItemG.txtExpandCollapseG.setTypeface(iconFont);
//Add onPreDrawListener
vhItemG.mGridViewG.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
vhItemG.mGridViewG.getViewTreeObserver().removeOnPreDrawListener(this);
vhItemG.mGridViewG.setVisibility(View.GONE);
final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
vhItemG.mGridViewG.measure(widthSpec, heightSpec);
vhItemG.mGridViewHeight = vhItemG.mGridViewG.getMeasuredHeight();
return true;
}
});
vhItemG.mCardViewG.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(vhItemG.mGridViewG.getVisibility() == View.GONE){
vhItemG.expandG();
} else {
vhItemG.collapseG();
}
}
});
}
else if (holder instanceof MyRecyclerAdapter.VHItemT)
{
RecyclerViewItemTV currentItem = getItemT(position-2);
final MyRecyclerAdapter.VHItemT vhItemT = (MyRecyclerAdapter.VHItemT)holder;
vhItemT.txtA.setText(currentItem.getTitleTV());
vhItemT.txtB.setText(currentItem.getDescriptionTV());
vhItemT.txtB.setVisibility(View.GONE);
vhItemT.txtExpandCollapse.setText(R.string.fa_icon_chevron_down);
vhItemT.txtExpandCollapse.setTypeface(iconFont);
//Add onPreDrawListener
vhItemT.txtB.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
vhItemT.txtB.getViewTreeObserver().removeOnPreDrawListener(this);
vhItemT.txtB.setVisibility(View.GONE);
final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
vhItemT.txtB.measure(widthSpec, heightSpec);
vhItemT.textBHeight = vhItemT.txtB.getMeasuredHeight();
return true;
}
});
vhItemT.cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(vhItemT.txtB.getVisibility() == View.GONE){
vhItemT.expandT();
} else {
vhItemT.collapseT();
}
}
});
}
}
// need to override this method
#Override
public int getItemViewType(int position) {
if(isPositionHeader(position))
return TYPE_HEADER;
return TYPE_ITEMG;
return TYPE_ITEMT;
}
private boolean isPositionHeader(int position)
{
return position == 0;
}
#Override
public int getItemCount() {
return listItemsG.size()+1;
return listItemsT.size()+1;
}
class VHHeader extends RecyclerView.ViewHolder{
Button btnCollapseAll, btnExpandAll;
public VHHeader(View headerView) {
super(headerView);
this.btnCollapseAll = headerView.findViewById(R.id.btn_collapseall);
this.btnExpandAll = headerView.findViewById(R.id.btn_expandall);
}
}
public class VHItemG extends RecyclerView.ViewHolder{
CardView mCardViewG;
LinearLayout mLinearLayoutG;
RelativeLayout mRelativeLayoutG;
RecyclerView mRecyclerViewG;
GridView mGridViewG;
TextView txtExpandCollapseG, txtAG;
public int mGridViewHeight;
public VHItemG(View itemView) {
super(itemView);
this.mCardViewG = itemView.findViewById(R.id.cv_gv);
this.mLinearLayoutG = itemView.findViewById(R.id.linearlayout_gv_titlerow);
this.mRelativeLayoutG = itemView.findViewById(R.id.relativelayout_gv);
this.mRecyclerViewG = itemView.findViewById(R.id.my_recyclerview);
this.txtAG = itemView.findViewById(R.id.tv_gv_A);
this.txtExpandCollapseG = itemView.findViewById(R.id.tv_gv_expandcollapse);
this.mGridViewG = itemView.findViewById(R.id.gv_a);
}
private void expandG() {
// change visibility to 'VISIBLE'
mGridViewG.setVisibility(View.VISIBLE);
// change direction of chevron to 'up'
txtExpandCollapseG.setText(R.string.fa_icon_chevron_up);
// apply animation to the height of 'txtB'
mAnimator = slideAnimator(0, mGridViewHeight);
// start the animation
mAnimator.start();
}
private void collapseG() {
// change direction of chevron to 'down'
txtExpandCollapseG.setText(R.string.fa_icon_chevron_down);
int finalHeight = mGridViewG.getHeight();
ValueAnimator mAnimator = slideAnimator(finalHeight, 0);
mAnimator.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationEnd(Animator animator) {
// Height will be 0, but set visibility to 'GONE'
mGridViewG.setVisibility(View.GONE);
}
#Override
public void onAnimationStart(Animator animator) {
}
#Override
public void onAnimationCancel(Animator animator) {
}
#Override
public void onAnimationRepeat(Animator animator) {
}
});
mAnimator.start();
}
public ValueAnimator slideAnimator(int start, int end) {
ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
// update height
int value = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = mGridViewG.getLayoutParams();
layoutParams.height = value;
mGridViewG.setLayoutParams(layoutParams);
}
});
return animator;
}
}
public class VHItemT extends RecyclerView.ViewHolder{
CardView cardView;
LinearLayout mLinearLayout;
RecyclerView mRecyclerView;
RelativeLayout mRelativeLayout;
TextView txtExpandCollapse, txtA, txtB;
public int textBHeight;
public VHItemT(View itemView) {
super(itemView);
this.cardView = itemView.findViewById(R.id.linearlayout_tv_main);
this.mLinearLayout = itemView.findViewById(R.id.linearlayout_tv_titlerow);
this.mRelativeLayout = itemView.findViewById(R.id.relativelayout_tv);
this.mRecyclerView = itemView.findViewById(R.id.my_recyclerview);
this.txtExpandCollapse = itemView.findViewById(R.id.tv_tv_expandcollapse);
this.txtA = itemView.findViewById(R.id.tv_tv_A);
this.txtB = itemView.findViewById(R.id.tv_tv_B);
}
private void expandT() {
// change visibility to 'VISIBLE'
txtB.setVisibility(View.VISIBLE);
// change direction of chevron to 'up'
txtExpandCollapse.setText(R.string.fa_icon_chevron_up);
// apply animation to the height of 'txtB'
mAnimator = slideAnimator(0, textBHeight);
// start the animation
mAnimator.start();
}
private void collapseT() {
// change direction of chevron to 'down'
txtExpandCollapse.setText(R.string.fa_icon_chevron_down);
int finalHeight = txtB.getHeight();
ValueAnimator mAnimator = slideAnimator(finalHeight, 0);
mAnimator.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationEnd(Animator animator) {
// Height will be 0, but set visibility to 'GONE'
txtB.setVisibility(View.GONE);
}
#Override
public void onAnimationStart(Animator animator) {
}
#Override
public void onAnimationCancel(Animator animator) {
}
#Override
public void onAnimationRepeat(Animator animator) {
}
});
mAnimator.start();
}
public ValueAnimator slideAnimator(int start, int end) {
ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
// update height
int value = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = txtB.getLayoutParams();
layoutParams.height = value;
txtB.setLayoutParams(layoutParams);
}
});
return animator;
}
}
}
GridView adapter (currently excluded from project)
private class MyGVAdapter extends ArrayAdapter<AdapterItem> {
private List<AdapterItem> items = new ArrayList<>();
MyGVAdapter(Context context, int textviewid) {
super(context, textviewid);
}
void addAdapterItem(MyGVFragment.AdapterItem item) {
items.add(item);
}
#Override
public int getCount() {
return items.size();
}
#Override
public MyGVFragment.AdapterItem getItem(int position) {
return ((null != items) ? items.get(position) : null);
}
#Override
public long getItemId(int position) {
return position;
}
#NonNull
#Override
public View getView(final int position, View convertView, #NonNull final ViewGroup parent) {
View rowView;
if (convertView == null) {
rowView = getActivity().getLayoutInflater().inflate(R.layout.gridview_item, parent, false);
} else {
rowView = convertView;
}
TextView tv = rowView.findViewById(R.id.item_gridview);
tv.setText(items.get(position).first);
return rowView;
}
}
class AdapterItem {
String first;
AdapterItem(String first) {
this.first = first;
}
}
}
gridview_item.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="match_parent" >
<TextView
android:id="#+id/item_gridview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="0dp"
android:paddingEnd="10dp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="?android:attr/textColorPrimary"
/>
</LinearLayout>
CardView with GridView (recyclerview_item_gv)
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:id="#+id/cv_gv"
android:layout_marginBottom="20dp"
>
<LinearLayout
android:id="#+id/lineralayout_gv_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp"
android:animateLayoutChanges="true">
<LinearLayout
android:id="#+id/linearlayout_gv_titlerow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="2dp"
android:weightSum="100">
<TextView
android:id="#+id/tv_gv_A"
android:layout_weight="90"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textColor="?android:attr/textColorPrimary"
style="#android:style/TextAppearance.Medium" />
<TextView
android:id="#+id/tv_gv_expandcollapse"
android:importantForAccessibility="no"
android:clickable="true"
android:focusable="true"
android:layout_weight="10"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:textColor="?android:attr/textColorPrimary"
style="#android:style/TextAppearance.Large" />
</LinearLayout>
<RelativeLayout
android:id="#+id/relativelayout_gv"
android:animateLayoutChanges="true"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<GridView
android:id="#+id/gv_a"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:columnWidth="100dp"
android:numColumns="auto_fit"
android:layout_marginBottom="20dp"
android:stretchMode="columnWidth" />
</RelativeLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
CardView with TextView (recyclerview_item_tv.xml)
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:id="#+id/cv_tv"
android:layout_marginBottom="20dp">
<LinearLayout
android:id="#+id/linearlayout_gv_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp"
android:animateLayoutChanges="true">
<LinearLayout
android:id="#+id/linearlayout_tv_titlerow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="2dp"
android:weightSum="100">
<TextView
android:id="#+id/tv_tv_A"
android:layout_weight="90"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textColor="?android:attr/textColorPrimary"
style="#android:style/TextAppearance.Medium" />
<TextView
android:id="#+id/tv_tv_expandcollapse"
android:importantForAccessibility="no"
android:clickable="true"
android:focusable="true"
android:layout_weight="10"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:textColor="?android:attr/textColorPrimary"
style="#android:style/TextAppearance.Large" />
</LinearLayout>
<RelativeLayout
android:id="#+id/relativelayout_tv"
android:animateLayoutChanges="true"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/tv_B"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?android:attr/textColorPrimary"
style="#android:style/TextAppearance.Large" />
</RelativeLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
Ok so I made a quick example of how to do it. This is how the Activity class I'm posting looks like, all items are in the same RecyclerView:
Bear in mind, it might not look like your code because I am trying to use (At least for me) best practices, and also shorten the amount of code and classes by containing a lot of things in the same class.
Here is the Activity:
public class RecyclerActivity extends AppCompatActivity {
RecyclerView recycler;
ArrayList<String> data;
RecyclerView.Adapter<ViewHolder> adapter;
private static final int ITEM_TYPE = 100;
private static final int HEADER_TYPE = 101;
private static final int HEADER_TYPE_2 = 102;
private static final int GRID_TYPE = 103;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler);
// find recycler,
recycler = findViewById(R.id.recycler);
// set the layout
recycler.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
// init data,
data = new ArrayList<>();
data.add("Item A");
data.add("Item B");
data.add("Item C");
// create the adapter
adapter = createAdapter();
// set the adapter
recycler.setAdapter(adapter);
}
// creates the adapter,
private RecyclerView.Adapter<ViewHolder> createAdapter() {
return new RecyclerView.Adapter<ViewHolder>() {
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int type) {
switch (type) {
case HEADER_TYPE:
// inflate the layout,
ViewHolder holderHeader1 = new ViewHolder(inflateHelper(R.layout.header, parent));
// set an on click to the view here to create only one object,
holderHeader1.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// do something
}
});
return holderHeader1;
case HEADER_TYPE_2:
// inflate the layout,
ViewHolder holderHeader2 = new ViewHolder(inflateHelper(R.layout.header, parent));
// set an on click to the view here to create only one object,
holderHeader2.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// do something
}
});
return holderHeader2;
case ITEM_TYPE:
// inflate the layout,
ViewHolder holderItem = new ViewHolder(inflateHelper(R.layout.item, parent));
// set an on click to the view here to create only one object,
holderItem.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// do something
}
});
return holderItem;
case GRID_TYPE:
// inflate the layout,
ViewHolder holderGrid = new ViewHolder(inflateHelper(R.layout.grid, parent));
// set an on click to the view here to create only one object,
holderGrid.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// do something
}
});
return holderGrid;
default:
// inflate the layout,
ViewHolder holderItemDefault = new ViewHolder(inflateHelper(R.layout.item, parent));
// set an on click to the view here to create only one object,
holderItemDefault.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// do something
}
});
return holderItemDefault;
}
}
/**
* Keep the viewholder simple and the all the view finding here. This way you
* only have one viewholder.
*/
#Override
public void onBindViewHolder(#NonNull ViewHolder viewHolder, int position) {
// go through the positions
switch (getItemViewType(position)) {
case HEADER_TYPE:
Button expandButton = viewHolder.itemView.findViewById(R.id.button);
expandButton.setText("Expand");
break;
case HEADER_TYPE_2:
Button collapseButton = viewHolder.itemView.findViewById(R.id.button);
collapseButton.setText("Collapse");
break;
case ITEM_TYPE:
// get the current item
String item = data.get(position - 3);
TextView title = viewHolder.itemView.findViewById(R.id.title);
title.setText(item);
break;
case GRID_TYPE:
break;
}
}
#Override
public int getItemCount() {
return data.size() + 3;
}
#Override
public int getItemViewType(int position) {
switch (position) {
case 0:
return HEADER_TYPE;
case 1:
return HEADER_TYPE_2;
case 2:
return GRID_TYPE;
default: return ITEM_TYPE;
}
}
};
}
private View inflateHelper(int resId, ViewGroup parent) {
return LayoutInflater.from(this).inflate(resId, parent, false);
}
// inner class for viewholder to use,
class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(#NonNull View itemView) {
super(itemView);
}
}
}
You might notice that I have used one ViewHolder. This is a pattern I believe we should adopt because it simplifies code so much more. You can find the views you need in the onBind method and thus get away with using one for all types of views.
Also I add the on click listener in the onCreateViewHolder because it is much more efficient to set it there, and it allows for the viewholder to not be onClick specific.
As I said, you can use as many types as you want, you just need to check for it, and set it at the right position.
Here are the layout files if you are interested:
Header
<?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:padding="4dp"
android:gravity="center">
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Expand" />
</LinearLayout>
Item
<?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:padding="16dp"
android:elevation="2dp"
android:layout_margin="16dp"
android:background="#drawable/rounded">
<TextView
android:id="#+id/title"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="Item A"
android:textColor="#fff"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_chevron_right"
android:tint="#fff"/>
</LinearLayout>
Grid Layout (I cheated a bit here because I didn't see a reason to not hardcode vowels, although you might need to do it dynamically)
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:padding="16dp"
android:background="#drawable/rounded"
android:backgroundTint="#fff"
android:elevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingBottom="16dp"
android:text="French Vowels"
android:textStyle="bold"
style="#style/Base.TextAppearance.AppCompat.Medium"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="#+id/a"
android:layout_width="0dp"
android:layout_weight="1"
android:gravity="center"
android:layout_height="wrap_content"
android:text="a"
style="#style/Base.TextAppearance.AppCompat.Medium"/>
<TextView
android:id="#+id/e"
android:layout_width="0dp"
android:layout_weight="1"
android:gravity="center"
android:layout_height="wrap_content"
android:text="e"
style="#style/Base.TextAppearance.AppCompat.Medium"/>
<TextView
android:id="#+id/i"
android:layout_width="0dp"
android:layout_weight="1"
android:gravity="center"
android:layout_height="wrap_content"
android:text="i"
style="#style/Base.TextAppearance.AppCompat.Medium"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="#+id/o"
android:layout_width="0dp"
android:layout_weight="1"
android:gravity="center"
android:layout_height="wrap_content"
android:text="o"
style="#style/Base.TextAppearance.AppCompat.Medium"/>
<TextView
android:id="#+id/u"
android:layout_width="0dp"
android:layout_weight="1"
android:gravity="center"
android:layout_height="wrap_content"
android:text="u"
style="#style/Base.TextAppearance.AppCompat.Medium"/>
<TextView
android:id="#+id/y"
android:layout_width="0dp"
android:layout_weight="1"
android:gravity="center"
android:layout_height="wrap_content"
android:text="y"
style="#style/Base.TextAppearance.AppCompat.Medium"/>
</LinearLayout>
</LinearLayout>
</FrameLayout>
Rounded Drawable
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#222"/>
<corners android:radius="6dp"/>
</shape>
For anyone reading, if you happen to use Kotlin, consider using my small library which eliminates this recycler view boilerplate to a simple chain of functions:
https://github.com/Pfuster12/BoilerCycle
Hello its been 2 days i am searching for a solution for this and still have no idea how to do, i want make a swipe left and right also rearrange recycle view,When user swipe left it will automatically list in completed list and if swipe on left it will delete list item in recycle view also user can rearrange the list element my long press.
Here is main activity:
public class MainActivity extends AppCompatActivity {
private RecyclerView shoppingItems;
private Toolbar toolbar;
private Realm realm;
private CoordinatorLayout coordinatorLayout;
private List<ShoppingItem> dataSet;
private RecyclerView.Adapter shoppingItemsAdapter = new RecyclerView.Adapter() {
private final int ACTIVE_VIEW=1;
private final int INACTIVE_VIEW=2;
private final int SUBHEADER_VIEW=3;
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType == ACTIVE_VIEW) {
View v = getLayoutInflater().inflate(R.layout.active_item, parent, false);
return new ActiveItemViewHolder(v,
(CheckBox)v.findViewById(R.id.item_status),
(TextView)v.findViewById(R.id.item_name),
(TextView)v.findViewById(R.id.item_quantity),
(ImageView)v.findViewById(R.id.item_action)
);
} else if(viewType == INACTIVE_VIEW) {
View v = getLayoutInflater().inflate(R.layout.inactive_item, parent, false);
return new InactiveItemViewHolder(v,
(CheckBox)v.findViewById(R.id.item_status),
(TextView)v.findViewById(R.id.item_name),
(ImageView)v.findViewById(R.id.item_action)
);
} else {
View v = getLayoutInflater().inflate(R.layout.subheader, parent, false);
return new SubheaderViewHolder(v);
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final ShoppingItem currentItem = dataSet.get(position);
if(currentItem.getTimestamp()==-1) return;
if(currentItem.isCompleted()) {
InactiveItemViewHolder h = (InactiveItemViewHolder)holder;
h.itemName.setText(currentItem.getName());
h.itemName.setPaintFlags(h.itemName.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
h.itemAction.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar snackbar = Snackbar
.make(coordinatorLayout, "Task is restored", Snackbar.LENGTH_LONG);
snackbar.show();
realm.beginTransaction();
currentItem.setCompleted(false);
currentItem.setTimestamp(System.currentTimeMillis());
realm.commitTransaction();
initializeDataSet();
shoppingItemsAdapter.notifyDataSetChanged();
}
});
}else{
ActiveItemViewHolder h = (ActiveItemViewHolder)holder;
h.itemName.setText(currentItem.getName());
h.itemQuantity.setText(currentItem.getQuantity());
h.itemStatus.setChecked(false);
h.itemStatus.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
if (checked) {
realm.beginTransaction();
currentItem.setCompleted(true);
currentItem.setTimestamp(System.currentTimeMillis());
realm.commitTransaction();
initializeDataSet();
shoppingItemsAdapter.notifyDataSetChanged();
Snackbar snackbar = Snackbar
.make(coordinatorLayout, "Task is Completed", Snackbar.LENGTH_LONG)
.setAction("UNDO", new View.OnClickListener() {
#Override
public void onClick(View view) {
realm.beginTransaction();
currentItem.setCompleted(false);
currentItem.setTimestamp(System.currentTimeMillis());
realm.commitTransaction();
initializeDataSet();
shoppingItemsAdapter.notifyDataSetChanged();
Snackbar snackbar1 = Snackbar.make(coordinatorLayout, "Task is restored!", Snackbar.LENGTH_SHORT);
snackbar1.show();
}
});
snackbar.show();
}
}
});
h.itemAction.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(MainActivity.this, ItemActivity.class);
i.putExtra("TITLE", "Edit item");
i.putExtra("ITEM_NAME", currentItem.getName());
i.putExtra("ITEM_QUANTITY", currentItem.getQuantity());
i.putExtra("ITEM_ID", currentItem.getId());
startActivityForResult(i, 1);
}
});
}
}
#Override
public int getItemCount() {
return dataSet.size();
}
#Override
public int getItemViewType(int position) {
ShoppingItem currentItem = dataSet.get(position);
if(currentItem.getTimestamp()==-1) return SUBHEADER_VIEW;
if(currentItem.isCompleted()) return INACTIVE_VIEW;
return ACTIVE_VIEW;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
coordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinatorLayout);
toolbar = (Toolbar) findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
RealmConfiguration configuration =
new RealmConfiguration.Builder(this).build();
Realm.setDefaultConfiguration(configuration);
realm = Realm.getDefaultInstance();
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(MainActivity.this, ItemActivity.class);
i.putExtra("TITLE", "Add Task");
startActivityForResult(i, 1);
}
});
shoppingItems = (RecyclerView)findViewById(R.id.shopping_items);
shoppingItems.setLayoutManager(new LinearLayoutManager(this));
initializeDataSet();
shoppingItems.setAdapter(shoppingItemsAdapter);
}
private void initializeDataSet() {
dataSet = new ArrayList<>();
RealmResults<ShoppingItem> activeItemResults
= realm.where(ShoppingItem.class).equalTo("completed", false)
.findAllSorted("timestamp", Sort.DESCENDING);
RealmResults<ShoppingItem> inactiveItemResults
= realm.where(ShoppingItem.class).equalTo("completed", true)
.findAllSorted("timestamp", Sort.DESCENDING);
ShoppingItem subheader = new ShoppingItem();
subheader.setTimestamp(-1);
for(ShoppingItem item:activeItemResults) dataSet.add(item);
dataSet.add(subheader);
for(ShoppingItem item:inactiveItemResults) dataSet.add(item);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(resultCode == RESULT_OK) {
initializeDataSet();
shoppingItemsAdapter.notifyDataSetChanged();
}
}
activity main.xml
android.support.design.widget.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:id="#+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.github.hathibelagal.shoppinglist.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_main" />
<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:layout_margin="#dimen/fab_margin"
android:src="#drawable/ic_add_24dp"
android:tint="#android:color/white" />
</android.support.design.widget.CoordinatorLayout>
active_item.xml:
RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="72dp">
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/item_status"
android:layout_centerVertical="true"
android:layout_alignParentStart="true" />
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_alignParentStart="true"
android:layout_marginLeft="72dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Medium Text"
android:id="#+id/item_name"
android:textColor="#android:color/black" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Text"
android:id="#+id/item_quantity" />
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/item_action"
android:layout_centerVertical="true"
android:layout_alignParentEnd="true"
android:src="#drawable/ic_create_24dp"
android:alpha="0.26" />
</RelativeLayout>
Please help me! Thanks for advance!
Try this out :
https://medium.com/#ipaulpro/drag-and-swipe-with-recyclerview-b9456d2b1aaf#.lrbbupqkq
Stack Overflow post for the same :
RecyclerView Swipe with a view below it
Drag and drop items in RecyclerView with GridLayoutManager
Ok, so I'm using RecyclerView in my project and need to implement click listener for each list item and an icon in each of the items.
What I tried was this solution: https://stackoverflow.com/a/24933117/722462 cause it looks pretty nice for me. But I couldn't get click listener to react for any click events. Any ideas what is wrong with my implementation? All the files listed below.
fragment_search.xml:
<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="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivityFragment">
<android.support.v7.widget.RecyclerView
android:id="#+id/search_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<LinearLayout
android:id="#+id/search_empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical|center_horizontal"
android:orientation="vertical"
android:visibility="gone">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/icon_search_empty"
android:background="#drawable/ic_info_outline_black_48dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Brak wyników wyszukiwania"
android:id="#+id/text_search_empty" />
</LinearLayout>
</RelativeLayout>
list item:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/item_station_layout"
android:layout_width="match_parent"
android:clickable="true"
android:layout_height="48dp">
<ImageView
android:id="#+id/icon_item_station_fav"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:background="#drawable/ic_favorite_border_blue_24dp"
android:clickable="true"
android:paddingLeft="16dp"
android:tint="#E3F2FD"/>
<TextView
android:id="#+id/item_station_name"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:paddingLeft="58dp"
android:gravity="start|center_vertical"
android:clickable="true"
android:ellipsize="end"
android:maxLines="1"
android:singleLine="true"
android:textSize="16sp" />
</RelativeLayout>
and finaly SearchAdapter.java:
public class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.ViewHolder> {
private List<StationDTO> stations;
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView stationName;
public ImageView favIcon;
private IHasSearchViewHolderCallback hasSearchViewHolderCallback;
public ViewHolder(View itemView, IHasSearchViewHolderCallback hasSearchViewHolderCallback) {
super(itemView);
this.hasSearchViewHolderCallback = hasSearchViewHolderCallback;
favIcon = (ImageView) itemView.findViewById(R.id.icon_item_station_fav);
stationName = (TextView) itemView.findViewById(R.id.item_station_name);
itemView.setOnClickListener(this);
favIcon.setOnClickListener(this);
Context ctx = itemView.getContext().getApplicationContext();
FontHelper.ROBOTO_REGULAR.on(ctx, stationName);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.item_station_layout:
hasSearchViewHolderCallback.onItemLayout(getAdapterPosition());
break;
case R.id.icon_item_station_fav:
hasSearchViewHolderCallback.onFavIcon(getAdapterPosition());
break;
case R.id.item_station_name:
hasSearchViewHolderCallback.onStationName(getAdapterPosition());
break;
}
}
public interface IHasSearchViewHolderCallback {
void onItemLayout(int position);
void onFavIcon(int position);
void onStationName(int position);
}
}
public SearchAdapter(List<StationDTO> stations) {
this.stations = stations;
}
#Override
public SearchAdapter.ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
View item = LayoutInflater
.from(parent.getContext())
.inflate(R.layout.item_station, parent, false);
ViewHolder vh = new ViewHolder(item, new ViewHolder.IHasSearchViewHolderCallback() {
#Override
public void onItemLayout(int position) {
Toast.makeText(parent.getContext(), "LAYOUT #" + position, Toast.LENGTH_SHORT).show();
}
#Override
public void onFavIcon(int position) {
Toast.makeText(parent.getContext(), "FAV #" + position, Toast.LENGTH_SHORT).show();
}
#Override
public void onStationName(int position) {
Toast.makeText(parent.getContext(), "NAME #" + position, Toast.LENGTH_SHORT).show();
}
});
return vh;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
StationDTO dto = stations.get(position);
holder.stationName.setText(dto.getName());
}
#Override
public int getItemCount() {
return stations.size();
}
}
Try changing:
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.item_station_layout:
hasSearchViewHolderCallback.onItemLayout(getAdapterPosition());
break;
case R.id.icon_item_station_fav:
hasSearchViewHolderCallback.onFavIcon(getAdapterPosition());
break;
case R.id.item_station_name:
hasSearchViewHolderCallback.onStationName(getAdapterPosition());
break;
}
}
to
itemView.setOnClickListener(new View.OnClickListener {
#Override
public void onClick(View v) {
// appropriate code in here
}
});
and do the same for favIcon. I have a feeling your problem is arising from the fact that your OnClickListener is on your ViewHolder and not actually on the TextView and ImageView.