在导航抽屉项目单击时,导航抽屉中的新列表视图
Posted
技术标签:
【中文标题】在导航抽屉项目单击时,导航抽屉中的新列表视图【英文标题】:On navigation drawer item click, new list view in navigation drawer 【发布时间】:2015-09-15 05:38:42 【问题描述】:我试图在导航抽屉中获得以下功能,但我无法打破它。
场景:-
我有一个导航抽屉。单击导航抽屉中的任何项目时,我需要打开一个列表视图,其中包含多个项目,可以进一步选择它以实现某种功能。 我还附上了图像,它将以适当的方式定义我的需求。请提供图片的参考以获得我基本上和实际需要的东西。
任何帮助将不胜感激..!
【问题讨论】:
你为什么不想使用ExpandableListView
?这将是您想要的最佳实践。
您没有提到您的场景中没有发生什么问题?你想要右边的城市列表吗?或者您想要扩展菜单列表?请多解释
最坏情况的解决方案是,使用两个具有线性布局方向的列表视图作为水平方向,并根据要求设置可见性可见和消失。但我想建议你使用 rom4ek 解决方案。
您可以发布您的代码吗?
【参考方案1】:
正如我看到你的图片,我理解的是,从你的抽屉里点击你想要另一个列表出现在它的右边。我说的对吗? 如果我更正,那么无法使用 ExpandableListView,因为 ExpandableListView 会在点击的项目下方生成项目。
所以一种解决方案是你可以取两个ListView。
抽屉内的第一个 ListView 和 主要内容上的第二个,并为这两个 ListView 创建自定义适配器。
现在当用户单击抽屉列表项时,确定单击了哪个选项,例如 City、MyNews 或其他。
确定点击后,您可以根据用户点击的选项为第二个 ListView 填充适配器。并将该适配器应用于第二个 ListView 并通知它。
所以当用户从抽屉中点击另一个项目时,同样的事情会发生。但是第二个 ListView 的数据会发生变化。
我希望你明白我在说什么,这对你有帮助。
[更新]
好的,所以你的 xml 应该看起来像这样。
注意:我只是为此写一个骨架。
<!-- The main content view -->
<FrameLayout android:id="@+id/content_frame" />
<!-- The navigation drawer -->
<LinearLayout
android:layout_gravity="start"
android:orientation="horizontal">
<ListView
android:layout_weight="1"
android:id="@+id/list1">
</ListView>
<ListView
android:layout_weight="1"
android:id="@+id/list2">
</ListView>
</LinearLayout>
现在在您的 java 端。考虑两个列表视图都被引用为 list1 和 list2 ,并且您创建了两个适配器 adapter1 和 adapter2。 p>
使项目点击 list1 并应用如下逻辑...
list1.setOnItemClickListener(new AdapterView.OnItemClickListener()
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int pos, long l)
// now here you can get which option is clicked from list1.
// using position and
int your_type = pos;
adapter2.filderDataAccordingToType(your_type);
// create the above method in your second adapter and pass your type like MyNews, City or any other.
// and apply the logic of filtering by passing type to your method
// your_type could be any data type i have take the integer.
// and after filtering data you can notify your adapter.
// so when the data of adpater gets changed your secondlistview get refreshed.
);
就是这样。 希望对您有所帮助。
【讨论】:
虽然它可能会有所帮助。将带有水平列表视图的线性布局放在抽屉中并休息您的逻辑。如果你能纠正它,请这样做。以便我接受你的回答。 我有点困惑,您希望抽屉上的两个列表视图或抽屉上的一个列表视图和抽屉外的另一个列表视图..?这样我就可以正确更新答案... 但是兄弟,如果您在一个抽屉中并排使用两个列表视图。它将为用户提供更少的空间,这作为 UX 部分不是一个好主意,否则你可以选择它。【参考方案2】:您可以使用creating a navigation drawer 上的 Android 开发者教程,但不要使用 ListView,而是使用ExpandableListView
。
例如,在该教程中,您可以看到在第一个代码块中他们使用了ListView
。取而代之的是,将其更改为以下内容:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_
android:layout_>
<FrameLayout
android:id="@+id/content_frame"
android:layout_
android:layout_ />
<ExpandableListView android:id="@+id/left_drawer"
android:layout_
android:layout_/>
</android.support.v4.widget.DrawerLayout>
Android Hive 上的this 教程很好地解释了如何实现 ExpandableListView 适配器。我不会在这里粘贴他们的代码,因为这是一个很长的教程。如果您有任何问题,请在下方评论。
【讨论】:
【参考方案3】:这是我的代码。
我正在为子项目使用回收站视图。 它正在向下扩展单词。我正在使用 2 个库。
编译'com.h6ah4i.android.widget.advrecyclerview:advrecyclerview:0.7.1' 编译'com.wnafee:vector-compat:1.0.5'
这里是导航抽屉片段
public class NavigationDrawerFragment extends Fragment implements NavigationDrawerCallbacks
private static final String SAVED_STATE_EXPANDABLE_ITEM_MANAGER = "RecyclerViewExpandableItemManager";
/**
* Remember the position of the selected item.
*/
private static final String STATE_SELECTED_POSITION = "selected_navigation_drawer_position";
/**
* Per the design guidelines, you should show the drawer on launch until the user manually
* expands it. This shared preference tracks this.
*/
private static final String PREF_USER_LEARNED_DRAWER = "navigation_drawer_learned";
/**
* A pointer to the current callbacks instance (the Activity).
*/
private NavigationDrawerCallbacks mCallbacks;
/**
* Helper component that ties the action bar to the navigation drawer.
*/
private ActionBarDrawerToggle mActionBarDrawerToggle;
private DrawerLayout mDrawerLayout;
private RecyclerView mDrawerList;
private View mFragmentContainerView;
private int mCurrentSelectedPosition = -1;
private boolean mFromSavedInstanceState;
private boolean mUserLearnedDrawer;
private Subscription subscription;
@Inject CategoryService categoryService;
private MyExpandableItemAdapter expandableItemAdapter;
private RecyclerView.Adapter wrappedAdapter;
private RecyclerViewExpandableItemManager expandableItemManager;
private LinearLayoutManager linearLayoutManager;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
DelhiShopApplication.component().inject(this);
// Read in the flag indicating whether or not the user has demonstrated awareness of the
// drawer. See PREF_USER_LEARNED_DRAWER for details.
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
mUserLearnedDrawer = sp.getBoolean(PREF_USER_LEARNED_DRAWER, false);
if (savedInstanceState != null)
mCurrentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION);
mFromSavedInstanceState = true;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
View view = inflater.inflate(R.layout.fragment_navigation_drawer, container, false);
mDrawerList = (RecyclerView) view.findViewById(R.id.drawerList);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mDrawerList.setLayoutManager(layoutManager);
mDrawerList.setHasFixedSize(true);
if (mCurrentSelectedPosition != -1)
selectItem(mCurrentSelectedPosition);
return view;
@Override
public void onViewCreated(View view, Bundle savedInstanceState)
super.onViewCreated(view, savedInstanceState);
final Parcelable eimSavedState = (savedInstanceState != null) ? savedInstanceState.getParcelable(SAVED_STATE_EXPANDABLE_ITEM_MANAGER) : null;
expandableItemManager = new RecyclerViewExpandableItemManager(eimSavedState);
private void setRecyclerView(Category category)
linearLayoutManager = new LinearLayoutManager(getActivity());
final MyExpandableItemAdapter myItemAdapter = new MyExpandableItemAdapter(category);
wrappedAdapter = expandableItemManager.createWrappedAdapter(myItemAdapter);
final GeneralItemAnimator animator = new RefactoredDefaultItemAnimator();
// Change animations are enabled by default since support-v7-recyclerview v22.
// Need to disable them when using animation indicator.
animator.setSupportsChangeAnimations(false);
mDrawerList.setLayoutManager(linearLayoutManager);
mDrawerList.setAdapter(wrappedAdapter); // requires *wrapped* adapter
mDrawerList.setItemAnimator(animator);
mDrawerList.setHasFixedSize(false);
// additional decorations
//noinspection StatementWithEmptyBody
// if (supportsViewElevation()) // // Lollipop 或更高版本具有原生投影功能。不需要 ItemShadowDecorator。 // 别的 // mDrawerList.addItemDecoration(new ItemShadowDecorator((NinePatchDrawable) getResources().getDrawable(R.drawable) // .material_shadow_z1))); //
expandableItemManager.attachRecyclerView(mDrawerList);
private boolean supportsViewElevation()
return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP);
public boolean isDrawerOpen()
return mDrawerLayout != null && mDrawerLayout.isDrawerOpen(mFragmentContainerView);
public ActionBarDrawerToggle getActionBarDrawerToggle()
return mActionBarDrawerToggle;
public DrawerLayout getDrawerLayout()
return mDrawerLayout;
@Override
public void onNavigationDrawerItemSelected(int position)
selectItem(position);
/**
* Users of this fragment must call this method to set up the navigation drawer interactions.
*
* @param fragmentId The android:id of this fragment in its activity's layout.
* @param drawerLayout The DrawerLayout containing this fragment's UI.
* @param toolbar The Toolbar of the activity.
*/
public void setup(int fragmentId, DrawerLayout drawerLayout, Toolbar toolbar)
mFragmentContainerView = (View) getActivity().findViewById(fragmentId).getParent();
mDrawerLayout = drawerLayout;
mDrawerLayout.setStatusBarBackgroundColor(getResources().getColor(R.color.myPrimaryDarkColor));
mActionBarDrawerToggle = new ActionBarDrawerToggle(getActivity(), mDrawerLayout, toolbar, R.string
.drawer_open, R.string.drawer_close)
@Override
public void onDrawerClosed(View drawerView)
super.onDrawerClosed(drawerView);
if (!isAdded())
return;
getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
@Override
public void onDrawerOpened(View drawerView)
super.onDrawerOpened(drawerView);
if (!isAdded())
return;
if (!mUserLearnedDrawer)
mUserLearnedDrawer = true;
SharedPreferences sp = PreferenceManager
.getDefaultSharedPreferences(getActivity());
sp.edit().putBoolean(PREF_USER_LEARNED_DRAWER, true).apply();
getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
;
// If the user hasn't 'learned' about the drawer, open it to introduce them to the drawer,
// per the navigation drawer design guidelines.
if (!mUserLearnedDrawer && !mFromSavedInstanceState)
mDrawerLayout.openDrawer(mFragmentContainerView);
// Defer code dependent on restoration of previous instance state.
mDrawerLayout.post(new Runnable()
@Override
public void run()
mActionBarDrawerToggle.syncState();
);
mDrawerLayout.setDrawerListener(mActionBarDrawerToggle);
private void selectItem(int position)
mCurrentSelectedPosition = position;
if (mDrawerLayout != null)
mDrawerLayout.closeDrawer(mFragmentContainerView);
if (mCallbacks != null)
mCallbacks.onNavigationDrawerItemSelected(position);
((NavigationDrawerAdapter) mDrawerList.getAdapter()).selectPosition(position);
public void openDrawer()
mDrawerLayout.openDrawer(mFragmentContainerView);
public void closeDrawer()
mDrawerLayout.closeDrawer(mFragmentContainerView);
@Override
public void onAttach(Activity activity)
super.onAttach(activity);
try
mCallbacks = (NavigationDrawerCallbacks) activity;
catch (ClassCastException e)
throw new ClassCastException("Activity must implement NavigationDrawerCallbacks.");
@Override
public void onDetach()
super.onDetach();
mCallbacks = null;
@Override
public void onSaveInstanceState(Bundle outState)
super.onSaveInstanceState(outState);
outState.putInt(STATE_SELECTED_POSITION, mCurrentSelectedPosition);
if (expandableItemManager != null)
outState.putParcelable(
SAVED_STATE_EXPANDABLE_ITEM_MANAGER,
expandableItemManager.getSavedState());
@Override
public void onConfigurationChanged(Configuration newConfig)
super.onConfigurationChanged(newConfig);
// Forward the new configuration the drawer toggle component.
mActionBarDrawerToggle.onConfigurationChanged(newConfig);
public void setUserData(String user, String email, Bitmap avatar)
((TextView) mFragmentContainerView.findViewById(R.id.txtUserEmail)).setText(email);
((TextView) mFragmentContainerView.findViewById(R.id.txtUsername)).setText(user);
public View getGoogleDrawer()
return mFragmentContainerView.findViewById(R.id.googleDrawer);
@Override
public void onResume()
super.onResume();
subscription = categoryService.getCategories()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Category>()
@Override
public void call(Category category)
// sadfksdjf
expandableItemAdapter = new MyExpandableItemAdapter(category);
mDrawerList.setAdapter(expandableItemAdapter);
setRecyclerView(category);
, new Action1<Throwable>()
@Override
public void call(Throwable throwable)
// slkdfj
);
@Override
public void onPause()
subscription.unsubscribe();
super.onPause();
@Override
public void onDestroyView()
super.onDestroyView();
if (expandableItemManager != null)
expandableItemManager.release();
expandableItemManager = null;
这是我的可扩展项目适配器
public class MyExpandableItemAdapter
extends AbstractExpandableItemAdapter<MyExpandableItemAdapter.MyGroupViewHolder, MyExpandableItemAdapter.MyChildViewHolder>
private static final String TAG = "MyExpandableItemAdapter";
private Category category;
public static abstract class MyBaseViewHolder extends AbstractExpandableItemViewHolder
public ViewGroup mContainer;
public View mDragHandle;
public TextView mTextView;
public MyBaseViewHolder(View v)
super(v);
mContainer = (ViewGroup) v.findViewById(R.id.container);
mDragHandle = v.findViewById(R.id.drag_handle);
mTextView = (TextView) v.findViewById(android.R.id.text1);
// hide the drag handle
mDragHandle.setVisibility(View.GONE);
public static class MyGroupViewHolder extends MyBaseViewHolder
public MorphButtonCompat mMorphButton;
public MyGroupViewHolder(View v)
super(v);
mMorphButton = new MorphButtonCompat(v.findViewById(R.id.indicator));
public static class MyChildViewHolder extends MyBaseViewHolder
public MyChildViewHolder(View v)
super(v);
public MyExpandableItemAdapter(Category dataProvider)
category = dataProvider;
// ExpandableItemAdapter requires stable ID, and also
// have to implement the getGroupItemId()/getChildItemId() methods appropriately.
setHasStableIds(true);
@Override
public int getGroupCount()
return category.getSubCategorySize();
@Override
public int getChildCount(int groupPosition)
return getGroupCategoryAtPosition(groupPosition).getSubCategorySize();
@Override
public long getGroupId(int groupPosition)
return groupPosition;
@Override
public long getChildId(int groupPosition, int childPosition)
return groupPosition * 100 + childPosition;
@Override
public int getGroupItemViewType(int groupPosition)
return 0;
@Override
public int getChildItemViewType(int groupPosition, int childPosition)
return 0;
@Override
public MyGroupViewHolder onCreateGroupViewHolder(ViewGroup parent, int viewType)
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
final View v = inflater.inflate(R.layout.list_group_item, parent, false);
return new MyGroupViewHolder(v);
@Override
public MyChildViewHolder onCreateChildViewHolder(ViewGroup parent, int viewType)
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
final View v = inflater.inflate(R.layout.list_item, parent, false);
return new MyChildViewHolder(v);
@Override
public void onBindGroupViewHolder(MyGroupViewHolder holder, int groupPosition, int viewType)
// child item
final Category groupItem = getGroupCategoryAtPosition(groupPosition);
// set text
holder.mTextView.setText(groupItem.getCategoryName());
// mark as clickable
holder.itemView.setClickable(true);
// set background resource (target view ID: container)
final int expandState = holder.getExpandStateFlags();
if ((expandState & RecyclerViewExpandableItemManager.STATE_FLAG_IS_UPDATED) != 0)
int bgResId;
MorphButton.MorphState indicatorState;
if ((expandState & RecyclerViewExpandableItemManager.STATE_FLAG_IS_EXPANDED) != 0)
bgResId = R.drawable.bg_group_item_expanded_state;
indicatorState = MorphButton.MorphState.END;
else
bgResId = R.drawable.bg_group_item_normal_state;
indicatorState = MorphButton.MorphState.START;
holder.mContainer.setBackgroundResource(bgResId);
if (holder.mMorphButton.getState() != indicatorState)
holder.mMorphButton.setState(indicatorState, true);
@Override
public void onBindChildViewHolder(MyChildViewHolder holder, int groupPosition, int childPosition, int viewType)
// group item
final Category childCategory = getChildCategory(groupPosition, childPosition);
// set text
holder.mTextView.setText(childCategory.getCategoryName());
// set background resource (target view ID: container)
int bgResId;
bgResId = R.drawable.bg_item_normal_state;
holder.mContainer.setBackgroundResource(bgResId);
@Override
public boolean onCheckCanExpandOrCollapseGroup(MyGroupViewHolder holder, int groupPosition, int x, int y, boolean expand)
Category groupCategory = getGroupCategoryAtPosition(groupPosition);
if (groupCategory.getSubCategorySize() == 0)
return false;
// check is enabled
if (!(holder.itemView.isEnabled() && holder.itemView.isClickable()))
return false;
final View containerView = holder.mContainer;
final View dragHandleView = holder.mDragHandle;
final int offsetX = containerView.getLeft() + (int) (ViewCompat.getTranslationX(containerView) + 0.5f);
final int offsetY = containerView.getTop() + (int) (ViewCompat.getTranslationY(containerView) + 0.5f);
return !hitTest(dragHandleView, x - offsetX, y - offsetY);
private Category getGroupCategoryAtPosition(int groupPosition)
return category.getSubCategory().get(groupPosition);
private Category getChildCategory(int groupPosition, int childPosition)
return getGroupCategoryAtPosition(groupPosition).getSubCategory().get(childPosition);
public static boolean hitTest(View v, int x, int y)
final int tx = (int) (ViewCompat.getTranslationX(v) + 0.5f);
final int ty = (int) (ViewCompat.getTranslationY(v) + 0.5f);
final int left = v.getLeft() + tx;
final int right = v.getRight() + tx;
final int top = v.getTop() + ty;
final int bottom = v.getBottom() + ty;
return (x >= left) && (x <= right) && (y >= top) && (y <= bottom);
这是我的 list_group_item.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
style="@style/commonListItemStyle"
android:layout_
android:layout_
android:layout_marginTop="8dp"
android:background="#ffffff">
<RelativeLayout
android:id="@+id/container"
android:layout_
android:layout_
android:clickable="true"
tools:ignore="UselessParent">
<View
android:id="@+id/drag_handle"
android:layout_
android:layout_
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:background="#20000000"
tools:ignore="RtlHardcoded" />
<TextView
android:id="@android:id/text1"
android:layout_
android:layout_
android:layout_toRightOf="@id/drag_handle"
android:gravity="center" />
</RelativeLayout>
</FrameLayout>
list_item.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
style="@style/commonListItemStyle"
android:layout_
android:layout_
android:background="@drawable/bg_swipe_item_neutral">
<RelativeLayout
android:id="@+id/container"
android:layout_
android:layout_
android:clickable="true"
tools:ignore="UselessParent">
<View
android:id="@+id/drag_handle"
android:layout_
android:layout_
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:background="#20000000" />
<TextView
android:id="@android:id/text1"
android:layout_
android:layout_
android:layout_toRightOf="@id/drag_handle"
android:gravity="center"
tools:ignore="RtlHardcoded" />
</RelativeLayout>
</FrameLayout>
【讨论】:
以上是关于在导航抽屉项目单击时,导航抽屉中的新列表视图的主要内容,如果未能解决你的问题,请参考以下文章