AndroidDevBro
AndroidDevBro

Reputation: 151

Android: ListView / GridView Overlapping Toolbar in MainActivity/Fragment

so I've recently been following this tutorial in order to create a ListView within my HomePage which is a Fragment. As this wouldn't work (to my knowledge?), I instead implemented the following code into my Main Activity, which holds a Navigation Drawer. I have tried to simplify your understanding along with app's order of what I'd like to achieve below:

  1. User logs into app
  2. User is the taken to the "Main Activity" which holds a Navigation Drawer via Intent
  3. User has a choice of selecting from various Fragments within the Navigation Drawer (Home, Favourites, Help, etc.) <-- This does not work any longer as the list view overlaps the MainActivity completely, including the toolbar which allows access to the Navigation Drawer (which is what I want to display within my Fragment "Home") -->

I have also created Product class to hold methods for Image, Title and Description within the ListView/GridView. I've also created ListViewAdapter and GridViewAdapter classes to extend the 'Products' held within the ListView/GridView.

MainActivity.java:

import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewStub;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.ListView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {

    private ViewStub stubGrid;
    private ViewStub stubList;
    private ListView listView;
    private GridView gridView;
    private ListViewAdapter listViewAdapter;
    private GridViewAdapter gridViewAdapter;
    private List<Product> productList;
    private int currentViewMode = 0;

    static final int VIEW_MODE_LISTVIEW = 0;
    static final int VIEW_MODE_GRIDVIEW = 1;

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

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);

        stubList = (ViewStub) findViewById(R.id.stub_list);
        stubGrid = (ViewStub) findViewById(R.id.stub_grid);

        // Inflate ViewStub before we get view
        stubList.inflate();
        stubGrid.inflate();

        listView = (ListView) findViewById(R.id.myListView);
        gridView = (GridView) findViewById(R.id.myGridView);

        // Get list of products
        getProductList();

        // Get current view mode in shared preferences
        SharedPreferences sharedPreferences = getSharedPreferences("View Mode", MODE_PRIVATE);
        currentViewMode = sharedPreferences.getInt("currentViewMode", VIEW_MODE_LISTVIEW); // Default view is ListView

        // Register item click
        //listView.setOnItemClickListener(onItemClick);
        //gridView.setOnItemClickListener(onItemClick);

        switchView();
    }

    private void switchView() {
        if (VIEW_MODE_LISTVIEW == currentViewMode) {
            // Display ListView
            stubList.setVisibility(View.VISIBLE);
            // Hide GridView
            stubGrid.setVisibility(View.GONE);
        } else {
            // Hide ListView
            stubList.setVisibility(View.GONE);
            // Display GridView
            stubGrid.setVisibility(View.VISIBLE);
        }

        setAdapters();

    }

    private void setAdapters() {
        if (VIEW_MODE_LISTVIEW == currentViewMode) {
            listViewAdapter = new ListViewAdapter(this, R.layout.list_item, productList);
            listView.setAdapter(listViewAdapter);
        } else {
            gridViewAdapter = new GridViewAdapter(this, R.layout.grid_item, productList);
            gridView.setAdapter(gridViewAdapter);
        }
    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

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

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.item_menu_1:
                if (VIEW_MODE_LISTVIEW == currentViewMode) {
                    currentViewMode = VIEW_MODE_GRIDVIEW;
                } else {
                    currentViewMode = VIEW_MODE_LISTVIEW;
                }
                // Switch view
                switchView();
                // Save view mode in share preferences
                SharedPreferences sharePreferences = getSharedPreferences("ViewMode", MODE_PRIVATE);
                SharedPreferences.Editor editor = sharePreferences.edit();
                editor.putInt("currentViewMode", currentViewMode);
                editor.commit();

                break;
        }
        // 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);
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        if (id == R.id.first_fragment) {
            setTitle("Home");
            FirstFragment fragment = new FirstFragment();
            FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.frame, fragment, "fragment1");
            fragmentTransaction.commit();
        } else if (id == R.id.second_fragment) {
            setTitle("Favourites");
            SecondFragment fragment = new SecondFragment();
            FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.frame, fragment, "fragment2");
            fragmentTransaction.commit();
        } else if (id == R.id.third_fragment) {
            setTitle("Account");
            ThirdFragment fragment = new ThirdFragment();
            FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.frame, fragment, "fragment3");
            fragmentTransaction.commit();
        } else if (id == R.id.fourth_fragment) {
            setTitle("Help & Feedback");
            FourthFragment fragment = new FourthFragment();
            FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.frame, fragment, "fragment4");
            fragmentTransaction.commit();
        }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

    public List<Product> getProductList() {
        // Pseudo code to get product, replace your code to get product here
        productList = new ArrayList<>();
        productList.add(new Product(R.drawable.nightclub, "Title 1", "This is description 1"));
        productList.add(new Product(R.drawable.nightclub, "Title 2", "This is description 2"));
        productList.add(new Product(R.drawable.nightclub, "Title 3", "This is description 3"));
        productList.add(new Product(R.drawable.nightclub, "Title 4", "This is description 4"));
        productList.add(new Product(R.drawable.nightclub, "Title 5", "This is description 5"));
        productList.add(new Product(R.drawable.nightclub, "Title 6", "This is description 6"));
        productList.add(new Product(R.drawable.nightclub, "Title 7", "This is description 7"));
        productList.add(new Product(R.drawable.nightclub, "Title 8", "This is description 8"));
        productList.add(new Product(R.drawable.nightclub, "Title 9", "This is description 9"));
        productList.add(new Product(R.drawable.nightclub, "Title 10", "This is description 10"));

        return productList;
    }

    /*
    AdapterView.OnItemClickListener onItemClick = new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            // Do something when u ser clicks an item
            Toast.makeText(getApplicationContext(), productList.get(position).getTitle() + " - " + productList.get(position).getDescription(), Toast.LENGTH_SHORT).show();
        }
    };*/
}

Content_Main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.example.michael.whatsupldn.MainActivity"
    tools:showIn="@layout/app_bar_main">

    <FrameLayout
        android:id="@+id/frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:alpha="200"/>
</LinearLayout>

Activity_Main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayoutx mlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <include
        layout="@layout/app_bar_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer"/>

    <ViewStub
        android:id="@+id/stub_list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:inflatedId="@+id/showlayout"
        android:layout="@layout/my_listview"/>

    <ViewStub
        android:id="@+id/stub_grid"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:inflatedId="@+id/showlayout"
        android:layout="@layout/my_gridview"/>

</android.support.v4.widget.DrawerLayout>

app_bar_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.michael.whatsupldn.MainActivity">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/london_skyline_dark"
        android:layout_alignParentTop="true"
        android:id="@+id/imageView"
        android:contentDescription="@string/london_skyline"/>

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main" />

</android.support.design.widget.CoordinatorLayout>

Emulator Output of MainActivity:

Expected Output: enter image description here

Navigation Drawer with Fragments: (I'd like to insert the list view into 'Home' Fragment enter image description here

Any help will be much appreciated!

Upvotes: 0

Views: 753

Answers (2)

Ferdous Ahamed
Ferdous Ahamed

Reputation: 21766

First of all, DrawerLayout can hold at-most two child views. First view contains the main content for the screen (your primary layout when the drawer is hidden) and Second view contains the contents of the navigation drawer.

See Documentation

SOLUTION:

1. Remove ViewStub for ListView and GridView from activity_Main layout.

// activity_Main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayoutx mlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <include
        layout="@layout/app_bar_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer"/>

</android.support.v4.widget.DrawerLayout>

2. Instead of ListView and GridView, just use only RecyclerView with different LayoutManager. Use LinearLayoutManager for list and GridLayoutManager for grid. Assuming that you are using FirstFragment as HomeFragment. In your FirstFragment layout XML, add a RecyclerView for showing list or grid.

// first_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_height="match_parent"
    android:layout_width="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false" />

</RelativeLayout>

3. In your FirstFragment class, add two layout manager(LinearLayoutManager and GridLayoutManager).

If you want to show List then use LinearLayoutManager and for Grid use GridLayoutManager with RecyclerView. Toggle view by calling method toggleListGrid().

Update your FirstFragment as below:

//FirstFragment.java

.........
...............

RecyclerView mRecyclerView;

RecyclerView.LayoutManager mGridLayoutManager;
RecyclerView.LayoutManager mLinearLayoutManager;

boolean isList = false; // By default list will be shown


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

    // Required for option menu
    setHasOptionsMenu(true);
}

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

    //REFERENCE
    mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);

    // Layout manager
    mGridLayoutManager = new GridLayoutManager(getActivity(), 2);
    mLinearLayoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);

    // Set layout manager
    toggleListGrid();


    // Set adapter to RecyclerView
    ...............
    ....................

    return rootView;
}

public void toggleListGrid() {

    isList = !isList;

    if(isList)
        mRecyclerView.setLayoutManager(mLinearLayoutManager);
    else
        mRecyclerView.setLayoutManager(mGridLayoutManager);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) 
{
    // Inflate the menu; this adds items to the action bar if it is present.
    inflater.inflate(R.menu.main, menu);

    super.onCreateOptionsMenu(menu, inflater);
}   

@Override
public boolean onOptionsItemSelected(MenuItem item)
{
    switch(item.getItemId())
    {
        case R.id.item_menu_1:
        {
            // Change view
            toggleListGrid();
            return true;
        }
        default:
            return super.onOptionsItemSelected(item);       
    }
}

.........
...................

4. Add an RecyclerView.Adapter to populate your data on RecyclerView.

Here is a good tutorial about RecyclerView: Android NavigationView – Fragments With RecyclerView

Hope this will help~

Upvotes: 1

Jameido
Jameido

Reputation: 1354

You should add this line of code app:layout_behavior="@string/appbar_scrolling_view_behavior" in your stub_list and stub_list ViewStub xml declaration, that should position it directly below the appbar; you can read more about that here under the CoordinatorLayout and the app bar section

Upvotes: 0

Related Questions