跨儿童片段/活动协调浮动操作按钮行为

问题描述:

我有一个问题协调活动中的浮动操作按钮及其子项的行为。跨儿童片段/活动协调浮动操作按钮行为

在我的应用程序,我有一个Activity其容纳ViewPager并与following library构造的xml定义FloatingActionMenuViewPager包含灵活号码Fragments,并且每个Fragment内部是RecyclerView

当点击,FloatingActionMenu扩展到两个按钮 - 一个增加了额外的页/分片到ViewPager,另增加了一个额外的行到RecyclerViewViewPager的页面上的用户当前所在。此功能有效。

要隐藏按钮,我在我的子片段中使用addOnItemTouchListenerRecyclerView。然后,在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; 
} 

最后,ViewPagerFragment S的一个:

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时,我可以看到hideMenuInterfacenull。我能做些什么来解决这个问题?它为什么只影响一些碎片而不影响全部碎片?如果我滑动到ViewPager中的最后一个片段,然后再回来,问题已经解决 - 可能是因为片段已被重新创建。

感谢您提供的任何见解!我只包含了我认为相关的代码,否则会出现页面,但请询问您是否认为其他任何内容都有帮助。

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


编辑:

为了扩大对我以前的答案,我申请从文档中的下列方式中的信息:我改变CategoryFragment(占据每个ViewPager项目的片段)

通过添加称为FloatingButtonInterface的内部interface,并在onAttach()期间为FloatingButtonInterface变量赋值:

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; 
} 
+1

您还可以添加这也解释了answer.It会帮助别人的答案到达这里。 – Droidekas 2015-09-03 16:34:38

+0

@Droidekas公平点。我编辑了我的答案以添加更多信息。 – PPartisan 2015-09-04 09:29:15