我有一个问题,协调Activity中浮动操作按钮的行为及其子项。
在我的应用中,我有一个Activity
,其中包含ViewPager
和xml
定义的FloatingActionMenu
ViewPager
。 Fragments
包含灵活数量的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中滑动到最后一个片段然后再返回,问题就解决了 - 可能是因为片段已经重新创建。
感谢您提供的任何见解!我只包括我觉得相关的代码,否则会有页面,但请问你是否认为其他任何东西都有帮助。
答案 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;
}