zoukankan      html  css  js  c++  java
  • Android 解决下拉刷新控件和ScrollVIew的滑动冲突问题。

    最近项目要实现ScrollView中嵌套广告轮播图+RecyleView卡片布局,并且RecyleView按照header和内容的排列样式,因为RecyleView的可扩展性很强,所以我毫无疑问的选择了它,而且让RecyleView实现了可拖拽的效果,

    最后我再加上了下拉刷新的效果(这里我用的下拉刷新控件是三方的SmartRefreshLayout)。记得刚开始实现这个效果的时候还是十分的得心印手。可是当我测试的时候,发现RecyleView的子item的拖拽效果并不流畅,起初我以

    为是由于RecyleView和ScrollView的滑动冲突导致的,可是慢慢我自己重新写了个demo,逐步调试,发现肯定是下拉刷新控件和ScrollView的原因造成的,于是对症下药,终于找到了解决的办法,这里将我的答案记录下来,为了

    后面其他的人遇到和我一样的问题,避免他们走很多的弯路,希望会对他们有所帮助,当然把自己遇到问题和解决问题的办法都记录下来,这对自己来说也是一种成长。如果有其他更好的思路,希望给我留言,谢谢。

     解决办法一:

            在布局页面中把ScrollView控件换成NestedScrollView控件:

            对NestedScrollView的详解:http://www.cnblogs.com/skytwo/p/4613912.html

        
      <android.support.v4.widget.NestedScrollView
             android:layout_width="match_parent"
             android:layout_height="match_parent">
     
    
           ..............
    
    </android.support.v4.widget.NestedScrollView>
    以下是简单demo:



    MainActivity:用底部BottomNavigationBar,实现viewpager和fragment连用
    代码:
    public class MainActivity extends AppCompatActivity implements BottomNavigationBar.OnTabSelectedListener,ViewPager.OnPageChangeListener{
        private ViewPager viewPager;
        private BottomNavigationBar bottomNavigationBar;
    
        //存放fragment的集合
        private Fragment[] fragments;
    
        //切换不同fragment用的下标
        private int index;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initBottomNavigationBar();
            initViewPager();
    
        }
        //初始化底部导航菜单
        private void initBottomNavigationBar() {
            bottomNavigationBar = (BottomNavigationBar) findViewById(R.id.bottom_navigation_bar);
            bottomNavigationBar.setTabSelectedListener(this);
            bottomNavigationBar.clearAll();
            bottomNavigationBar.setMode(BottomNavigationBar.MODE_FIXED);
            bottomNavigationBar.setBackgroundStyle(BottomNavigationBar.BACKGROUND_STYLE_STATIC);
            bottomNavigationBar.addItem(new BottomNavigationItem(R.drawable.ic_launcher,"主页").setInactiveIconResource(R.drawable.ic_launcher).setActiveColorResource(R.color.colorPrimaryDark))
                    .addItem(new BottomNavigationItem(R.drawable.ic_launcher,"单据").setInactiveIconResource(R.drawable.ic_launcher).setActiveColorResource(R.color.colorPrimaryDark))
                    .addItem(new BottomNavigationItem(R.drawable.ic_launcher, "审核").setInactiveIconResource(R.drawable.ic_launcher).setActiveColorResource(R.color.colorPrimaryDark))
                    .addItem(new BottomNavigationItem(R.drawable.ic_launcher, "报表").setInactiveIconResource(R.drawable.ic_launcher).setActiveColorResource(R.color.colorPrimaryDark))
                    .addItem(new BottomNavigationItem(R.drawable.ic_launcher,"设置").setInactiveIconResource(R.drawable.ic_launcher).setActiveColorResource(R.color.colorPrimaryDark))
                    .initialise();
        }
        //初始化viewpager
        private void initViewPager() {
            viewPager = (ViewPager) findViewById(R.id.view_pager);
            fragments = new Fragment[5];
            fragments[0]=new FragOne();
            fragments[1]=new FragTwo();
            fragments[2]=new FragThree();
            fragments[3]=new FragFour();
            fragments[4]=new FragFive();
    
            viewPager.setOffscreenPageLimit(4);
            viewPager.setAdapter(new SectionsPagerAdapter(getSupportFragmentManager(), fragments));
            viewPager.addOnPageChangeListener(this);
            viewPager.setCurrentItem(0);
    
        }
        @Override
        public void onTabSelected(int position) {
            viewPager.setCurrentItem(position);
        }
    
        @Override
        public void onTabUnselected(int position) {
    
        }
    
        @Override
        public void onTabReselected(int position) {
    
        }
    
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    
        }
    
        @Override
        public void onPageSelected(int i) {
            bottomNavigationBar.selectTab(i);
            this.index = i;
    
    
        }
    
        @Override
        public void onPageScrollStateChanged(int state) {
    
        }
    
         class SectionsPagerAdapter extends FragmentPagerAdapter {
            Fragment fragments[]=new Fragment[4];
    
            public SectionsPagerAdapter(FragmentManager fm, Fragment fragments[]) {
                super(fm);
                this.fragments = fragments;
            }
    
            @Override
            public Fragment getItem(int position) {
                return fragments[position];
            }
    
            @Override
            public int getCount() {
                return fragments.length;
            }
        }
    }
    MainActity布局:
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context="com.example.admin.demo.MainActivity">
    
    
        <android.support.v4.view.ViewPager
            android:id="@+id/view_pager"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            />
        <com.ashokvarma.bottomnavigation.BottomNavigationBar
            android:id="@+id/bottom_navigation_bar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            />
    
    </LinearLayout>
    主fragment:实现下拉刷新、上拉加载、RecyleView拖拽等各种效果的fragment
    public class FragOne extends Fragment implements MyItemTouchCallback.OnDragListener {
        private List<String> list = new ArrayList<String>();
        private View parent;
        //显示模块的recyleview
        private RecyclerView mRecyclerView;
        //可拖动模块的帮助类
        private ItemTouchHelper itemTouchHelper;
        //适配器
        private RecyleViewAdapter mRecyclerAdapter;
    
        //声明刷新控件
        private SmartRefreshLayout srf;
    
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            parent = inflater.inflate(R.layout.frag_one, container, false);
            initView();
            return parent;
        }
        private void initView() {
            for (int i = 0; i < 100; i++) {
                list.add(i + "");
            }
            mRecyclerView = (RecyclerView) parent.findViewById(recyclerView);
    
            // 设置添加删除item的时候的动画效果
            mRecyclerView.setItemAnimator(new DefaultItemAnimator());
    
    
            GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(), 4);
            gridLayoutManager.setSmoothScrollbarEnabled(true);
            gridLayoutManager.setAutoMeasureEnabled(true);
    
            mRecyclerView.setLayoutManager(gridLayoutManager);
            mRecyclerView.setHasFixedSize(true);
            mRecyclerView.setNestedScrollingEnabled(false);
    
    
    
            // 设置适配器
            mRecyclerAdapter = new RecyleViewAdapter(list);
            itemTouchHelper = new ItemTouchHelper(new MyItemTouchCallback(mRecyclerAdapter).setOnDragListener(this));
            itemTouchHelper.attachToRecyclerView(mRecyclerView);
            mRecyclerView.setAdapter(mRecyclerAdapter);
            mRecyclerView.addOnItemTouchListener(new OnRecyclerItemClickListener(mRecyclerView) {
                @Override
                public void onLongClick(RecyclerView.ViewHolder vh) {
                    itemTouchHelper.startDrag(vh);
                    VibratorUtil.Vibrate(getActivity(), 70);   //震动70ms
                }
    
                @Override
                public void onItemClick(RecyclerView.ViewHolder vh) {
                    super.onItemClick(vh);
                }
            });
            srf = (SmartRefreshLayout) parent.findViewById(R.id.refresh);
            srf.setDefaultRefreshHeaderCreater(new DefaultRefreshHeaderCreater() {
                @Override
                public RefreshHeader createRefreshHeader(Context context, RefreshLayout layout) {
                    return new ClassicsHeader(context);//指定为经典Header,默认是 贝塞尔雷达Header
                }
            });
            srf.setOnRefreshListener(new OnRefreshListener() {
                @Override
                public void onRefresh(RefreshLayout refreshlayout) {
                    srf.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            mRecyclerAdapter.notifyDataSetChanged();
    
                            srf.finishRefresh();
                            Toast.makeText(getActivity(), "刷新成功", Toast.LENGTH_SHORT).show();
                        }
                    }, 3000);
                }
            });
            srf.setEnableLoadmore(false);//屏蔽掉上拉加载的效果
    
    
        }
    
        @Override
        public void onFinishDrag() {
    
        }
    
    
        class RecyleViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements MyItemTouchCallback.ItemTouchAdapter {
            private List<String> mData;
    
            public RecyleViewAdapter(List<String> data) {
                mData = data;
            }
    
            @Override
            public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                return new TestViewHolder(View.inflate(parent.getContext(), R.layout.item_test, null));
            }
    
            @Override
            public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
                TestViewHolder tHolder = (TestViewHolder) holder;
                tHolder.tv.setText(mData.get(position));
            }
    
            @Override
            public int getItemCount() {
                return mData == null ? 0 : mData.size();
            }
    
            @Override
            public void onMove(int fromPosition, int toPosition) {
                if (fromPosition < toPosition) {
                    for (int i = fromPosition; i < toPosition; i++) {
                        Collections.swap(mData, i, i + 1);
                    }
                } else {
                    for (int i = fromPosition; i > toPosition; i--) {
                        Collections.swap(mData, i, i - 1);
                    }
                }
                notifyItemMoved(fromPosition, toPosition);
            }
    
            @Override
            public void onSwiped(int position) {
                mData.remove(position);
                notifyItemRemoved(position);
    
            }
    
            private class TestViewHolder extends RecyclerView.ViewHolder {
                TextView tv;
    
                public TestViewHolder(View itemView) {
                    super(itemView);
                    tv = (TextView) itemView.findViewById(R.id.tv);
                }
    
            }
    
        }
    主fragment布局:
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <com.scwang.smartrefresh.layout.SmartRefreshLayout
            android:id="@+id/refresh"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <android.support.v4.widget.NestedScrollView
                android:layout_width="match_parent"
                android:layout_height="match_parent">
    
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:orientation="vertical">
    
                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="@string/test" />
    
                    <RelativeLayout
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:descendantFocusability="blocksDescendants">
    
                        <android.support.v7.widget.RecyclerView
                            android:id="@+id/recyclerView"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"></android.support.v7.widget.RecyclerView>
                    </RelativeLayout>
                </LinearLayout>
            </android.support.v4.widget.NestedScrollView>
        </com.scwang.smartrefresh.layout.SmartRefreshLayout>
    
    </LinearLayout>
    RecyleView实现可拖拽效果的帮助类:
    MyItemTouchCallback :
    public class MyItemTouchCallback extends ItemTouchHelper.Callback {
    
        private ItemTouchAdapter itemTouchAdapter;
        public MyItemTouchCallback(ItemTouchAdapter itemTouchAdapter){
            this.itemTouchAdapter = itemTouchAdapter;
        }
    
        @Override
        public boolean isLongPressDragEnabled() {
            return false;
        }
    
        @Override
        public boolean isItemViewSwipeEnabled() {
            return true;
        }
    
    
        @Override
        public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
            if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {
                final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN |
                        ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
                final int swipeFlags = 0;
                return makeMovementFlags(dragFlags, swipeFlags);
            } else {
                final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
                final int swipeFlags = 0;
                return makeMovementFlags(dragFlags, swipeFlags);
            }
        }
    
        @Override
        public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
            int fromPosition = viewHolder.getAdapterPosition();//得到拖动ViewHolder的position
            int toPosition = target.getAdapterPosition();//得到目标ViewHolder的position
            itemTouchAdapter.onMove(fromPosition,toPosition);
            return true;
        }
    
        @Override
        public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
            int position = viewHolder.getAdapterPosition();
            itemTouchAdapter.onSwiped(position);
    
        }
    
        @Override
        public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
            if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
                //滑动时改变Item的透明度
                final float alpha = 1 - Math.abs(dX) / (float) viewHolder.itemView.getWidth();
                viewHolder.itemView.setAlpha(alpha);
                viewHolder.itemView.setTranslationX(dX);
            } else {
                super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
            }
        }
    
        @Override
        public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
            if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
                if (background == null && bkcolor == -1) {
                    Drawable drawable = viewHolder.itemView.getBackground();
                    if (drawable == null) {
                        bkcolor = 0;
                    } else {
                        background = drawable;
                    }
                }
                viewHolder.itemView.setBackgroundColor(Color.LTGRAY);
            }
            super.onSelectedChanged(viewHolder, actionState);
        }
    
        @Override
        public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
            super.clearView(recyclerView, viewHolder);
    
            viewHolder.itemView.setAlpha(1.0f);
            if (background != null) viewHolder.itemView.setBackgroundDrawable(background);
            if (bkcolor != -1) viewHolder.itemView.setBackgroundColor(bkcolor);
            //viewHolder.itemView.setBackgroundColor(0);
    
            if (onDragListener!=null){
                onDragListener.onFinishDrag();
            }
        }
    
        private Drawable background = null;
        private int bkcolor = -1;
    
        private OnDragListener onDragListener;
        public MyItemTouchCallback setOnDragListener(OnDragListener onDragListener) {
            this.onDragListener = onDragListener;
            return this;
        }
        public interface OnDragListener{
            void onFinishDrag();
        }
    
        public interface ItemTouchAdapter {
            void onMove(int fromPosition, int toPosition);
            void onSwiped(int position);
        }
    }
    OnRecyclerItemClickListener:
    public class OnRecyclerItemClickListener implements RecyclerView.OnItemTouchListener{
        private GestureDetectorCompat mGestureDetector;
        private RecyclerView recyclerView;
    
        public OnRecyclerItemClickListener(RecyclerView recyclerView){
            this.recyclerView = recyclerView;
            mGestureDetector = new GestureDetectorCompat(recyclerView.getContext(),new ItemTouchHelperGestureListener());
        }
        @Override
        public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
            mGestureDetector.onTouchEvent(e);
            return false;
        }
    
        @Override
        public void onTouchEvent(RecyclerView rv, MotionEvent e) {
            mGestureDetector.onTouchEvent(e);
        }
    
        @Override
        public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
    
        }
        private class ItemTouchHelperGestureListener extends GestureDetector.SimpleOnGestureListener {
    
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
                if (child!=null) {
                    RecyclerView.ViewHolder vh = recyclerView.getChildViewHolder(child);
                    onItemClick(vh);
                }
                return true;
            }
            @Override
            public void onLongPress(MotionEvent e) {
                View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
                if (child!=null) {
                    RecyclerView.ViewHolder vh = recyclerView.getChildViewHolder(child);
                    onLongClick(vh);
                }
            }
        }
        public void onLongClick(RecyclerView.ViewHolder vh){}
        public void onItemClick(RecyclerView.ViewHolder vh){}
    }
     VibratorUtil(手机振动工具类)
    /**
     * 手机震动工具类
     * @author Administrator
     * 使用必须添加权限:<uses-permission android:name="android.permission.VIBRATE" />
     */
    public class VibratorUtil {
    
        /**
         * final Activity activity  :调用该方法的Activity实例
         * long milliseconds :震动的时长,单位是毫秒
         * long[] pattern  :自定义震动模式 。数组中数字的含义依次是[静止时长,震动时长,静止时长,震动时长。。。]时长的单位是毫秒
         * boolean isRepeat : 是否反复震动,如果是true,反复震动,如果是false,只震动一次
         */
        public static void Vibrate(final Activity activity, long milliseconds) {
            Vibrator vib = (Vibrator) activity.getSystemService(Service.VIBRATOR_SERVICE);
            vib.vibrate(milliseconds);
        }
        public static void Vibrate(final Activity activity, long[] pattern, boolean isRepeat) {
            Vibrator vib = (Vibrator) activity.getSystemService(Service.VIBRATOR_SERVICE);
            vib.vibrate(pattern, isRepeat ? 1 : -1);
        }
    
    }
  • 相关阅读:
    iOS push
    iOS Beta 升级或降级
    Charles SSL
    看懂UML类图和时序图
    UML示例图 zt
    一个二维码-->网址-->iOS/Android跳转
    获取Shell脚本当前的目录
    编辑请求内容 Charles
    adjustsFontSizeToFitWidth 与 NSLineBreakByCharWrapping 无法共用
    js数据类型
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/7425578.html
Copyright © 2011-2022 走看看