Заполнение TabLayout с использованием FragmentStatePagerAdapter только с выбранными элементами

Я использую Android TabLayout для создания tabs с FragmentStatePagerAdapter как adapter. Теперь с этим кодом он генерирует items на каждом tab, когда я его прокручиваю.

SongManager.getAudioListFromResponse(result) дает List из Audio объектов, каждый из которых имеет String названный жанр. Например, первое аудио относится к жанру рок, а второе — к жанру блюз.

getItem() в SongListAdapter создает новый фрагмент, который использует атрибуты одного Audio и добавляет его к recylerview для отображения. (Я могу добавить SongListFragment, если нужно).

На данный момент этот код заполняет все вкладки одним и тем же Fragments. Неважно, какие tab я выберу, они все одинаковые.

Мой вопрос был бы.. Как я могу сделать так, чтобы он получал Audio's genre и сортировал его соответственно.

Или как я могу поймать в main activity Songmanager.getSonglist... что вкладка поменялась местами и каково название вкладки.

А также как мне сделать так, чтобы при выборе я мог добавить песню на вкладку recommended.

Вот код, в котором я создаю TabLayout :

SongManager.getSonglist(getApplicationContext(), new OkHttp3Connection.OkHttp3RequestCallback() {
        @Override
        public void onSuccess(String result, String user_tag) {

            ViewPager viewPager = findViewById(R.id.viewpager);

            SongListAdapter songListAdapter =
                    new SongListAdapter(getSupportFragmentManager(), getApplicationContext());
            songListAdapter.setAudioList(SongManager.getAudioListFromResponse(result));
            viewPager.setAdapter(songListAdapter);

            // Give the TabLayout the ViewPager
            TabLayout tabLayout = findViewById(R.id.tab_layout);
            tabLayout.setupWithViewPager(viewPager);

            songListAdapter.setItemListener(new SongListAdapter.SongListViewPagerListViewItemListener() {
                @Override
                public void onClick(Audio audio) {
                    goToCameraView();
                    songGraph.setAudio(audio);
                }
            });

            // Iterate over all tabs and set the custom view
            for (int i = 0; i < tabLayout.getTabCount(); i++) {

                TabLayout.Tab tab = tabLayout.getTabAt(i);

                if (tab != null) {
                    tab.setCustomView(songListAdapter.getTabView(i));
                }
            }
        }

        @Override
        public void onError(String error, String user_tag) {
            System.out.println("HTTP Error: " + error);
        }
    });

И весь SongListAdapter класс:

public class SongListAdapter extends FragmentStatePagerAdapter {

    String tabTitles[] = new String[]{"Recommended", "Popular", "Rock", "Pop", "Blues", "Chill"};
    Context context;



    private ArrayList<Audio> audioList;

    public SongListAdapter(FragmentManager fm, Context context) {
        super(fm);
        this.context = context;
    }

    @Override
    public int getCount() {
        return tabTitles.length;
    }

    @Override
    public SongListFragment getItem(int position) {
        SongListFragment slf = new SongListFragment();
        slf.setAudioList(getAudioList());
        slf.setItemOnClickListener(new SongListFragment.SongListItemOnClickListener() {
            @Override
            public void onClick(Audio audio) {
                System.out.println("asdfdas");
                itemListener.onClick(audio);
            }
        });
        return slf;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        // Generate title based on item position
        return tabTitles[position];
    }

    public View getTabView(int position) {
        View tab = LayoutInflater.from(context).inflate(R.layout.custom_tab, null);
        TextView tv = tab.findViewById(R.id.custom_text);
        tv.setText(tabTitles[position]);
        return tab;
    }

    public ArrayList<Audio> getAudioList() {
        return audioList;
    }

    public void setAudioList(ArrayList<Audio> audioList) {
        this.audioList = audioList;
    }

    SongListViewPagerListViewItemListener itemListener;

    public void setItemListener(SongListViewPagerListViewItemListener itemListener) {
        this.itemListener = itemListener;
    }

    public interface SongListViewPagerListViewItemListener {
        void onClick(Audio audio);
    }
}

Весь результат выглядит так:

введите здесь описание изображения


comment
Пожалуйста, уточните свой вопрос! Мне нужно несколько фрагментов на одной вкладке и так далее. Вы говорите, что вам нужны некоторые фрагменты на одной вкладке и другие фрагменты на других вкладках? Если это так, вам понадобится другая структура данных, например список списков, и верните выбранный список в ваш адаптер. Вы также можете использовать (жанр?) фильтр и вернуть отфильтрованный результат из ваш адаптер   -  person kalabalik    schedule 02.07.2018
comment
@kalabalik Попытался уточнить вопрос   -  person kataroty    schedule 02.07.2018
comment
Можете ли вы получить списки песен из SongManager в зависимости от жанра? Если нет, то получите список песен, который у вас есть сейчас, а затем повторите список, чтобы создать несколько списков в зависимости от жанра. Это не идеально, но это то, что вам придется делать, если у вас нет API, который возвращает список на основе жанра.   -  person denvercoder9    schedule 02.07.2018
comment
Несколько ошибок: 1. tab.setCustomView(songListAdapter.getTabView(i)); является избыточным. Вы уже делаете setupWithViewPager(..). Кроме того, ваш пользовательский вид — это просто текст, так зачем надувать его самостоятельно. 2. slf.setAudioList(getAudioList()); вы не передаете данные во фрагменты. Посмотрите на это: stackoverflow.com/questions/7149802/   -  person denvercoder9    schedule 02.07.2018
comment
@ rafid059 Список, который возвращает SongManager, имеет свойства жанра. https://pastebin.com/tgXgrWrR — это ссылка на SongManager. Исходя из этого, мне придется составлять несколько списков?   -  person kataroty    schedule 02.07.2018
comment
@ rafid059 допустим, я создаю несколько списков, но где я указываю, какой список относится к какой вкладке, это часть, которую я не совсем понимаю   -  person kataroty    schedule 02.07.2018
comment
Вы передаете все списки классу адаптера и устанавливаете для каждого из них разные фрагменты в зависимости от позиции.   -  person denvercoder9    schedule 02.07.2018
comment
С помощью этого кода.. Как я могу поймать в основном действии Songmanager.getSonglist..., что вкладка поменялась местами и каково название вкладки. Думаю, я мог бы понять это оттуда.   -  person kataroty    schedule 02.07.2018
comment
Вы получаете один и тот же список на всех вкладках, в этом проблема? И вы хотите показать список, основанный на поколениях на разных вкладках? Пожалуйста, просто очистите? Потому что я знаю решение, и я был в таком состоянии раньше.   -  person Man    schedule 04.07.2018


Ответы (2)


Я отвечу на то, что вы понимаете из вашего вопроса, то есть вы хотите отображать разные списки аудио в зависимости от жанра на разных вкладках.

Итак, я думаю, что первая проблема связана с тем, как вы возвращаете экземпляр фрагмента из метода getItem SongsListAdapter, т.е.

@Override
    public SongListFragment getItem(int position) {
        SongListFragment slf = new SongListFragment();
        slf.setAudioList(getAudioList());
        slf.setItemOnClickListener(new SongListFragment.SongListItemOnClickListener() {
            @Override
            public void onClick(Audio audio) {
                System.out.println("asdfdas");
                itemListener.onClick(audio);
            }
        });
        return slf;
    }

Здесь вы должны вернуть разные экземпляры SongListFragment, отфильтровав AudioList на основе жанра. Так что это может выглядеть примерно так:

@Override
    public SongListFragment getItem(int position) {
        SongListFragment slf = new SongListFragment();
        slf.setAudioList(filterBasedOnGenre(getAudioList(), tabTitles[position]));
        slf.setItemOnClickListener(new SongListFragment.SongListItemOnClickListener() {
            @Override
            public void onClick(Audio audio) {
                System.out.println("asdfdas");
                itemListener.onClick(audio);
            }
        });
        return slf;
    }

public ArrayList<Audio> filterBasedOnGenre(ArrayList<Audio> audioList, String genreToFilter)
    {
        ArrayList<Audio> filteredAudioList = new ArrayList<>();

        for (Audio audio : audioList) {
            if (audio.getGenre().equalsIgnoreCase(genreToFilter)) {
                filteredAudioList.add(audio);
            }  
        }
        return filteredAudioList; 
    }

Рассмотрение аудио выглядит так:

    public class Audio {
           public Audio(String songName, String singer, String genre) {
                this.songName = songName;
                this.singer = singer;
                this.genre = genre;
            }

            private String songName;
            private String singer;
            private String genre;

            public String getSongName() {
                return songName;
            }

            public void setSongName(String songName) {
                this.songName = songName;
            }

            public String getSinger() {
                return singer;
            }

            public void setSinger(String singer) {
                this.singer = singer;
            }

            public String getGenre() {
                return genre;
            }

            public void setGenre(String genre) {
                this.genre = genre;
            }
        }

Надеюсь, это поможет.
Дайте мне знать, если вам понадобится дополнительная помощь.

person Man    schedule 04.07.2018
comment
Извините, я действительно понял что-то близкое к этому, но забыл ответить на него здесь. В любом случае, спасибо за ответ, и я думаю, что дам вам награду, но я подожду день или около того. Возможно, есть лучшее решение. - person kataroty; 05.07.2018
comment
На самом деле, я знаю, что есть лучшие способы реализации, потому что я сам пробовал их. Я хотел дать самое простое решение за меньшее время. Я рад, что вы нашли решение самостоятельно, молодец. - person Man; 05.07.2018

Итак, ваше решение для самостоятельного решения хорошо. В настоящее время я работаю над приложением медиаплеера, поэтому, если вы хотите кэшировать свой songadapater или что-то еще, вам нужно создать файл кеша для хранения вашего объекта массива.

этот метод записывает кэш в файл.

void createdcachedreadfile(Context con, String filename) throws IOException {
    String tempfile = null;
    for (Songpojo file : songpojoList) {
        FileOutputStream fos = null;
        try {
            fos = con.openFileOutput(filename, Context.MODE_PRIVATE);
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(songpojoList);
            oos.close();
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

И восстановить

  public Object readCaheFile(Context context1, String filename) throws IOException, ClassNotFoundException {
    FileInputStream fis = context1.openFileInput(filename);
    ObjectInputStream ois = new ObjectInputStream(fis);
    Object object = ois.readObject();
    return object;
}

Может быть, это все еще полезно

Удачного кодирования!!!!

person Jigar Fumakiya    schedule 09.07.2018