解決下拉刷新控件和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);
}

}
 




 
 


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM