1

I'm currently new to android development and I'm in the process of building my first app. I'm stuck on a particular tricky bit in which I'm trying to implement and Endless Recycler View.

I'm using a recycler view (currently) just to get the current dates and display them in a calendar output. There is two things that are really holding me up. One there is not much documentation out there on using an endless recycler view without a database (I do plan to but again not right now), and not knowing where/how to make it endless. The recyclerView I have Implemented is already working I just need it to load endlessly. The only examples I could find essentially required me to be using a database, or were to create one gigantic method in the onCreate method. Again I have also tried to implement my own setOnScrollListener inside the home class but alas I couldn't get it working.

Below are the desired results that I've got pictured in my head. Link to UI picture

Here is my code so far. Ideally I would like to keep the on scroll Listener in the RecyclerAdapter as I will probably reuse it later on in other aspects of the app. Thank you in advanced.

HOME CLASS

public class Home extends AppCompatActivity implements AdapterView.OnItemSelectedListener {

private static final String TAG = "Home Class" ;

//Recycler View Variables and myCalendarClass Variables
private myCalendarClass myCalendarObj;
private int weeksInView = 1; //will need to make this update dynamicallly based on when a user toggles the view
private ArrayList<Calendar> calendarArrayList = new ArrayList<>();
private ArrayList<Integer> iconList = new ArrayList<>();
private ArrayList<Integer> eventCounterList = new ArrayList<>();

//recycler view dynamic loading variables
private RecyclerView calendarRecyclerView;
private boolean isLoading = true;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_home);

    initializeNavMenuButtons();
    setViewSpinner();

    this.myCalendarObj = new myCalendarClass();
    setAllCalendarFields(this.myCalendarObj);

    getImagesAndEventCounters();

    //Example of the order to call the methods when a user switches the view
        //setCalendarItrToCurrentSunday();
        //setCalendarArrayList();
        //getImagesAndEventCounters();
}

        //Recycler view code

//gets images and events to feed into the recycler view
private void getImagesAndEventCounters() {
    Log.d(TAG, "initImageBitMaps: called");

    ArrayList<Calendar> weekView = getCalendarArrayList();

    int daysInView = this.weeksInView * 7;

    System.out.println("Days in view " + daysInView + " Weeks In View " + this.weeksInView);

    for (int i = 0; i < daysInView; i++) {

        calendarArrayList.add(weekView.get(i));

        iconList.add(R.id.fitnessIcon);
        eventCounterList.add(R.string.XEventsDefault);

        iconList.add(R.id.educationIcon);
        eventCounterList.add(R.string.XEventsDefault);

        iconList.add(R.id.workIcon);
        eventCounterList.add(R.string.XEventsDefault);

        iconList.add(R.id.personalIcon);
        eventCounterList.add(R.string.XEventsDefault);

        initRecyclerView();
    }


}

//passes data to the parent recycler view and sets the view
private void initRecyclerView() {

         //For one recyclerView
            this.parentLayoutManager = new GridLayoutManager(this, 7);
            //GridLayoutManager layoutManager =  parentLayoutManager;
            RecyclerView recyclerView = findViewById(R.id.calendarRecyclerView);
            recyclerView.setLayoutManager(parentLayoutManager);
            RecyclerViewAdapter adapter = new RecyclerViewAdapter(this,iconList,eventCounterList,weeksInView,calendarArrayList);
            recyclerView.setAdapter(adapter);

    //ViewSpinner(Drop Down Menu)
private void setViewSpinner(){
    Spinner viewSpinner = findViewById(R.id.ViewDropDownButton);
    ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,R.array.Calendar_View_List, android.R.layout.simple_spinner_item);

    viewSpinner.setAdapter(adapter);
    viewSpinner.setOnItemSelectedListener(this);

}

@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
    String text = parent.getItemAtPosition(position).toString();

    myCalendarClass myCalendarObj;

    if(text.equals("Week View")){
        myCalendarObj = new myCalendarClass("Week View");
        setAllCalendarFields(myCalendarObj);
        getImagesAndEventCounters();
        this.myCalendarObj = myCalendarObj;
    }
    else if (text.equals("Biweekly View")){
        myCalendarObj = new myCalendarClass("Biweekly View");
        setAllCalendarFields(myCalendarObj);
        getImagesAndEventCounters();
        this.myCalendarObj = myCalendarObj;
    }
    else if (text.equals("Month View")){
        myCalendarObj = new myCalendarClass("Month View");
        setAllCalendarFields(myCalendarObj);
        getImagesAndEventCounters();
        this.myCalendarObj = myCalendarObj;
    }


    }

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

}


  //setters
//sets all the local variables needed from myCalendarClass
private void setAllCalendarFields(myCalendarClass c){
    this.myCalendarObj = c;
    this.calendarArrayList = c.getCalendarArrayList();
    this.weeksInView = c.getWeeksInView();
}

//getters
//returns the calendar arraylist
private ArrayList<Calendar> getCalendarArrayList(){
    return this.calendarArrayList;
}

RECYCLER ADAPTER

    public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {

    private static final String TAG = "RecyclerViewAdapter";

    //variables for creating the recyclerView cards
    private ArrayList<Integer> iconList;
    private ArrayList<Integer> eventCounterList;
    private Context mContext;
    private int itemCount;
    private ArrayList<Calendar> calendarArrayList;
    private ArrayList<String> dayStr;
    private ArrayList<String> dayNum;

    public RecyclerViewAdapter(Context context, ArrayList<Integer> imageList, ArrayList<Integer> eventArray, int weeksInView,ArrayList<Calendar> calendarArrayList){
        this.iconList = imageList;
        this.eventCounterList = eventArray;
        this.mContext = context;
        this.itemCount = weeksInView*7;
        this.calendarArrayList = calendarArrayList;
        setDayStrNDayNum();

    }

    @NonNull
    @Override
    //this is the method that actually inflates each individual layout
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        Log.d(TAG, "onCreateViewHolder: called.");

        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_listitem,parent,false);

        return new ViewHolder(view);
    }

    @Override
    //this is where we bind the data to each individual list items
    //essentially all the data and stuff is actually attached in this method to each indiviual list item
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        Log.d(TAG, "onBindViewHolder: called");

        holder.fitnessIcon.getDrawable();
        holder.educationIcon.getDrawable();
        holder.personalIcon.getDrawable();
        holder.workIcon.getDrawable();

        holder.fitnessEventCounter.setText(eventCounterList.get(position));
        holder.educationEventCounter.setText(eventCounterList.get(position));
        holder.workEventCounter.setText(eventCounterList.get(position));
        holder.personalEventCounter.setText(eventCounterList.get(position));

        holder.dayString.setText(dayStr.get(position));
        holder.dayNum.setText(dayNum.get(position));

    }

    //returns the amount of items we wish to include in the recycler view (not the individual items within a card layout
    // but instead how many cards we wish to include...probably
    @Override
    public int getItemCount() {
        return itemCount;
    }

    public class ViewHolder extends RecyclerView.ViewHolder{

        ImageView fitnessIcon;
        ImageView educationIcon;
        ImageView workIcon;
        ImageView personalIcon;

        TextView dayString;
        TextView dayNum;
        TextView fitnessEventCounter;
        TextView educationEventCounter;
        TextView workEventCounter;
        TextView personalEventCounter;

        public ViewHolder(View itemView){
            super(itemView);

            //icons within the layout_listitem
            fitnessIcon = itemView.findViewById(R.id.fitnessIcon);
            educationIcon = itemView.findViewById(R.id.educationIcon);
            workIcon = itemView.findViewById(R.id.workIcon);
            personalIcon = itemView.findViewById(R.id.personalIcon);

            //text fields within the layout_listitem
            dayNum = itemView.findViewById(R.id.dayNum);
            dayString = itemView.findViewById(R.id.dayStr);
            fitnessEventCounter = itemView.findViewById(R.id.fitnessEventCounter);
            educationEventCounter = itemView.findViewById(R.id.educationEventCounter);
            workEventCounter = itemView.findViewById(R.id.workEventCounter);
            personalEventCounter = itemView.findViewById(R.id.personalEventCounter);


        }



    }

    public void setItemCount(int newItemCount){
        itemCount = newItemCount;
    }

    //sets the dayStr arrays and the dayNum array using CalendarArrayList
    // to pull the day in the month and the string value(monday,tuesday,etc.)
    private void setDayStrNDayNum(){

        Iterator<Calendar> itr = this.calendarArrayList.iterator();

        ArrayList<String> tempDayNum = new ArrayList<>();
        ArrayList<String> tempDayStr = new ArrayList<>();

        int i = 0;
        while(itr.hasNext()){
            String dayInMonth = getDayInMonth(calendarArrayList.get(i));
            String weekDayToString = weekDayToString(calendarArrayList.get(i));

            tempDayNum.add(dayInMonth);
            tempDayStr.add(weekDayToString);
            i++;
            itr.next();
        }//while

        this.dayNum = tempDayNum;
        this.dayStr = tempDayStr;

    }

    //takes in a Calendar Obj, gets the int, and returns it in a String Format
    private String getDayInMonth (Calendar c){
        Integer temp = c.get(Calendar.DAY_OF_MONTH);
        String answer = Integer.toString(temp);
        return answer;
    }

    //takes in a Calendar Obj, gets the weekday digit from 1 to 7, and returns a String
    // 1 being Su for Sunday, 2 Mo for Monday, and etc.
    private String weekDayToString (Calendar x){
        int temp = x.get(Calendar.DAY_OF_WEEK);

        switch(temp){
            case 1:
                return "Su";

            case 2:
                return "Mo";

            case 3:
                return "Tu";

            case 4:
                return "We";

            case 5:
                return "Th";

            case 6:
                return "Fr";

            case 7:
                return "Sa";

        }
        return "null";
    }//weekDayToString

}
AgainstAO
  • 11
  • 2

1 Answers1

0

here is an idea: in onCreate create some base list containing the next 1000 dates surrounding the current date for your recyclerview and use the following link to understand how to find out after any scrollevent at which position you are on the recyclerview. once you get close to the edges simply add an additional 1000 dates on that end of the spectrum.

Look at the following link to see how to set an onscrolllistener on a recyclerview inside of the adapter (basically you need to pass the recyclerview to the adapters constructor)

hope this helps

quealegriamasalegre
  • 1,385
  • 5
  • 18
  • Excellent suggestion. I hadn't thought to preload more events than what the user is currently viewing but I guess it makes more sense from a usability point of view. I also tried implementing the some of the methods you linked to but it seems most of them are using SetOnScrollListener...which apparently is now deprecated because android studio wont let me use it. I'm going to try to implement addOnScrollListener from the most recent comment on your second link soon, will update. Thank you again. – AgainstAO Mar 16 '20 at 07:18
  • yes I think addOnScrollListener will do exactly the same. they just changed it so you could add more than one scrolllistener. good luck with that hope it works – quealegriamasalegre Mar 16 '20 at 07:26
  • I've now passed the recycler view into the adapter class, while also seting the addOnScrollListener in a method to be called in the constructor...However it always is returning that I have 0 items in the layout manager. Tried copying it however to happen in the Home class just to see if it would work but it wont even print out the test statement I gave it inside the recyclerView.addOnScrollListerner method...its werid its like its not even initalizing – AgainstAO Mar 16 '20 at 19:40