編輯:關於Android編程
大多數場景下,會單單使用viewPager+Fragment來完成項目需求,但也有一些特殊情況需要用到viewPager的多重嵌套。
我的想法是:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;">
①用viewPager+Fragment來完成"外賣、食堂、雲購訂單"這整個大的框架,到這裡一切順利。
②接著,用viewPager+Fragment來實現“外賣訂單”裡的“等配送、待付款、已完成、已取消”這整個小的框架,但這裡在就出問題了。
二、“症狀”:
①小框架的滑動事件出現了問題,不能流暢的從一個tab沒到下一個tab
②每個tab中的內容是不顯示的
③當滑動到“已完成”這個tab時,小框架被滑出去了,直接切換到大框架中的“食堂訂單”
④到了“雲購訂單”時反而出現了小框架其中一個tab的內容
三、嘗試:
我猜想這是2個viewPager嵌套產生的問題,於是自定義了小框架的viewPager,重寫dispatchTouchEvent使父控件不攔截滑動事件,經測試,失敗。自定義小框架的viewPager代碼如下:
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
/**
* @創建者 CSDN_LQR
* @描述 自定義ViewPager:首尾頁面父控件攔截事件
*/
public class CustomViewPager extends ViewPager {
private int startX;
private int startY;
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomViewPager(Context context) {
super(context);
}
/**
* 事件分發,請求父控件及祖宗控件是否攔截事件
* 1、右劃,而且是第一個頁面,需要父控件攔截
* 2、左劃,而且是最後一個頁面,需要父控件攔截
* 3、上下滑動,需要父控件攔截
*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
getParent().requestDisallowInterceptTouchEvent(true);//不要攔截,這樣是為了保證ACTION_MOVE調用
startX = (int) ev.getRawX();
startY = (int) ev.getRawY();
break;
case MotionEvent.ACTION_MOVE:
int endX = (int) ev.getRawX();
int endY = (int) ev.getRawY();
if (Math.abs(endX - startX) > Math.abs(endY - startY)) {//左右滑動
if (endX > startX) {//往右滑動
if (getCurrentItem() == 0) {//第一個頁面,需要父控件攔截
getParent().requestDisallowInterceptTouchEvent(false);
}
} else {//左劃
if (getCurrentItem() == getAdapter().getCount() - 1) {//最後一個頁面,需要攔截
getParent().requestDisallowInterceptTouchEvent(false);
}
}
} else {//上下滑動
getParent().requestDisallowInterceptTouchEvent(false);
}
break;
default:
break;
}
return super.dispatchTouchEvent(ev);
}
}
四、原因:
經過一番折騰,原因還是未知,但是可以確定跟Fragment有關。
五、解決辦法:
直接去掉Fragment!!!
1、自定義BasePager類:
①BasePager類代碼:
import android.app.Activity;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
import com.dfdz.wmpt.R;
/**
* @創建者 CSDN_LQR
* @描述 基本頁面(用於替換Fragment)
*/
public abstract class BasePager {
public Activity mActivity;
public View mRootView;//布局對象
public TextView tvTitle;//標題對象
public FrameLayout flContent;//內容
public BasePager(Activity activity) {
mActivity = activity;
init();
}
private void init() {
mRootView = View.inflate(mActivity, R.layout.base_pager, null);
flContent = (FrameLayout) mRootView.findViewById(R.id.fl_content);
flContent.addView(initView());
}
/**
* 初始化布局
*/
public abstract View initView();
/**
* 初始化數據
*/
public void initData() {
}
}
②base_pager.xml代碼:
<framelayout android:id="@+id/fl_content" android:layout_height="0dp" android:layout_weight="1" android:layout_width="match_parent">
</framelayout>
2、把之前小框架中的Fragment全部不繼承Fragment,改繼承BasePager(我這裡不管大框架還是小框架全部繼承BasePager)。
3、設置新的適配器
不使用FragmentPagerAdapter,使用PagerAdapter
/**
* @創建者 CSDN_LQR
* @描述 viewPager的頁面適配器
*/
class ContentAdapter extends PagerAdapter {
@Override
public int getCount() {
return mPagerList.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
BasePager pager = mPagerList.get(position);
container.addView(pager.mRootView);
pager.initData();//初始化數據。。。。不要放在此處初始化數據,否則會預加載下一個頁面
return pager.mRootView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public CharSequence getPageTitle(int position) {
return mTlTitleArr[position];
}
}
4、布局中使用了上面的自定義ViewPager
注:為方便日後理解,這裡貼出部分關鍵(小框架)代碼:
/**
* @創建者 CSDN_LQR
* @描述 OrderFragment中的外賣訂單pager
*/
public class TakeOutFoodOrderPager extends BasePager {
@InjectView(R.id.tlTop)
TabLayout mTlTop;
@InjectView(R.id.vpContent)
CustomViewPager mVpContent;
private String[] mTlTitleArr;
private List mPagerList;
private ContentAdapter mMyPagerAdapter;
public TakeOutFoodOrderPager(Activity activity) {
super(activity);
}
@Override
public View initView() {
View view = View.inflate(mActivity, R.layout.fragment_takeoutfood_cateen, null);
ButterKnife.inject(this, view);
//設置tabLayout模式
mTlTop.setTabMode(TabLayout.MODE_FIXED);
return view;
}
@Override
public void initData() {
mTlTitleArr = UIUtils.getStringArr(R.array.tablayout_title_takeoutfood);
if (mPagerList == null) {
mPagerList = new ArrayList();
mPagerList.add(new WaitDistributionTakeOutFoodPager(mActivity));
mPagerList.add(new WaitPayTakeOutFoodPager(mActivity));
mPagerList.add(new FinishTakeOutFoodPager(mActivity));
mPagerList.add(new CancelTakeOutFoodPager(mActivity));
}
//添加Tab
for (String title : mTlTitleArr) {
mTlTop.addTab(mTlTop.newTab().setText(title));
}
//設置viewPager頁面適配器
mMyPagerAdapter = new ContentAdapter();
mVpContent.setAdapter(mMyPagerAdapter);
//關聯tabLayout和viewPager
mTlTop.setupWithViewPager(mVpContent);
}
/**
* @創建者 CSDN_LQR
* @描述 viewPager的頁面適配器
*/
class ContentAdapter extends PagerAdapter {
@Override
public int getCount() {
return mPagerList.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
BasePager pager = mPagerList.get(position);
container.addView(pager.mRootView);
pager.initData();//初始化數據。。。。不要放在此處初始化數據,否則會預加載下一個頁面
return pager.mRootView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public CharSequence getPageTitle(int position) {
return mTlTitleArr[position];
}
}
}
本文實例為大家分享了android wheel省市縣三級聯動效果,供大家參考,具體內容如下在github上面有一個叫做 Android-wheel 的開源控件, 代碼地址
本文介紹Android中的5種數據存儲方式,具體內容如下 數據存儲在開發中是使用最頻繁的,在這裡主要介紹Android平台中實現數據存儲的5種方式,
前言:最近公司C輪融資成功了,移動團隊准備擴大一下,需要招聘Android開發工程師,陸陸續續面試了幾位Android應聘者,面試過程中聊到性能優化中如何避免內存洩漏問題
首先上效果圖實現原理要完成一個輪播圖片,首先想到的應該是使用ViewPager來實現。ViewPager已經有了滑動的功能,我們只要讓它自己滾動。再加上下方的小圓點就行了