Android:MainActivity/Fragment 中的 ListView / GridView 重叠工具栏

Posted

技术标签:

【中文标题】Android:MainActivity/Fragment 中的 ListView / GridView 重叠工具栏【英文标题】:Android: ListView / GridView Overlapping Toolbar in MainActivity/Fragment 【发布时间】:2017-12-18 08:12:15 【问题描述】:

所以我最近一直在关注this 教程,以便在我的主页中创建一个ListView,这是一个片段。由于这行不通(据我所知?),我改为将以下代码实现到包含导航抽屉的主活动中。我已尝试简化您对应用程序的理解以及我希望在下面实现的目标:

    用户登录应用 用户通过Intent 被带到“主要活动”,其中包含一个导航抽屉 用户可以选择从导航抽屉中的各种片段(主页、收藏夹、帮助等)

我还创建了 Product 类来保存 ListView/GridView 中的 Image、Title 和 Description 方法。我还创建了 ListViewAdapter 和 GridViewAdapter 类来扩展 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_
    android:layout_
    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_
        android:layout_
        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_
    android:layout_
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <include
        layout="@layout/app_bar_main"
        android:layout_
        android:layout_ />

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_
        android:layout_
        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_
        android:layout_
        android:layout_marginTop="10dp"
        android:inflatedId="@+id/showlayout"
        android:layout="@layout/my_listview"/>

    <ViewStub
        android:id="@+id/stub_grid"
        android:layout_
        android:layout_
        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_
    android:layout_
    tools:context="com.example.michael.whatsupldn.MainActivity">

    <ImageView
        android:layout_
        android:layout_
        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_
        android:layout_
        android:theme="@style/AppTheme.AppBarOverlay">

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

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

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

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

MainActivity 的模拟器输出:

预期输出:

带有片段的导航抽屉:(我想将列表视图插入到“主页”片段中

任何帮助将不胜感激!

【问题讨论】:

请发帖activity_main.xml @StanislavBondar 完成,请查看。我还上传了我的 content_main.xml,以备不时之需... 最简单的方法是在xml中添加android:layout_marginTop="?attr/actionBarSize"ViewStub 能否也添加您的app_bar_main.xml 文件? @LucaRossi 好的我已经上传了,看看 【参考方案1】:

首先,DrawerLayout 最多可以容纳two 子视图。 First 视图包含主屏幕 content (your primary layout when the drawer is hidden),Second 视图包含 navigation drawer 的内容。

见Documentation

解决方案:

1.activity_Main布局中删除ListViewGridViewViewStub

// 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_
    android:layout_
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <include
        layout="@layout/app_bar_main"
        android:layout_
        android:layout_ />

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_
        android:layout_
        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. 而不是ListViewGridView,只使用RecyclerView 和不同的LayoutManager。对列表使用LinearLayoutManager,对网格使用GridLayoutManager。假设您使用FirstFragment 作为HomeFragment。在您的 FirstFragment 布局 XML 中,添加 RecyclerView 以显示列表或网格。

// 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_
    android:layout_>

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

</RelativeLayout>

3. 在您的FirstFragment 类中,添加两个布局管理器(LinearLayoutManagerGridLayoutManager)。

如果您想显示List,请使用LinearLayoutManager 和 对于Grid 使用GridLayoutManagerRecyclerView。通过调用方法toggleListGrid()切换视图。

更新您的FirstFragment 如下:

//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. 添加RecyclerView.Adapter 以在RecyclerView 上填充您的数据。

这是一个关于 RecyclerView 的好教程: Android NavigationView – Fragments With RecyclerView

希望对你有帮助~

【讨论】:

感谢您的详细解答。但是我对第 2 步感到困惑,您指的是哪个 .xml,.java 文件?如中,我应该在哪里插入 RecyclerView,以及如何声明它们? 我已经更新了我的答案。使用RecyclerView 代替ListViewGridView。当我从activity_main.xml 中的STEP 1 中删除ListViewGridView 因此,为了显示列表和网格,我在first_fragment.xml 中添加了RecyclerView。正如我在STEP 3 and 4 中所述,您必须使用Adapter 来表示RecyclerView 和两个LayoutManager。主要是根据您的需要在任何片段上显示列表/网格。见附件教程链接,了解RecyclerViewFragment的使用。 你没有提到必须为片段创建一个适配器类,在这种情况下有必要吗? (如视频教程所示) 我在 STEP 4 中提到过。Add an RecyclerView.Adapter to populate your data on RecyclerView.。按照教程为 RecyclerView 创建适配器。 感谢您接受我的回答。如果它看起来有用,我希望你也投赞成票。谢谢~【参考方案2】:

你应该在你的stub_liststub_list ViewStub xml 声明中添加这行代码app:layout_behavior="@string/appbar_scrolling_view_behavior",它应该直接位于应用栏下方;您可以在 CoordinatorLayout 和应用栏部分

阅读更多关于 here 的信息

【讨论】:

我已经在 MainActivity.xml 中的两个 ViewStub 中添加了上面的行,但是没有任何改变。

以上是关于Android:MainActivity/Fragment 中的 ListView / GridView 重叠工具栏的主要内容,如果未能解决你的问题,请参考以下文章

Android 逆向Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )

Android 逆向Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )

android 21 是啥版本

Android逆向-Android基础逆向(2-2)

【Android笔记】android Toast

图解Android - Android核心机制