我使用BottomSheet
方法实施了DialogFragment
。我在TabLayout
中有ViewPager
和BottomSheet
。 ViewPager
正在托管2个页面,每个页面都会膨胀RecyclerView
。第一个(咖啡标签)RecyclerView
滚动正常。我现在遇到的问题是,对于第二个(Milk选项卡),滚动不起作用。知道我该如何解决这个问题?谢谢!
您可以使用我在此处创建的演示项目进行测试:https://github.com/choongyouqi/bottomsheet`
答案 0 :(得分:7)
如R.Zagórski所述,我描述了这种滚动行为here的原因,即BottomSheetBehavior
仅支持一个滚动子项。然而,这个答案并没有集中在底部对话框上。
因此 - 就像R.Zagórski一样 - 我扩展了自己的library,克服了这个限制。 从 0.0.3 开始,支持底部对话框!您可以在此处找到库和示例应用程序: https://github.com/laenger/ViewPagerBottomSheet
要在项目中使用,只需将maven repo url添加到build.gradle:
repositories {
maven { url "https://raw.github.com/laenger/maven-releases/master/releases" }
}
将库添加到依赖项:
dependencies {
compile "biz.laenger.android:vpbs:0.0.3"
}
使用ViewPagerBottomSheetDialogFragment
作为Dialog Fragments的超类。然后在内容视图中设置任何ViewPager:
public class DialogFragment extends ViewPagerBottomSheetDialogFragment {
@Override
public void setupDialog(Dialog dialog, int style) {
super.setupDialog(dialog, style);
final View contentView = View.inflate(getContext(), R.layout.dialog_bottom_sheet, null);
final ViewPager viewPager = (ViewPager) contentView.findViewById(R.id.viewpager);
// ...
BottomSheetUtils.setupViewPager(viewPager);
dialog.setContentView(contentView);
}
}
答案 1 :(得分:4)
尝试在StackOverflow上查找问题时,我找到了this thread。它描述了错误(至少我是如何看待它),BottomSheetBehaviour
仅适用于它找到的第一个可滚动子项。它还建议使用不同的CoordinatorLayout.Behavior
提议和发布的here。
但是,你的情况有点不同。使用BottomSheetDialogFragment
。这就是提供的解决方案不起作用的地方。但是我设法解决了这个问题。已发布repository,您的项目已修改为正常运行。它使用前面提到的库中的ViewPagerBottomSheetBehavior
。
基本上,进行了以下更改:
StatisticFragment
延伸ViewPagerBottomSheetDialogFragment
而非BottomSheetDialogFragment
StatisticsFragment
中的onCreateDialog函数已更改:
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
ViewPagerBottomSheetDialog dialog = (ViewPagerBottomSheetDialog) super.onCreateDialog(savedInstanceState);
View rootView = View.inflate(getContext(), R.layout.sheet_main, null);
viewPager = (ViewPager) rootView.findViewById(R.id.viewpager);
tabLayout = (TabLayout) rootView.findViewById(R.id.tabs);
dialog.setContentView(rootView);
mBehavior = ViewPagerBottomSheetBehavior.from((View) rootView.getParent());
mBehavior.setPeekHeight(400);
if (viewPager != null && tabLayout != null) {
initViewPager();
}
return dialog;
}
在ViewPager
:
BottomSheetUtils.setupViewPager(viewPager);
就是这样。该项目有效。
以下是在幕后完成的:
BottomSheetDialogFragment
只有一种方法:
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new BottomSheetDialog(getContext(), getTheme());
}
返回BottomSheetDialog
。但是,它将静态定义的行为设置为BottomSheetBehavior
。我们需要的是覆盖ViewPagerBottomSheetDialogFragment
以返回ViewPagerBottomSheetDialog
,其中CoordinatorLayout.Behavior
设置为ViewPagerBottomSheetBehavior
。此外,还需要覆盖自定义BottomSheet
以适应ViewPagerBottomSheetBehavior
。
答案 2 :(得分:4)
将此视图用作根视图:
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.LinearLayout;
public class DisallowInterceptView extends LinearLayout {
public DisallowInterceptView(Context context) {
super(context);
requestDisallowInterceptTouchEvent(true);
}
public DisallowInterceptView(Context context, AttributeSet attrs) {
super(context, attrs);
requestDisallowInterceptTouchEvent(true);
}
public DisallowInterceptView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
requestDisallowInterceptTouchEvent(true);
}
public boolean dispatchTouchEvent(MotionEvent ev) {
getParent().requestDisallowInterceptTouchEvent(true);
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
requestDisallowInterceptTouchEvent(false);
break;
}
return super.onTouchEvent(event);
}
}
然后在您的布局中用于bottmSheet:
<?xml version="1.0" encoding="utf-8"?>
<com.your.package.DisallowInterceptView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:maxHeight="400dp"
android:minHeight="300dp"
android:orientation="vertical"
>
...
</LinearLayout>
</com.your.package.DisallowInterceptView>
答案 3 :(得分:1)
您可以在CoordinatorLayout中使用2 RecyclerView。
<android.support.design.widget.CoordinatorLayout
android:id="@+id/mainBottomSheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerViewRight"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerViewLeft"
android:layout_width="200dp"
android:layout_height="match_parent" />
</android.support.design.widget.CoordinatorLayout>
查看此帖子link
答案 4 :(得分:1)
我遇到了同样的问题,无需覆盖BottomSheetBehavior或需要其他库即可解决此问题,您可以执行以下操作: 在您的底层工作表实现中实现一个回调,用于注册页面更改。
fun onPageChanged(currentPage: Int) {
recycler1.isNestedScrollingEnabled = currentPage == 0
recycler2.isNestedScrollingEnabled = currentPage == 1
dialog?.findViewById<FrameLayout>(R.id.design_bottom_sheet)?.requestLayout()
}
在onLayoutChild的BottomSheetBehavior实现中,将执行对第一个支持嵌套滚动的子级的查找,此更改将重复进行。不是最佳解决方案,但在我的情况下效果很好
答案 5 :(得分:0)
您无需将StatisticFragment
扩展为ViewPagerBottomSheetDialogFragment
,也无需使用任何库。
您的代码我刚刚对与Static Fragment
相关的View Pager.
进行了一些更改
以下是我已进行更改的Statistic Fragment
。
以上所有答案中都没有任何错误。
将此代码替换为您的旧Static fragment
,而不是任何其他更改,它会为您提供所需的输出。
我刚刚对您的View Pager
进行了更改,并使其按您的意愿运行。
使用OnPageChangeListener
方法获取该视图。
统计Fragment.java
public class StatisticFragment extends BottomSheetDialogFragment {
private BottomSheetBehavior mBehavior;
private TabLayout tabLayout;
private ViewPager viewPager;
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
View rootView = View.inflate(getContext(), R.layout.sheet_main, null);
viewPager = (ViewPager) rootView.findViewById(R.id.viewpager);
tabLayout = (TabLayout) rootView.findViewById(R.id.tabs);
if (viewPager != null && tabLayout != null) {
initViewPager();
}
final ViewPager.OnPageChangeListener pageChangeListener = new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int arg0) {
// TODO Auto-generated method stub
View view = viewPager.findViewWithTag(arg0);
if (view == null) {
return;
}
CustomPagerAdapter adapter = new CustomPagerAdapter(getContext());
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(10);
tabLayout.setupWithViewPager(viewPager);
}
@Override
public void onPageScrollStateChanged(int state) {
}
};
viewPager.addOnPageChangeListener(pageChangeListener);
viewPager.post(new Runnable() {
@Override
public void run() {
pageChangeListener.onPageSelected(viewPager.getCurrentItem());
}
});
dialog.setContentView(rootView);
mBehavior = BottomSheetBehavior.from((View) rootView.getParent());
return dialog;
}
private void initViewPager() {
CustomPagerAdapter adapter = new CustomPagerAdapter(getContext());
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(10);
tabLayout.setupWithViewPager(viewPager);
}
@Override
public void onStart() {
super.onStart();
//mBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
//mBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
public class ServiceVideHolder extends RecyclerView.ViewHolder {
protected ViewGroup mItemView;
protected TextView mNameView;
protected TextView mCodeView;
public ServiceVideHolder(View v) {
super(v);
//rootView = v;
mItemView = (ViewGroup) v.findViewById(R.id.item);
mNameView = (TextView) v.findViewById(R.id.main_text);
mCodeView = (TextView) v.findViewById(R.id.sub_text);
}
}
public class ItemViewHolder extends RecyclerView.ViewHolder {
protected TextView mMainText;
protected TextView mSubText;
public ItemViewHolder(View v) {
super(v);
mMainText = (TextView) v.findViewById(R.id.main_text);
mSubText = (TextView) v.findViewById(R.id.sub_text);
}
}
public class ItemAdapter extends RecyclerView.Adapter<ItemViewHolder> {
private List<Item> items;
public ItemAdapter(List<Item> items) {
this.items = items;
}
@Override
public ItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
return new ItemViewHolder(view);
}
@Override
public void onBindViewHolder(final ItemViewHolder viewHolder, final int position) {
final Item item = items.get(position);
viewHolder.mMainText.setText(item.name);
viewHolder.mSubText.setText(item.value);
viewHolder.mMainText.setTextColor(ResourcesCompat.getColor(getResources(), position % 2 == 0 ? R.color.md_red_500 : R.color.md_blue_500, null));
}
@Override
public int getItemCount() {
return items.size();
}
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
public void addFrag(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
@Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
public class CustomPagerAdapter extends PagerAdapter {
private Context mContext;
public CustomPagerAdapter(Context context) {
mContext = context;
}
@Override
public Object instantiateItem(ViewGroup collection, int position) {
//CustomPagerEnum customPagerEnum = CustomPagerEnum.values()[position];
LayoutInflater inflater = LayoutInflater.from(mContext);
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.adapter, collection, false);
rootView.setTag(position);
Toast.makeText(mContext, "Inside Instanciate Item", Toast.LENGTH_SHORT).show();
//View rootView = View.inflate(getContext(), R.layout.adapter, null);
final RecyclerView mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
ArrayList<Item> items = new ArrayList<>();
if (position == 0) {
items.add(new Item("Coffee 1", "1"));
items.add(new Item("Coffee 2", "2"));
items.add(new Item("Coffee 3", "3"));
items.add(new Item("Coffee 4", "4"));
items.add(new Item("Coffee 5", "5"));
items.add(new Item("Coffee 6", "6"));
items.add(new Item("Coffee 7", "7"));
items.add(new Item("Coffee 8", "8"));
items.add(new Item("Coffee 9", "9"));
items.add(new Item("Coffee 10", "10"));
} else {
items.add(new Item("Milk 1", "1"));
items.add(new Item("Milk 2", "2"));
items.add(new Item("Milk 3", "3"));
items.add(new Item("Milk 4", "4"));
items.add(new Item("Milk 5", "5"));
items.add(new Item("Milk 6", "6"));
items.add(new Item("Milk 7", "7"));
items.add(new Item("Milk 8", "8"));
items.add(new Item("Milk 9", "9"));
items.add(new Item("Milk 10", "10"));
}
final ItemAdapter mAdapter = new ItemAdapter(items);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
mRecyclerView.setNestedScrollingEnabled(false);
mRecyclerView.setAdapter(mAdapter);
Paint paint = new Paint();
paint.setStrokeWidth(1);
paint.setColor(ResourcesCompat.getColor(getResources(), R.color.md_grey_500, null));
paint.setAntiAlias(true);
paint.setPathEffect(new DashPathEffect(new float[]{25.0f, 25.0f}, 0));
mRecyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getActivity()).showLastDivider().paint(paint).build()); //.marginResId(R.dimen.leftmargin, R.dimen.rightmargin)
collection.addView(rootView);
return rootView;
}
@Override
public void destroyItem(ViewGroup collection, int position, Object view) {
collection.removeView((View) view);
}
@Override
public int getCount() {
return 2;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public CharSequence getPageTitle(int position) {
//CustomPagerEnum customPagerEnum = CustomPagerEnum.values()[position];
return position == 0 ? "Coffee" : "Milk";
}
}
}
已完成。