简体   繁体   中英

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: 在此处输入图片说明

Navigation Drawer with Fragments: (I'd like to insert the list view into 'Home' Fragment 在此处输入图片说明

Any help will be much appreciated!

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~

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM