协调子碎片/活动中的浮动操作按钮行为

时间:2015-04-04 10:29:18

标签: android android-viewpager android-recyclerview floating-action-button

我有一个问题,协调Activity中浮动操作按钮的行为及其子项。

在我的应用中,我有一个Activity,其中包含ViewPagerxml定义的FloatingActionMenu ViewPagerFragments包含灵活数量的Fragment,每个RecyclerView内部都是FloatingActionMenu

点击后,ViewPager展开为两个按钮 - 一个向RecyclerView添加额外的页面/片段,另一个向页面上的ViewPager添加一行。用户当前正在addOnItemTouchListener。此功能有效。

要隐藏按钮,我会将RecyclerView用于我的子片段中的OnInterceptTouchEvent。然后,在Interface中,如果滑动手势足够大,我会使用自定义Activity将事件转发回托管public class Categories extends ActionBarActivity implements View.OnClickListener, FloatingButtonInterface{ //... // Final parameter is for the custom Interface mAdapter = new CategoriesViewPagerAdapter(mFragmentManager, allCategoriesCursor, this); mViewPager = (ViewPager) findViewById(R.id.categories_view_pager_pager); mViewPager.setAdapter(mAdapter); menuOriginalXPos = mFloatingActionsMenu.getX(); menuOriginalYPos = mFloatingActionsMenu.getY(); //... // onTouchEvent is the imaginative name for my custom Interface method. @Override public void onTouchEvent(int callBackID) { if (callBackID == FloatingButtonInterface.MOTION_DOWN){ if (mFloatingActionsMenu.getVisibility() == View.GONE) { Animation translate = new TranslateAnimation( menuOriginalXPos, menuOriginalXPos, mViewPager.getHeight(), menuOriginalYPos); translate.setDuration(250); translate.setInterpolator(new LinearInterpolator()); mFloatingActionsMenu.startAnimation(translate); mFloatingActionsMenu.setEnabled(true); mFloatingActionsMenu.setVisibility(View.VISIBLE); } } else if (callBackID == FloatingButtonInterface.MOTION_UP) { if (mFloatingActionsMenu.getVisibility() == View.VISIBLE) { Animation translate = new TranslateAnimation( menuOriginalXPos, menuOriginalXPos, menuOriginalYPos, mViewPager.getHeight()); translate.setDuration(250); translate.setInterpolator(new LinearInterpolator()); mFloatingActionsMenu.startAnimation(translate); mFloatingActionsMenu.setEnabled(false); mFloatingActionsMenu.setVisibility(View.GONE); } } } ,托管public interface FloatingButtonInterface { public static final int MOTION_UP = 4; public static final int MOTION_DOWN = MOTION_UP+1; public static final int MOTION_NONE = 0; public void onTouchEvent(int callBackID); } 会隐藏或显示按钮。以下是我的一些代码:

ViewPager

这是我非常直接的界面:

public class CategoriesViewPagerAdapter extends FragmentStatePagerAdapter {

private static final String LOG_TAG = "CategoriesViewPagerAd";

private Cursor mCursor;
private FloatingButtonInterface hideMenuInterface;
private FragmentManager mFragmentManager;
private boolean refreshItem = false;

public CategoriesViewPagerAdapter(FragmentManager fm, Cursor data, FloatingButtonInterface hideMenuInterface) {
    super(fm);
    mCursor = data;
    mFragmentManager = fm;
    this.hideMenuInterface = hideMenuInterface;
}

@Override
public Fragment getItem(int i) {
    mCursor.moveToPosition(i);
    int categoryFragmentIdentifier =
            mCursor.getInt(mCursor.getColumnIndex(FilesDatabaseHelper.KEY_ID));
    CategoryFragment frag = CategoryFragment.newInstance(categoryFragmentIdentifier);
    frag.setOnTouchEvent(hideMenuInterface);
    return frag;
}

ViewPager内:

Fragment

最后,public class CategoryFragment extends Fragment implements RecyclerView.OnItemTouchListener, View.OnClickListener{ //... private static final int TOUCH_SLOP=200; //... static CategoryFragment newInstance(int categoryIdentifier){ CategoryFragment frag = new CategoryFragment(); Bundle bundle = new Bundle(); bundle.putInt(CATEGORY_ID, categoryIdentifier); frag.setArguments(bundle); return frag; } //... @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); mRecyclerView.addOnItemTouchListener(this); //... @Override public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { switch (e.getAction()){ case MotionEvent.ACTION_DOWN: originalFingerPos = e.getY(); break; case MotionEvent.ACTION_MOVE: if (e.getY() - originalFingerPos > TOUCH_SLOP){ if (hideMenuInterface != null) { hideMenuInterface.onTouchEvent(FloatingButtonInterface.MOTION_DOWN); } else { Log.e(LOG_TAG, "hideMenuInterface is null"); } } else if (e.getY() + TOUCH_SLOP < originalFingerPos ){ if (hideMenuInterface != null) { hideMenuInterface.onTouchEvent(FloatingButtonInterface.MOTION_UP); } else { Log.e(LOG_TAG, "hideMenuInterface is null"); } } } return false; } Fragments之一:

LogCat

我遇到的主要问题与用户在配置更改后在屏幕上向上或向下滑动时自动隐藏按钮的代码有关。如果我在测试设备上更改屏幕方向,当我尝试通过滑动隐藏按钮时,某些hideMenuInterface不会响应,当我检查null时,我可以看到{{1}} 1}}是{{1}}。我该怎么做才能解决这个问题?为什么它只影响一些片段而不是所有片段?如果我在ViewPager中滑动到最后一个片段然后再返回,问题就解决了 - 可能是因为片段已经重新创建。

感谢您提供的任何见解!我只包括我觉得相关的代码,否则会有页面,但请问你是否认为其他任何东西都有帮助。

1 个答案:

答案 0 :(得分:1)

我在Android Developer docs找到了这个问题的答案。按照此页面上的说明操作后,按钮行为更加可靠。


修改

为了扩展我以前的答案,我以下列方式应用文档中的信息:

我通过添加名为CategoryFragment的内部ViewPager并为interface分配值来更改FloatingButtonInterface(占据每个FloatingButtonInterface项目的片段) onAttach()期间的变量:

public class CategoryFragment extends Fragment implements RecyclerView.OnItemTouchListener {
//...
    private static final int TOUCH_SLOP = 200;
    private FloatingButtonInterface floatingButtonInterface;
//...
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        floatingButtonInterface = (FloatingButtonInterface) activity;
    }
//...
    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        switch (e.getAction()) {
            case MotionEvent.ACTION_DOWN:
                originalFingerPos = e.getY();
                return false;
            case MotionEvent.ACTION_MOVE:
                if (e.getY() - originalFingerPos > TOUCH_SLOP) {
                    floatingButtonInterface.onTouchEvent(FloatingButtonInterface.MOTION_DOWN);
                    return false;
                } else if (e.getY() + TOUCH_SLOP < originalFingerPos) {
                    floatingButtonInterace.onTouchEvent(FloatingButtonInterface.MOTION_UP);
                    return false;
                }
                return false;
            }
            return false;
        }
//...
public interface FloatingButtonInterface {

    public static final int MOTION_UP = MOTION_NONE + 4;
    public static final int MOTION_DOWN = MOTION_UP + 1;
    public static final int MOTION_NONE = 0;

    public void onTouchEvent(int callBackId);
}

唯一的其他变化是在ViewPagerAdapter内。由于CategoryFragment负责分配接口,因此可以删除适配器中与此相关的任何代码,以便适配器现在看起来像:

public class CategoriesViewPagerAdapter extends FragmentStatePagerAdapter {

private static final String LOG_TAG = "CategoriesViewPagerAd";

private Cursor mCursor;
private FloatingButtonInterface hideMenuInterface;
private FragmentManager mFragmentManager;
private boolean refreshItem = false;

public CategoriesViewPagerAdapter(FragmentManager fm, Cursor data) {
    super(fm);
    mCursor = data;
    mFragmentManager = fm;
}

@Override
public Fragment getItem(int i) {
    mCursor.moveToPosition(i);
    int categoryFragmentIdentifier =
            mCursor.getInt(mCursor.getColumnIndex(FilesDatabaseHelper.KEY_ID));
    CategoryFragment frag = CategoryFragment.newInstance(categoryFragmentIdentifier);
    return frag;
}