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
布局中删除ListView
和GridView
的ViewStub
。
// 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. 而不是ListView
和GridView
,只使用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
类中,添加两个布局管理器(LinearLayoutManager
和GridLayoutManager
)。
如果您想显示
List
,请使用LinearLayoutManager
和 对于Grid
使用GridLayoutManager
和RecyclerView
。通过调用方法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
代替ListView
和GridView
。当我从activity_main.xml
中的STEP 1
中删除ListView
和GridView
因此,为了显示列表和网格,我在first_fragment.xml
中添加了RecyclerView
。正如我在STEP 3 and 4
中所述,您必须使用Adapter
来表示RecyclerView
和两个LayoutManager
。主要是根据您的需要在任何片段上显示列表/网格。见附件教程链接,了解RecyclerView
和Fragment
的使用。
你没有提到必须为片段创建一个适配器类,在这种情况下有必要吗? (如视频教程所示)
我在 STEP 4 中提到过。Add an RecyclerView.Adapter to populate your data on RecyclerView.
。按照教程为 RecyclerView 创建适配器。
感谢您接受我的回答。如果它看起来有用,我希望你也投赞成票。谢谢~【参考方案2】:
你应该在你的stub_list
和stub_list
ViewStub xml 声明中添加这行代码app:layout_behavior="@string/appbar_scrolling_view_behavior"
,它应该直接位于应用栏下方;您可以在 CoordinatorLayout 和应用栏部分
【讨论】:
我已经在 MainActivity.xml 中的两个 ViewStub 中添加了上面的行,但是没有任何改变。以上是关于Android:MainActivity/Fragment 中的 ListView / GridView 重叠工具栏的主要内容,如果未能解决你的问题,请参考以下文章
Android 逆向Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )
Android 逆向Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )