Moin,
ich habe in dem ViewPager2 mit TabLayout einen Recyclerview. Um in den die Daten einzuspeisen benutze ich einen Adapter (ViewPagerAdapter). Sobald die Daten in dem RecyclerView drin sind, ist die Interaktion mit den Daten kein Problem. Problematisch wird aber die erste Ebene, der richtige Umgang mit dem ViewPagerAdapter. Wenn ich in der tabbed Ansicht bin und den Tab wechsel, wird sofort der Adapter für die restlichen Tabs erzeugt und die Daten werden nur auf dem letzten Tab aktualisiert.
Hier ist meine Activity, die den ViewPagerAdapter implementiert;
public class AudioFilePanel extends AppCompatActivity
{
public static final int FILE_BROWSER_REQUEST_CODE = 1;
private String currentTab;
private ViewPagerAdapter adapter;
private ViewPager2 viewPager;
private Map<String, List<FileElement>> content;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_audio_file_panel);
viewPager = findViewById(R.id.view_pager2);
TabLayout tabLayout = findViewById(R.id.tabs);
Button addFilesByTag = findViewById(R.id.add_files_with_tag);
if (null == currentTab)
{
currentTab = "music";
}
content = listByTag();
adapter = new ViewPagerAdapter(getApplicationContext(), new ArrayList<>(content.values()), currentTab);
viewPager.setAdapter(adapter);
new TabLayoutMediator(tabLayout, viewPager,
(tab, position) -> tab.setText(content.keySet().toArray()[position].toString())).attach();
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener()
{
@Override
public void onTabSelected(TabLayout.Tab tab)
{
currentTab = tab.getText().toString();
}
@Override
public void onTabUnselected(TabLayout.Tab tab)
{
}
@Override
public void onTabReselected(TabLayout.Tab tab)
{
}
});
addFilesByTag.setOnClickListener(l ->
{
Intent fileBrowser = new Intent(AudioFilePanel.this, FileBrowser.class);
startActivityForResult(fileBrowser, 1);
});
}
private void updateViweData()
{
content = listByTag();
adapter = new ViewPagerAdapter(getApplicationContext(), new ArrayList<>(content.values()), currentTab);
viewPager.setAdapter(adapter);
}
private Map<String, List<FileElement>> listByTag()
{
Map<String, List<FileElement>> result = new HashMap<>();
DirectoryDao dao = new DirectoryDao(getApplicationContext());
String[] categories = {"music", "ambience", "effect"};
for (String category : categories)
{
List<FileElement> directories =
dao.getDirectoriesForCategory(category).stream().map(f -> new FileElement( new File(f.getPath()).getName(), f.getPath(), true)).collect(Collectors.toList());
result.put(category, directories);
}
return result;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK && requestCode == FILE_BROWSER_REQUEST_CODE)
{
String path = data.getStringExtra("path");
storeDirectory(path, data.getBooleanExtra("includeSubdirs", true), currentTab);
updateViweData();
}
}
private void storeDirectory(String path, boolean recursive, String tag)
{
Directory directory = new Directory();
directory.setPath(path);
directory.setTag(tag);
directory.setRecursive(recursive);
DirectoryDao dao = new DirectoryDao(getApplicationContext());
directory.setId(dao.insert(directory));
}
}
Alles anzeigen
Das ist der ViewPagerAdapter:
Beim debuggen habe ich rausgefunden, dass beim ersten Tabwechsel (danach nicht mehr) direkt der onBindViewHolder ausgeführt wird.
public class ViewPagerAdapter extends RecyclerView.Adapter<ViewPagerAdapter.ViewHolder>
{
private static final String PREVIOUS_DIRECTORY = "previous directory";
private List<List<FileElement>> filesListsByCategory;
private LayoutInflater mInflater;
private Context ctx;
private ItemListAdapter adapter;
private String rootPath;
private List<FileElement> rootElements;
private String tag;
public ViewPagerAdapter(Context context, List<List<FileElement>> data, String tag)
{
this.mInflater = LayoutInflater.from(context);
this.filesListsByCategory = data;
this.ctx = context;
this.tag = tag;
rootElements = new ArrayList<>(filesListsByCategory.get(0));
}
@NotNull
@Override
public ViewHolder onCreateViewHolder(@NotNull ViewGroup parent, int viewType)
{
return new ViewHolder(mInflater.inflate(R.layout.item_viewpager, parent, false));
}
@Override
public void onBindViewHolder(ViewHolder holder, int position)
{
FileBrowserService fbs = new FileBrowserService();
List<FileElement> categoryFiles = new ArrayList<>(filesListsByCategory.get(position));
adapter = new ItemListAdapter(categoryFiles, item -> handleClickOnElement(fbs, item));
holder.myView.setAdapter(adapter);
}
private void handleClickOnElement(FileBrowserService fbs, FileElement item)
{
if (new File(item.getPath()).isDirectory())
{
List<FileElement> newContent;
String newPath;
if (item.isRoot())
{
rootPath = item.getPath();
}
if (PREVIOUS_DIRECTORY.equals(item.getName()))
{
newPath = item.getPath().substring(0, item.getPath().lastIndexOf('/'));
} else
{
newPath = item.getPath();
}
FileElement goToParent = new FileElement(PREVIOUS_DIRECTORY, newPath, false);
if (item.getPath().equals(rootPath) && !item.isRoot())
{
newContent = rootElements;
} else
{
newContent = fbs.getFiles(newPath);
newContent.add(0, goToParent);
}
updateListElements(newContent);
} else
{
//TODO: play track
}
}
private void updateListElements(List<FileElement> newContent)
{
adapter.updateData(null, "clearData");
adapter.updateData(newContent, "updateData");
}
@Override
public int getItemCount()
{
return filesListsByCategory.size();
}
class ViewHolder extends RecyclerView.ViewHolder
{
RecyclerView myView;
RelativeLayout relativeLayout;
ViewHolder(View itemView)
{
super(itemView);
myView = itemView.findViewById(R.id.my_list);
myView.setLayoutManager(new LinearLayoutManager(ctx));
relativeLayout = itemView.findViewById(R.id.container);
}
}
}
Alles anzeigen
Das Endeffekt sieht so aus:
Hat jemand eine Idee wie man den ViewPagerAdapter anbinden muss oder was ich falsch mache?
(Es ist für mich sehr wichtig die Antworten zu erklären, denn ich möchte eine Lösung, aber ich möchte es auch verstehen)