Alezis
Alezis

Reputation: 1212

RecyclerView issue with scrollToPosition

I have a fragment with a calendar and a spinner to filter data.

Under the calendar there is a recyclerview that shows notifications in the calendar.

I show all the notifications from the current month and I scroll the recyclerview to today notifications, and the top item shown is the first of today.

The spinner filter by notification type. (All, generic, task, exam, absence)

Works properly but when I select whatever and again select ALL, the recyclerview scrolls to the position I set with rvNotifications.scrollToPosition(index) but the item is in the bottom of the shown items, not in the top.

Could anyone help me?

public class CalendarFragment extends Fragment implements NotificationsAdapter.ListItemClickListener {

    private ArrayList<String> types;

    private ArrayList<SchoolNotification> notifications = new ArrayList();
    private ArrayList<SchoolNotification> notifications_month = new ArrayList();
    private ArrayList<SchoolNotification> notifications_generic = new ArrayList();
    private ArrayList<SchoolNotification> notifications_task = new ArrayList();
    private ArrayList<SchoolNotification> notifications_exam = new ArrayList();
    private ArrayList<SchoolNotification> notifications_absence = new ArrayList();
    private ArrayList<SchoolNotification> notifications_shown = new ArrayList();

    private List<CalendarDay> generic_events_list = new ArrayList();
    private List<CalendarDay> task_events_list = new ArrayList();
    private List<CalendarDay> exam_events_list = new ArrayList();
    private List<CalendarDay> absence_events_list = new ArrayList();

    private Spinner sp_types;
    private NotificationsAdapter mAdapter;
    private RecyclerView rvNotifications;
    private MaterialCalendarView calendar_mv;

    private CalendarDay selectedDate;

    private Integer index = 0;
    private Integer indexOrigin = 0;
    private Integer indexGeneric = 0;
    private Integer indexTask = 0;
    private Integer indexExam = 0;
    private Integer indexAbsence = 0;


    public static CalendarFragment newInstance() {
        CalendarFragment fragment = new CalendarFragment();
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        notifications = getArguments().getParcelableArrayList("notifications");

        View view = inflater.inflate(R.layout.fragment_calendar, container, false);

        view = initialize(view);

        return view;
    }

    private View initialize(View view) {

        rvNotifications = (RecyclerView) view.findViewById(R.id.rv_notifications);
        LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
        rvNotifications.setLayoutManager(layoutManager);
        rvNotifications.setHasFixedSize(true);

        calendar_mv = (MaterialCalendarView) view.findViewById(R.id.calendar_view);
        sp_types = (Spinner) view.findViewById(R.id.sp_event_type);
        types = new ArrayList<>(Arrays.asList(getActivity().getResources().getString(R.string.all_events),
                getActivity().getResources().getString(R.string.generic), getActivity().getResources().getString(R.string.task),
                getActivity().getResources().getString(R.string.exam), getActivity().getResources().getString(R.string.abscence)));


        NotificationsSelectedMonth();

        classifyNotifications();

        mAdapter = new NotificationsAdapter(notifications_shown, getResources(), CalendarFragment.this);
        rvNotifications.setAdapter(mAdapter);
        rvNotifications.scrollToPosition(index);

        indexOrigin = index;

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), R.layout.spinner_item, types);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        sp_types.setAdapter(adapter);

        List<CalendarDay> today = new ArrayList<>();
        Calendar today_cal = Calendar.getInstance();
        today_cal.set(Calendar.HOUR_OF_DAY, 0);
        CalendarDay calendarDay = CalendarDay.from(today_cal);
        today.add(calendarDay);

        calendar_mv.addDecorator(new DateDecorator(getActivity(), getColor(getActivity(), R.color.primary_darker), generic_events_list));
        calendar_mv.addDecorator(new DateDecorator(getActivity(), getColor(getActivity(), R.color.green), task_events_list));
        calendar_mv.addDecorator(new DateDecorator(getActivity(), getColor(getActivity(), R.color.red), exam_events_list));
        calendar_mv.addDecorator(new DateDecorator(getActivity(), getColor(getActivity(), R.color.black), absence_events_list));

        setListeners();

        return view;
    }

    private void setListeners() {

        sp_types.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
                calendar_mv.removeDecorators();

                List<CalendarDay> today = new ArrayList<>();
                Calendar today_cal = Calendar.getInstance();
                today_cal.set(Calendar.HOUR_OF_DAY, 0);
                CalendarDay calendarDay = CalendarDay.from(today_cal);
                today.add(calendarDay);

                calendar_mv.addDecorator(new DateDecorator(getActivity(), today, true));
                switch (position) {
                    case 0:
                        calendar_mv.addDecorator(new DateDecorator(getActivity(), getColor(getActivity(), R.color.primary_darker), generic_events_list));
                        calendar_mv.addDecorator(new DateDecorator(getActivity(), getColor(getActivity(), R.color.green), task_events_list));
                        calendar_mv.addDecorator(new DateDecorator(getActivity(), getColor(getActivity(), R.color.red), exam_events_list));
                        calendar_mv.addDecorator(new DateDecorator(getActivity(), getColor(getActivity(), R.color.black), absence_events_list));
                        mAdapter = new NotificationsAdapter(notifications_shown, getResources(), CalendarFragment.this);
                        rvNotifications.swapAdapter(mAdapter, false);
                        rvNotifications.scrollToPosition(index);
                        break;
                    case 1:
                        calendar_mv.addDecorator(new DateDecorator(getActivity(), getColor(getActivity(), R.color.primary_darker), generic_events_list));
                        mAdapter = new NotificationsAdapter(notifications_generic, getResources(), CalendarFragment.this);
                        rvNotifications.swapAdapter(mAdapter, false);
                        rvNotifications.scrollToPosition(indexGeneric);
                        break;
                    case 2:
                        calendar_mv.addDecorator(new DateDecorator(getActivity(), getColor(getActivity(), R.color.green), task_events_list));
                        mAdapter = new NotificationsAdapter(notifications_task, getResources(), CalendarFragment.this);
                        rvNotifications.swapAdapter(mAdapter, false);
                        rvNotifications.scrollToPosition(indexTask);
                        break;
                    case 3:
                        calendar_mv.addDecorator(new DateDecorator(getActivity(), getColor(getActivity(), R.color.red), exam_events_list));
                        mAdapter = new NotificationsAdapter(notifications_exam, getResources(), CalendarFragment.this);
                        rvNotifications.setAdapter(mAdapter);
                        rvNotifications.scrollToPosition(indexExam);
                        break;
                    case 4:
                        calendar_mv.addDecorator(new DateDecorator(getActivity(), getColor(getActivity(), R.color.black), absence_events_list));
                        mAdapter = new NotificationsAdapter(notifications_absence, getResources(), CalendarFragment.this);
                        rvNotifications.swapAdapter(mAdapter, false);
                        rvNotifications.scrollToPosition(indexAbsence);
                        break;
                }

            }

            @Override
            public void onNothingSelected(AdapterView<?> parentView) {
            }

        });

    @Override
    public void onListItemClick(SchoolNotification notification) {

        NotificationDetailFragment detailFragment = NotificationDetailFragment.newInstance();
        Bundle bundle = new Bundle();
        bundle.putParcelable("notification", notification);
        detailFragment.setArguments(bundle);

        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.frame_layout, detailFragment);
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();
    }

    private void NotificationsSelectedMonth() {
        SchoolNotification notif;
        Date notif_date;
        Calendar cal = Calendar.getInstance();
        notifications_month = new ArrayList<>();
        for (int i = 0; i < notifications.size(); i++) {
            notif = notifications.get(i);

            notif_date = notif.getDate();
            cal.setTime(notif_date);

            if (((Integer) cal.get(Calendar.MONTH)) == calendar_mv.getCurrentDate().getMonth()) {
                notifications_month.add(notif);
            }
        }
    }

    private void classifyNotifications() {

        initializeCalendarsDays();
        initializeNotificationCollections();

        Calendar calendar = Calendar.getInstance();
        Calendar cal = Calendar.getInstance();
        CalendarDay calendarDay;

        SchoolNotification notif;
        Date notif_date;

        Calendar auxcal = Calendar.getInstance();
        auxcal.add(Calendar.DATE, + 1);
        Date tomorrow = cal.getTime();

        Boolean setIndex = false;
        Boolean setIndexG = false;
        Boolean setIndexT = false;
        Boolean setIndexE = false;
        Boolean setIndexA = false;


        for (int i = 0; i < notifications_month.size(); i++) {
            notif = notifications_month.get(i);

            notif_date = notif.getDate();

            if (notif_date.before(tomorrow) && !setIndex) {
                index = i;
                setIndex = true;
            }

            cal.setTime(notif_date);
            calendar.set(cal.get(Calendar.YEAR),
                    cal.get(Calendar.MONTH), //months starts from 0
                    cal.get(Calendar.DAY_OF_MONTH));
            calendarDay = CalendarDay.from(calendar);

            if (selectedDate == null || (selectedDate.getYear() == calendarDay.getYear() &&
                    selectedDate.getMonth() == calendarDay.getMonth() &&
                    selectedDate.getDay() == calendarDay.getDay())) {
                notifications_shown.add(notif);
            }

            switch (notif.getType()) {
                case StaticConfiguration.GENERIC:
//                    if (maxDayGeneric.compareTo(dayToday) > 0 || dayToday.compareTo(notif_date) > 0) {
//                        indexGeneric = notifications_generic.size();
//                    }
                    if (notif_date.before(tomorrow) && !setIndexG) {
                        indexGeneric = notifications_generic.size();
                        setIndexG = true;
                    }
                    generic_events_list.add(calendarDay);
                    if (selectedDate == null || (selectedDate.getYear() == calendarDay.getYear() &&
                            selectedDate.getMonth() == calendarDay.getMonth() &&
                            selectedDate.getDay() == calendarDay.getDay())) {
                        notifications_generic.add(notif);
                    }
                    break;
                case StaticConfiguration.TASK:
//                    if (maxDayTask.compareTo(dayToday) > 0 || dayToday.compareTo(notif_date) > 0) {
//                        indexTask = notifications_task.size();
//                    }
                    if (notif_date.before(tomorrow) && !setIndexT) {
                        indexTask = notifications_task.size();
                        setIndexT = true;
                    }
                    task_events_list.add(calendarDay);
                    if (selectedDate == null || (selectedDate.getYear() == calendarDay.getYear() &&
                            selectedDate.getMonth() == calendarDay.getMonth() &&
                            selectedDate.getDay() == calendarDay.getDay())) {
                        notifications_task.add(notif);
                    }
                    break;
                case StaticConfiguration.EXAM:
//                    if (maxDayExam.compareTo(dayToday) > 0 || dayToday.compareTo(notif_date) > 0) {
//                        indexExam = notifications_exam.size();
//                    }
                    if (notif_date.before(tomorrow) && !setIndexE) {
                        indexExam = notifications_exam.size();
                        setIndexE = true;
                    }
                    exam_events_list.add(calendarDay);
                    if (selectedDate == null || (selectedDate.getYear() == calendarDay.getYear() &&
                            selectedDate.getMonth() == calendarDay.getMonth() &&
                            selectedDate.getDay() == calendarDay.getDay())) {
                        notifications_exam.add(notif);
                    }
                    break;
                case StaticConfiguration.ABSENCE:
//                    if (maxDayAbsence.compareTo(dayToday) > 0 || dayToday.compareTo(notif_date) > 0) {
//                        indexAbsence = notifications_absence.size();
//                    }
                    if (notif_date.before(tomorrow) && !setIndexA) {
                        indexAbsence = notifications_absence.size();
                        setIndexA = true;
                    }
                    absence_events_list.add(calendarDay);
                    if (selectedDate == null || (selectedDate.getYear() == calendarDay.getYear() &&
                            selectedDate.getMonth() == calendarDay.getMonth() &&
                            selectedDate.getDay() == calendarDay.getDay())) {
                        notifications_absence.add(notif);
                    }
                    break;
            }
        }
        calendar_mv.addDecorator(new DateDecorator(getActivity(), getColor(getActivity(), R.color.primary_darker), generic_events_list));
        calendar_mv.addDecorator(new DateDecorator(getActivity(), getColor(getActivity(), R.color.green), task_events_list));
        calendar_mv.addDecorator(new DateDecorator(getActivity(), getColor(getActivity(), R.color.red), exam_events_list));
        calendar_mv.addDecorator(new DateDecorator(getActivity(), getColor(getActivity(), R.color.black), absence_events_list));
    }

    private void initializeCalendarsDays() {
        generic_events_list.clear();
        task_events_list.clear();
        exam_events_list.clear();
        absence_events_list.clear();
    }

    private void initializeNotificationCollections() {
        notifications_shown.clear();
        notifications_generic.clear();
        notifications_task.clear();
        notifications_exam.clear();
        notifications_absence.clear();
    }
}

Upvotes: 1

Views: 781

Answers (2)

Xenolion
Xenolion

Reputation: 12717

You should set an offset so for your recycler view like:

layoutManager.scrollToPositionWithOffset(index, 0);

Upvotes: 1

Alezis
Alezis

Reputation: 1212

with

rvNotifications.setAdapter(mAdapter);

instead of

rvNotifications.swapAdapter(mAdapter, false);

it works. But I dont know if it is a valid answer

Upvotes: 0

Related Questions