I have a recyclerview with multiple layout items populated into it. One for the first item and the other one is for the rest of the list. These are declared into JobListAdapter class. We want to show and hide some few details of the recyclerview using a button in ToolBar activity. How can we achieve this? I have tried an approach where we use a boolean isVisible and we set it to true and false. It is setting the value to true and false according to the click but there is no change in the UI. The UI must be showing and hiding the elements according to the toggle click.
The following is the code of JobListAdapter
public class JobListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int VIEW_JOB = 0;
private static final int VIEW_BREAK = 1;
private static final int VIEW_PREVIEW = 2;
private final int[] mPriorityColours;
private JobClickListener mDragStartListener;
private Context mContext;
private boolean hasPreview;
private long mJobId;
private List<Job> mData;
private ItemDeliverPreviewAdapter adapter;
private ShuffleViewModel viewModel;
private RecyclerView recyclerView;
public boolean isVisible;
public JobListAdapter(Context context, JobClickListener dragStartListener, List<Job> data, int startBreakMinutes) {
viewModel = new ViewModelProvider((RouteActivity) context).get(ShuffleViewModel.class);
mDragStartListener = dragStartListener;
mContext = context;
mData = data;
mPriorityColours = mContext.getResources().getIntArray(R.array.priority);
// check If Last Finished Job has break
if (startBreakMinutes > 0) {
Job breakJob = new Job();
breakJob.id = BREAK_ID;
breakJob.breakMins = startBreakMinutes;
// insert fake break
mData.add(0, breakJob);
}
for (int i = 0; i < mData.size(); i++) {
// add actual breaks
int min = mData.get(i).breakMins;
if (min > 0 && !mData.get(i).isBreak()) {
Job breakJob = new Job();
breakJob.id = BREAK_ID;
breakJob.breakMins = min;
// insert fake break
mData.add(i + 1, breakJob);
i++; // skipp the loop
}
}
}
// Method to update initial visibility state
public void setInitialVisibility(boolean isVisible) {
this.isVisible = isVisible; // Update visibility state for the entire adapter
notifyDataSetChanged(); // Notify adapter to update UI
isVisible = this.isVisible;
Log.d("JobListAdapter", "setInitialVisibilityValue: " + this.isVisible + " " + isVisible);
}
@SuppressLint("WrongConstant")
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, int position2) {
final int position = viewHolder.getAdapterPosition();
final Job job = mData.get(position);
Repo repo = new Repo();
//viewHolder.itemView.findViewById(R.id.site_access_heading).setVisibility(job.isVisible() ? View.VISIBLE : View.GONE);
if (viewHolder instanceof JobViewHolder) {
final JobViewHolder holder = (JobViewHolder) viewHolder;
holder.toggleVisibility(isVisible);
//toggleJobViewHolderVisibility(holder, job.isVisible());
//If job must be completed with the timeslot and eta falls outside the timeslot, below critical flg will be CRITICAL
//Indicating this critical job will be failed
String criticalFlag = job.getCriticalTimeSlotFlag();
if (criticalFlag == "CRITICAL") {
holder.criticalTimeFlag.setVisibility(View.VISIBLE);
} else {
holder.criticalTimeFlag.setVisibility(View.GONE);
}
if (position == 0) {
viewModel.setCurrentBreakCountdownBase(null);
}
setBackground(holder, job, position);
setNewFlag(holder, job);
// PRIORITY
try {
holder.priority.setBackgroundTintList(ColorStateList.valueOf(mPriorityColours[job.getJobPriority()]));
} catch (Exception e) {
FirebaseLogger firebaseLogger = new FirebaseLogger();
firebaseLogger.crashLogger(e, 3333);
FirebaseCrashlytics.getInstance().recordException(e);
e.printStackTrace();
}
holder.priority.setText(String.valueOf(job.getJobPriority()));
holder.bg.setOnClickListener(view -> mDragStartListener.onJobClick(job.getId()));
holder.siteAccess.setText(job.getSiteAccess());
holder.recyclerView.setLayoutManager(new LinearLayoutManager(mContext));
holder.recyclerView.setAdapter(adapter);
holder.updateAdapterData(repo.getJobItems(job.id));
/*// Set visibility of UI components based on job's visibility state
holder.siteAccess.setVisibility(job.isVisible() ? View.VISIBLE : View.GONE);
holder.recyclerView.setVisibility(job.isVisible() ? View.VISIBLE : View.GONE);
holder.siteAccessHeading.setVisibility(job.isVisible() ? View.VISIBLE : View.GONE);
holder.itemsText.setVisibility(job.isVisible() ? View.VISIBLE : View.GONE);*/
holder.name.setText(job.getSiteName());
holder.address.setText(job.getAddress());
holder.eta.setText(job.getFormattedEta());
holder.postcode.setText(job.getPostcode());
holder.slotNumber.setText(String.valueOf(position + 1));
holder.slotNumber.setEnabled(false);
holder.timesFromTo.setText(job.getTimeSlot(mContext));
holder.timesFromTo.setBackgroundColor(job.getEtaColor(mContext));
holder.dragHandle.setVisibility(View.GONE);
} else if (viewHolder instanceof BreakViewHolder) { // view is a break
final BreakViewHolder holder = (BreakViewHolder) viewHolder;
if (position != 0) { // cant change upcoming break as it's referenced in a finished job
holder.startBtn.setVisibility(View.GONE);
holder.endBtn.setVisibility(View.GONE);
holder.chronometer.setVisibility(View.GONE);
holder.dragHandle.setVisibility(View.VISIBLE);
} else {
holder.bg.setOnLongClickListener(null); // no longer possible to delete
if (viewModel.getCurrentBreakCountdownBase() != null) {
holder.chronometer.setBase(viewModel.getCurrentBreakCountdownBase());
holder.chronometer.start();
holder.endBtn.setVisibility(View.VISIBLE);
holder.startBtn.setVisibility(View.GONE);
} else {
holder.startBtn.setVisibility(View.VISIBLE);
holder.endBtn.setVisibility(View.GONE);
}
holder.chronometer.setVisibility(View.VISIBLE);
holder.dragHandle.setVisibility(View.GONE);
}
holder.index.setText(String.valueOf(position + 1));
holder.mins.setText(String.format(mContext.getString(R.string.mins), job.getBreakMins()));
holder.startBtn.setOnClickListener(v -> {
if (position < mData.size()) {
mDragStartListener.onBreakStart(mData.get(position).breakMins);
// preserve break on rotation
long base = SystemClock.elapsedRealtime();
viewModel.setCurrentBreakCountdownBase(base);
holder.chronometer.setBase(base);
holder.chronometer.start();
holder.startBtn.setVisibility(View.GONE);
holder.endBtn.setVisibility(View.VISIBLE);
}
});
holder.endBtn.setOnClickListener(v -> {
new Repo().finishBreak();
// stop chronometer
holder.chronometer.stop();
holder.chronometer.setText("00:00");
// get next job index
// remove break
mData.remove(position);
notifyItemRemoved(position);
// starts new job
mDragStartListener.onBreakFinished(getFirstJobId());
notifyDataSetChanged();
});
holder.dragHandle.setVisibility(View.GONE);
} else { // preview
final JobPreview preview = (JobPreview) viewHolder;
preview.toggleVisibility(isVisible);
//toggleJobPreviewVisibility(preview, isVisible);
preview.bg.setOnClickListener(v -> mDragStartListener.onJobClick(job.id));
preview.address.setText(job.getAddress());
preview.name.setText(job.getSiteName());
preview.eta.setText(job.getFormattedEta());
preview.bg.setBackgroundColor(job.getEtaColor(mContext));
preview.priority.setText(String.valueOf(job.getJobPriority()));
preview.time.setText(job.getLandscapeTimeSlot(mContext));
preview.callIcon.setVisibility(job.hasCallAhead() ? View.VISIBLE : View.GONE);
preview.postcode.setText(job.getPostcode());
preview.siteAccess.setText(job.getSiteAccess());
preview.recyclerView.setLayoutManager(new LinearLayoutManager(mContext));
preview.recyclerView.setAdapter(adapter);
/* // Set visibility of UI components based on job's visibility state
preview.siteAccess.setVisibility(job.isVisible() ? View.VISIBLE : View.GONE);
preview.recyclerView.setVisibility(job.isVisible() ? View.VISIBLE : View.GONE);
preview.siteAccessHeading.setVisibility(job.isVisible() ? View.VISIBLE : View.GONE);
preview.itemsText.setVisibility(job.isVisible() ? View.VISIBLE : View.GONE);*/
preview.updateAdapterData(repo.getJobItems(job.id));
String criticalFlag = job.getCriticalTimeSlotFlag();
if (criticalFlag == "CRITICAL") {
preview.criticalTimeFlag.setVisibility(View.VISIBLE);
} else {
preview.criticalTimeFlag.setVisibility(View.GONE);
}
}
}
private void setBackground(JobViewHolder holder, Job job, int position) {
if (job.isNew < 0) {
holder.bg.setBackgroundColor(ContextCompat.getColor(mContext, R.color.directions_drawable_green));
} else {
if (position % 2 == 0) {
holder.bg.setBackgroundColor(ContextCompat.getColor(mContext, R.color.grey_dark));
} else {
holder.bg.setBackgroundColor(ContextCompat.getColor(mContext, R.color.grey_light));
}
}
}
private void setNewFlag(JobViewHolder holder, Job job) {
String flagText = job.getNewFlag();
if (flagText != null) {
holder.newFlag.setVisibility(View.VISIBLE);
holder.newFlag.setOnClickListener(view -> {
Balloon balloon = new Balloon.Builder(mContext)
.setArrowSize(9)
.setArrowOrientation(ArrowOrientation.BOTTOM)
.setArrowConstraints(ArrowConstraints.ALIGN_ANCHOR)
.setArrowPosition(0.5f)
.setArrowVisible(true)
.setPadding(6)
.setTextSize(14f)
.setCornerRadius(4f)
.setAlpha(1f)
.setText(flagText + " job")
.setAutoDismissDuration(1500L)
.setTextColor(ContextCompat.getColor(mContext, R.color.black))
.setTextIsHtml(true)
.setIconDrawable(ContextCompat.getDrawable(mContext, R.drawable.vector_alert))
.setBackgroundColor(ContextCompat.getColor(mContext, R.color.reg_yellow))
.setBalloonAnimation(BalloonAnimation.FADE)
.build();
balloon.showAlignTop(view, 0, dpToPx(2));
});
} else {
holder.newFlag.setVisibility(View.GONE);
}
}
public List<Job> getJobsToSkip() {
List<Job> jobsToSkip = new ArrayList<>();
for (Job j : mData) {
if (!j.isBreak()) {
jobsToSkip.add(j);
}
}
// remove all breaks
for (int i = 0; i < mData.size(); i++) {
if (mData.get(i).isBreak()) mData.remove(i);
}
notifyDataSetChanged();
return jobsToSkip;
}
@Override
public int getItemCount() {
return mData.size();
}
@Override
public int getItemViewType(int position) {
if (position == 0 && mData.get(0).getId() != BREAK_ID) return VIEW_PREVIEW;
return mData.get(position).getId() == BREAK_ID ? VIEW_BREAK : VIEW_JOB;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_JOB) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_job, parent, false);
return new JobViewHolder(view);
} else if (viewType == VIEW_BREAK) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_break, parent, false);
return new BreakViewHolder(view);
} else { // JOB_PREVIEW
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_job_preview, parent, false);
//adapter = new ItemDeliverPreviewAdapter(mContext, jobItemData);
return new JobPreview(view);
}
}
public long getFirstJobId() {
//int nonBreakIndex = getNextNonBreakJob(-1);
return mData.isEmpty() ? -1 : mData.get(0).getId();
//return mData.isEmpty() || nonBreakIndex == -1 ? -1 : mData.get(nonBreakIndex).getId();
}
/**
* @return next job id or -1 if non found
*/
public long completeJob() {
mData.remove(0);
notifyItemRemoved(0);
notifyDataSetChanged();
if (mData.isEmpty()) {
return -1;
} else {
return mData.get(0).getId();
}
}
public void failJob(long id) {
for (int i = 0; i < mData.size(); i++) {
if (mData.get(i).getId() == id) {
mData.remove(i);
notifyItemRemoved(i);
return;
}
}
notifyDataSetChanged();
}
private int hasJob(long jobId) {
for (int i = 0; i < mData.size(); i++) {
if (mData.get(i).getId() == jobId) return i;
}
return -1;
}
public void addNewJob(Job j) {
int position = hasJob(j.getId());
if (position == -1) {
// add new job
position = mData.isEmpty() ? 0 : 1;
mData.add(position, j);
notifyItemInserted(position);
} else {
// amend existing job
mData.remove(position);
mData.add(position, j);
notifyItemChanged(position);
}
}
public void cancelJob(long jobId) {
for (int i = 0; i < mData.size(); i++) {
if (mData.get(i).id == jobId) {
mData.remove(i);
notifyItemRemoved(i);
}
}
}
public void updateEta(List<Job> jobs) {
for (int i = 0; i < mData.size(); i++) {
if (mData.get(i).isBreak()) {
//leave breaks alone
} else {
if (i < jobs.size()) { // just in case...
for (int j = 0; j < jobs.size(); j++) {
if (mData.get(i).getId() == jobs.get(j).getId()) {
// replace eta
mData.remove(i);
mData.add(i, jobs.get(j));
notifyItemChanged(i);
}
}
}
}
}
// remove nexts
}
private int dpToPx(float dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, mContext.getResources().getDisplayMetrics());
}
public List<Job> getJobs() {
return mData;
}
public void failAllJobs() {
List<Job> list = new ArrayList<>();
for (int i = 0; i < mData.size(); i++) { // final disposal cannot be skipped
if (mData.get(i).isFinalDisposal()) list.add(mData.get(i));
}
mData = list;
notifyDataSetChanged();
}
// Add a method to set the RecyclerView reference
public void setRecyclerView(RecyclerView recyclerView) {
this.recyclerView = recyclerView;
}
/* public void toggleFieldsVisibility(boolean isVisible) {
// Update the visibility state for all items in the dataset
for (Job job : mData) {
job.setVisible(isVisible);
}
// Notify the adapter that the dataset has changed
notifyDataSetChanged();
if (recyclerView != null) {
recyclerView.invalidate();
} else {
Log.e("JobListAdapter", "RecyclerView is null");
}
}*/
private void toggleJobViewHolderVisibility(JobViewHolder holder, boolean isVisible) {
//this.isVisible = isVisible;
Job job = new Job();
Log.d("toggleJobViewHolderVisibility", "JobViewHolder: " + isVisible);
int visibility = job.isVisible() ? View.GONE : View.VISIBLE; // Toggle visibility
holder.siteAccess.setVisibility(visibility);
holder.recyclerView.setVisibility(visibility);
holder.siteAccessHeading.setVisibility(visibility);
holder.itemsText.setVisibility(visibility);
}
private void toggleJobPreviewVisibility(JobPreview preview, boolean isVisible) {
Job job = new Job();
//this.isVisible = isVisible;
Log.d("toggleJobPreviewVisibility", "JobPreview: " + isVisible);
int visibility = job.isVisible() ? View.GONE : View.VISIBLE; // Toggle visibility
preview.siteAccess.setVisibility(visibility);
preview.recyclerView.setVisibility(visibility);
preview.siteAccessHeading.setVisibility(visibility);
preview.itemsText.setVisibility(visibility);
}
private void transitionVisibility(View view, boolean isVisible) {
if (view != null) {
if (isVisible && view.getVisibility() != View.VISIBLE) {
// Show the view with transition effect
TransitionManager.beginDelayedTransition((ViewGroup) view.getParent(), new AutoTransition());
view.setVisibility(View.VISIBLE);
} else if (!isVisible && view.getVisibility() == View.VISIBLE) {
// Hide the view with transition effect
TransitionManager.beginDelayedTransition((ViewGroup) view.getParent(), new AutoTransition());
view.setVisibility(View.GONE);
}
}
}
/**
* Simple example of a view holder that implements {@link ItemTouchHelperViewHolder} and has a
* "handle" view that initiates a drag event when touched.
*/
private class JobViewHolder extends RecyclerView.ViewHolder implements
ItemTouchHelperViewHolder {
public final View bg;
final TextView priority, name, address, timesFromTo, postcode, eta, siteAccess, siteAccessHeading, itemsText;
final ImageView newFlag, criticalTimeFlag;
final EditText slotNumber;
final View dragHandle;
final RecyclerView recyclerView;
JobViewHolder(View itemView) {
super(itemView);
Repo repo = new Repo();
bg = itemView.findViewById(R.id.item_bg);
newFlag = itemView.findViewById(R.id.new_flag);
criticalTimeFlag = itemView.findViewById(R.id.critical_time_flag);
priority = itemView.findViewById(R.id.job_item_priority);
slotNumber = itemView.findViewById(R.id.job_item_slot);
eta = itemView.findViewById(R.id.job_item_eta);
name = itemView.findViewById(R.id.job_item_name);
address = itemView.findViewById(R.id.job_item_address);
timesFromTo = itemView.findViewById(R.id.time_from_to);
postcode = itemView.findViewById(R.id.job_item_postcode);
dragHandle = itemView.findViewById(R.id.drag);
siteAccess = itemView.findViewById(R.id.site_access_detail);
siteAccessHeading = itemView.findViewById(R.id.site_access_heading);
itemsText = itemView.findViewById(R.id.items_heading);
recyclerView = itemView.findViewById(R.id.job_preview_items_recycler);
// jobType = itemView.findViewById(R.id.job_type);
adapter = new ItemDeliverPreviewAdapter(mContext, repo.getJobItems(mJobId));
recyclerView.setAdapter(adapter);
}
void toggleVisibility(boolean isVisible) {
int visibility = isVisible ? View.GONE : View.VISIBLE;
// Update visibility of UI components based on visibility state
siteAccess.setVisibility(visibility);
recyclerView.setVisibility(visibility);
siteAccessHeading.setVisibility(visibility);
itemsText.setVisibility(visibility);
}
// Method to update adapter data
public void updateAdapterData(List<JobItem> jobItems) {
adapter.jobItemData = jobItems;
}
@Override
public void onItemSelected() {
}
@Override
public void onItemClear() {
}
}
private class BreakViewHolder extends RecyclerView.ViewHolder {
final Button startBtn, endBtn;
final Chronometer chronometer;
final View dragHandle, bg;
final TextView index, mins;
BreakViewHolder(View v) {
super(v);
bg = v.findViewById(R.id.item_bg);
mins = v.findViewById(R.id.item_break_mins);
index = v.findViewById(R.id.item_break_index);
startBtn = v.findViewById(R.id.item_break_start_btn);
endBtn = v.findViewById(R.id.item_break_end_btn);
chronometer = v.findViewById(R.id.item_break_chronometer);
dragHandle = v.findViewById(R.id.item_break_drag);
}
}
private class JobPreview extends RecyclerView.ViewHolder {
View bg;
TextView address;
TextView postcode;
View callIcon;
TextView eta;
TextView name;
TextView time;
TextView priority;
ImageView criticalTimeFlag;
TextView siteAccess;
TextView siteAccessHeading;
TextView itemsText;
RecyclerView recyclerView;
private long mJobId;
JobPreview(@NonNull View itemView) {
super(itemView);
Repo repo = new Repo();
bg = itemView;
address = itemView.findViewById(R.id.preview_address);
eta = itemView.findViewById(R.id.preview_eta);
name = itemView.findViewById(R.id.preview_name);
time = itemView.findViewById(R.id.preview_time);
priority = itemView.findViewById(R.id.preview_priority);
callIcon = itemView.findViewById(R.id.preview_call_icon);
postcode = itemView.findViewById(R.id.preview_postcode);
criticalTimeFlag = itemView.findViewById(R.id.critical_time_flag);
// jobType = itemView.findViewById(R.id.job_type);
siteAccessHeading = itemView.findViewById(R.id.site_access_heading);
siteAccess = itemView.findViewById(R.id.site_access_detail);
itemsText = itemView.findViewById(R.id.items_heading);
recyclerView = itemView.findViewById(R.id.job_preview_items_recycler);
adapter = new ItemDeliverPreviewAdapter(mContext, repo.getJobItems(mJobId));
recyclerView.setAdapter(adapter);
}
void toggleVisibility(boolean isVisible) {
int visibility = isVisible ? View.GONE : View.VISIBLE;
// Update visibility of UI components based on visibility state
siteAccess.setVisibility(visibility);
recyclerView.setVisibility(visibility);
siteAccessHeading.setVisibility(visibility);
itemsText.setVisibility(visibility);
}
public void updateAdapterData(List<JobItem> jobItems) {
adapter.jobItemData = jobItems;
}
}
}
And the following is the code of ToolBarActivity
public abstract class ToolbarActivity extends AppCompatActivity implements JobClickListener {
protected Toolbar toolbar;
protected TextView mTotalJobsText, mCompletedJobsText, mSkippedJobText, mNotificationText, mExpandCollapseText;
private boolean isVisible;
private JobListAdapter mAdapter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void onResume() {
super.onResume();
updateToolbar();
}
protected void initToolbarView() {
final Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mTotalJobsText = findViewById(R.id.info_total);
mSkippedJobText = findViewById(R.id.info_skipped);
mCompletedJobsText = findViewById(R.id.info_completed);
mNotificationText = findViewById(R.id.info_notification);
Job job = new Job();
RecyclerView recyclerView = findViewById(R.id.route_plan_recycler);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
// Pass the initial visibility state to the adapter
mAdapter = new JobListAdapter(this, this, new ArrayList<>(), 0);
mAdapter.setRecyclerView(recyclerView);
recyclerView.setAdapter(mAdapter);
mExpandCollapseText = findViewById(R.id.expand_collapse_button);
mExpandCollapseText.setOnClickListener(v -> {
Log.d("ToolbarActivity", "Expand/Collapse text clicked");
isVisible = !isVisible;
Log.d("ToolbarActivity", "isVisible: " + isVisible);
if (mAdapter != null) {
mAdapter.setInitialVisibility(isVisible);
Log.d("ToolbarActivity", "SetInitialVisibilityInToolbar: " + isVisible);// Update adapter's visibility state
} else {
Log.e("ToolbarActivity", "Adapter is null");
}
});
findViewById(R.id.info_history).setOnClickListener(v -> NavigationUtil.startIntent(ToolbarActivity.this, new Intent(ToolbarActivity.this, JobHistoryActivity.class)));
}
I have tried to log at certain places. The logs were returning expected results but it was not reflecting on the UI Here is the log Expand/Collapse text clicked isVisible: false setInitialVisibilityValue: false false SetInitialVisibilityInToolbar: false Expand/Collapse text clicked isVisible: true setInitialVisibilityValue: true true SetInitialVisibilityInToolbar: true