TabLayout mit RecyclerView zur weiteren Navigation

N

Nono

Neues Mitglied
Threadstarter
Hallo zusammen,

ich habe eine Tabbed Acitivity mit 3 Tabs. In jedem Tab soll eine Liste, in diesem Fall als RecyclerView umgesetzt, mit Elementen sein, auf die man drauf klicken kann, um zu einer neuen Seite zu gelangen. Die Tabs sollen aber zu jeder Zeit weiter anklickbar sein. Hier ist ein Bild von meinem aktuellen Stand:



Da diese von Android Studio generierte Tabbed Activity mit Fragments arbeitet, habe ich es so versucht, dass bei einem Klick auf so ein Listen-Element ein neues entsprechendes Fragment geöffnet wird. Nachfolgend werde ich euch meinen Code zeigen.

Zuerst die MainActivity mit dem TabLayout. Hier habe ich bereits eine Methode eingebaut, die aufgerufen werden soll, wenn ein Listen-Element angeklickt wurde.

Code:
public class MainActivity extends AppCompatActivity {

    private SectionsPagerAdapter mSectionsPagerAdapter;

    private ViewPager mViewPager;
    private Toolbar toolbar;

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

        toolbar = (Toolbar) findViewById(R.id.toolbar);
        toolbar.setTitle("Pflege");
        setSupportActionBar(toolbar);

        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

        // Hier soll später wenns klappt die Toolbar mit einem Back-Button versehen werden

        FragmentManager.OnBackStackChangedListener mBackStackListener = new FragmentManager.OnBackStackChangedListener() {
            @Override
            public void onBackStackChanged() {
                FragmentManager manager = getSupportFragmentManager();
                int count = manager.getBackStackEntryCount();
                if(count > 0) {
                    // TODO: Show back icon
                } else {
                    // TODO: Other icon
                }
            }
        };
        FragmentManager manager = getSupportFragmentManager();
        manager.addOnBackStackChangedListener(mBackStackListener);

        mViewPager = (ViewPager) findViewById(R.id.container);
        mViewPager.setAdapter(mSectionsPagerAdapter);

        TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(mViewPager);

        tabLayout.getTabAt(0).setIcon(R.drawable.tab_icon_pflege);
        tabLayout.getTabAt(1).setIcon(R.drawable.tab_icon_dokumentation);
        tabLayout.getTabAt(2).setIcon(R.drawable.tab_icon_probleme);

        tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                switch(tab.getPosition()) {
                    case 0:
                        mViewPager.setCurrentItem(0);
                        toolbar.setTitle("Pflege");
                        break;
                    case 1:
                        mViewPager.setCurrentItem(1);
                        toolbar.setTitle("Daten");
                        break;
                    case 2:
                        mViewPager.setCurrentItem(2);
                        toolbar.setTitle("Probleme");
                        break;
                    default:
                        mViewPager.setCurrentItem(tab.getPosition());
                        toolbar.setTitle("Pflege");
                        break;
                }
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });

    }

    // Diese Methode soll bei einem Klick auf ein Listen-Element aufgerufen werden, um ein neues Fragment zu laden

    public void onItemSelected (Fragment fragment){
        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.container, fragment);
        String name = "Test";
        fragmentTransaction.addToBackStack(name);
        fragmentTransaction.commit();
        getSupportActionBar().setTitle(name);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }


    /**
     * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
     * one of the sections/tabs/pages.
     */
    public class SectionsPagerAdapter extends FragmentPagerAdapter {

        public SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            switch(position){
                case 0:
                    Tab1Pflege tab1 = new Tab1Pflege();
                    return tab1;
                case 1:
                    Tab2Dokumentation tab2 = new Tab2Dokumentation();
                    return tab2;
                case 2:
                    Tab3Probleme tab3 = new Tab3Probleme();
                    return tab3;
                default:
                    return null;
            }
        }

        @Override
        public int getCount() {
            // Show 3 total pages.
            return 3;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            switch (position) {
                case 0:
                    return "Pflege";
                case 1:
                    return "Daten";
                case 2:
                    return "Probleme";
            }
            return null;
        }
    }

}
Hier kommt jetzt die Klasse für den ersten Tab. Hier wird der RecyclerView erstellt mit der RvAdapter Klasse, an die ich die MainActivity übergebe, damit in der RvAdapter Klasse die onItemSelected Methode benutzt werden kann.

Code:
public class Tab1Pflege extends Fragment {

    private RecyclerView recyclerView;
    private RecyclerView.Adapter rvAdapter;
    private RecyclerView.LayoutManager rvLayoutManager;

    private ArrayList<String> listItems;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.tab1_pflege, container, false);

        listItems = new ArrayList<>();
        listItems.add("Test1");
        listItems.add("Test2");
        listItems.add("Test3");

        recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
        rvLayoutManager = new LinearLayoutManager(getActivity());
        recyclerView.setLayoutManager(rvLayoutManager);
        rvAdapter = new RvAdapter(listItems, (MainActivity) getActivity());
        recyclerView.setAdapter(rvAdapter);

        return rootView;
    }

}
Hier ist jetzt der Code der RvAdapter Klasse. Dort wird ein onClickListener für die Listen-Elemente erstellt, in dem die Methode aus der MainActivity aufgerufen wird.

Code:
public class RvAdapter extends RecyclerView.Adapter<RvAdapter.MyViewHolder> {

    private ArrayList<String> listItems;
    private MainActivity activity;

    public RvAdapter (ArrayList<String> listItems, MainActivity activity){

        this.listItems = listItems;
        this.activity = activity;

    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.rv_item_layout, null);

        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, final int position) {

        holder.itemTitle.setText(listItems.get(position));
        holder.itemImage.setImageResource(R.drawable.ic_keyboard_arrow_right);


        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Wasserwechsel wasserwechsel = new Wasserwechsel();
                activity.onItemSelected(wasserwechsel);

            }
        });

    }

    @Override
    public int getItemCount() {
        return listItems.size();
    }

    public class MyViewHolder extends RecyclerView.ViewHolder{

        TextView itemTitle;
        ImageView itemImage;

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

            itemTitle = (TextView) itemView.findViewById(R.id.itemTitle);
            itemImage = (ImageView) itemView.findViewById(R.id.itemImage);
        }

    }
"Wasserwechsel" heißt die Klasse, die erstmal bei einem Klick auf ein Element aufgerufen werden soll. Der Code dafür ist hier:

Code:
public class Wasserwechsel extends Fragment {

    public TextView textView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.wasserwechsel, container, false);
        textView = (TextView) rootView.findViewById(R.id.textView);

        return rootView;
    }

}
Sie beinhaltet erstmal nur ein TextView. Aktuell kann ich jetzt normal zwischen den Tabs hin und her wechseln, das funktioniert. Wenn ich im ersten Tab dann aber zum Beispiel auf "Tab1" klicke, verschwindet der RecyclerView und der Inhalt bleibt leer, also es wird nicht das TextView aus dem "Wasserwerte" Fragment angezeigt. Wenn ich zum zweiten Tab wechsel ist dieses komischerweise ebenfalls leer, beim dritten aber nicht.

Ich möchte es also so hinbekommen, dass die Tabs die Hauptnavigation zwischen den 3 Oberbereichen bieten sollen. Innerhalb dieser Tabs sollen aber weitere Unterseiten verlinkt sein. Wenn man auf so eine Unterseite geht soll der Titel in der Toolbar geändert werden und ein Back-Button eingefügt werden. Weiterhin soll man aber auch noch zwischen den Tabs hin und her wechseln können.

Kann mir jemand dabei helfen meinen Code lauffähig zu bekommen oder mir eine Möglichkeit nennen, eine solche Art der Navigation besser hinzubekommen? Kennt jemand vielleicht sogar ein gutes Tutorial, das genau so eine Navigation mit Tabs und Listen behandelt?

Ich würde mich sehr über Hilfe freuen.
Viele Grüße
 
markus.tullius

markus.tullius

Experte
Hallo Nono,

soll die App wirklich wie eine iPhone App aussehen?
Wenn nicht, würde an deiner Stelle lieber ein NavigationDrawer verwenden. Der ist einfacher zu implementieren, und sieht moderner aus. (Und kein Android-User tippt aus Versehen auf die NavigationsBar, die sich bei allen Handys ohne Hardwaretasten direkt unter der TabBar befindet).


Creating a Navigation Drawer | Android Developers
https://material.io/guidelines/patterns/navigation-drawer.html
Android Sliding Menu using Navigation Drawer

Und sonst liegt dein Problem in den Austausch deiner Fragmente. Statt Wasserwerfer in den Container zu packen, starte lieber eine neue Activity mit dem Fragment Wasserwerfer.
 
Ähnliche Themen - TabLayout mit RecyclerView zur weiteren Navigation Antworten Datum
20
7
5
Oben Unten