300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > Android viewpager+fragment实现无限滚动 左右有前/后一页的部分 并fragment显示的

Android viewpager+fragment实现无限滚动 左右有前/后一页的部分 并fragment显示的

时间:2024-03-16 01:32:43

相关推荐

Android viewpager+fragment实现无限滚动 左右有前/后一页的部分 并fragment显示的

背景:最近在做app的时候碰到一个这样的需求。1,将从网络上获取的json数组数据显示出来,每页显示一个数据源,并且可以左右翻页查看;2,中间显示一个完整页,两边分别还有上下一页的一点,;3,可无限循环滑动。大致效果如下:

思考:这样的效果一下就想到用viewpager+fragment来做。本案例所有代码都有贴出来,有需要的可以自己试试看!

1,activity向fragment传数据可以用fragment的setArguments(Bundle bundle)方法來传,数据源需要实现Serializable接口;

2,显示两边可以用Viewpager的clipToPadding属性实现。

3,无限循环不能用到第一页/最后一页然后改变position的方法实现,因为这样的话第一页左边会空白,最后一页右边会空白。那么我这里的实现方法是用的是改变数据源的方法,即每次滑动结束过后重置fragment列表,并将当前显示的fragment放到fragment列表的中间,然后分别加上前两个与后两个fragment,然后更新adapter里面的fragment列表,并将当前currentindex设置为中间 值2;

代码如下:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="/apk/res/android"xmlns:tools="/tools"android:id="@+id/activity_main"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="cn.humanetplan.myapp.MainActivity"><TextViewandroid:layout_marginTop="30dp"android:id="@+id/tv_title"android:padding="5dp"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"android:text="Viewpager+Fragment无限滑动" /><android.support.v4.view.ViewPagerandroid:id="@+id/vp"android:layout_marginTop="15dp"android:layout_below="@+id/tv_title"android:layout_width="match_parent"android:paddingRight="40dp"android:paddingLeft="40dp"android:clipToPadding="false"android:background="@drawable/frag_bg"android:layout_marginBottom="150dp"android:layout_height="match_parent"></android.support.v4.view.ViewPager></RelativeLayout>

MainActivity代码

package cn.humanetplan.myapp;import android.animation.ArgbEvaluator;import android.graphics.drawable.Drawable;import android.graphics.drawable.GradientDrawable;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentManager;import android.support.v4.app.FragmentStatePagerAdapter;import android.support.v4.app.FragmentTransaction;import android.support.v4.view.ViewPager;import android.os.Bundle;import android.util.Log;import android.view.ViewGroup;import java.util.ArrayList;import java.util.List;import cn.humanetplan.myapp.Bases.BaseActivity;public class MainActivity extends BaseActivity {ViewPager vp;List<DataBean> beanList = new ArrayList<>();//viewpager中显示的fragment的位置private int currentItem = 2;//当前fragment对应在数据源中的真实位置private int trueIndex = 0;//存放每个fragment对应数据源中的真实位置private List<Integer> trueIndexList = new ArrayList<>();//fragment集合private List<MyFragment> showFrag = new ArrayList<>();private MyFragmentPagerAdapter adapter;@Overrideprotected int setContentLayout() {return R.layout.activity_main;}@Overrideprotected void init() {vp = (ViewPager) findViewById(R.id.vp);TestData();updateViews();}private void updateViews() {//初始化viewif (showFrag != null) {showFrag.clear();if (adapter != null) {adapter.notifyDataSetChanged();}}//把当前要生成/显示fragment的数据源对应的index记下来;RecordTrueIndex(trueIndex);//生成fragmentfor (int i = 0; i < trueIndexList.size(); i++) {showFrag.add(MyFragment.getMyFragmentInstance(beanList.get(trueIndexList.get(i))));}if (adapter != null) {adapter.setFragments(showFrag);vp.setCurrentItem(currentItem);} else {InitGv();}}private void InitGv() {adapter = new MyFragmentPagerAdapter(getSupportFragmentManager(), showFrag);vp.setAdapter(adapter);vp.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {//通过估值器动态设置滑动时候左右page的背景色ChangeVpBack(positionOffset, position);}@Overridepublic void onPageSelected(int position) {//每次切换page结束后重置fragment,将当前数据源置为中间要显示的数据源trueIndex = trueIndexList.get(position);updateViews();}@Overridepublic void onPageScrollStateChanged(int state) {}});vp.setCurrentItem(currentItem);}/*** 通过估值器动态渐变背景色** @param positionOffset* @param position*/private void ChangeVpBack(float positionOffset, int position) {ArgbEvaluator evaluator = new ArgbEvaluator();int c2 = 0xff3F51B5;int c1 = 0x643F51B5;int evaluate;if (position % 2 == 0) {evaluate = (Integer) evaluator.evaluate(positionOffset, c2, c1);} else {evaluate = (Integer) evaluator.evaluate(positionOffset, c1, c2);}//动态改变shape的背景色GradientDrawable vpdrawable = (GradientDrawable) vp.getBackground();vpdrawable.setColor(evaluate);}/*** 记下当前要生成fragment的数据源对应的index记下来;* 生成5个fragment,当前要显示的放到中间,前后各加两个** @param trueIndex 要显示的fragment对应的数据源的真实位置*/private void RecordTrueIndex(int trueIndex) {int frag0 = trueIndex - 2;//前2,也就是fragment list中的第一个,index 0int frag1 = trueIndex - 1;//前1,也就是fragment list中的第2个,index 1int frag3 = trueIndex + 1;//后1,也就是fragment list中的第4个,index 3int frag4 = trueIndex + 2;//后2,也就是fragment list中的第5个,index 4if (frag0 < 0) {//负值几,就从最后一个往前数几个frag0 = beanList.size() + frag0;}if (frag1 < 0) {//负值几,就从最后一个往前数几个frag1 = beanList.size() + frag1;}if (frag3 >= beanList.size()) {//超过数据源几个,就从第0个加上超过的数,也就是还有+0,省略frag3 = frag3 - beanList.size();}if (frag4 >= beanList.size()) {//超过数据源几个,就从第0个加上超过的数,也就是还有+0,省略frag4 = frag4 - beanList.size();}if (trueIndexList != null) {trueIndexList.clear();}trueIndexList.add(frag0);trueIndexList.add(frag1);trueIndexList.add(trueIndex);trueIndexList.add(frag3);trueIndexList.add(frag4);}//初始化测试数据private void TestData() {beanList.add(new DataBean(R.mipmap.girl1, "第一张图片"));beanList.add(new DataBean(R.mipmap.girl2, "第二张图片"));beanList.add(new DataBean(R.mipmap.girl3, "第三张图片"));beanList.add(new DataBean(R.mipmap.girl4, "第四张图片"));}public class MyFragmentPagerAdapter extends FragmentStatePagerAdapter {private List<MyFragment> mlist;private FragmentManager fm;public MyFragmentPagerAdapter(FragmentManager fm, List<MyFragment> list) {super(fm);this.mlist = list;this.fm = fm;}@Overridepublic Fragment getItem(int arg0) {return mlist.get(arg0);//显示第几个页面}@Overridepublic int getCount() {return mlist.size();//有几个页面}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {super.destroyItem(container, position, object);}public void setFragments(List<MyFragment> fragments) {if (this.mlist != null) {FragmentTransaction ft = fm.beginTransaction();for (Fragment f : this.mlist) {ft.remove(f);}mit();ft = null;fm.executePendingTransactions();}this.mlist = fragments;notifyDataSetChanged();}@Overridepublic int getItemPosition(Object object) {return POSITION_NONE;}}}

DataBean代码

package cn.humanetplan.myapp;import java.io.Serializable;/*** Created by xiaobo on /7/18.*/public class DataBean implements Serializable{private int resourceId;private String tips;public DataBean(int resourceId, String tips) {this.resourceId = resourceId;this.tips = tips;}public int getResourceId() {return resourceId;}public void setResourceId(int resourceId) {this.resourceId = resourceId;}public String getTips() {return tips;}public void setTips(String tips) {this.tips = tips;}}

frag_mine.xml代码

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><ImageViewandroid:layout_marginTop="20dp"android:id="@+id/iv_girl"android:src="@mipmap/girl4"android:layout_gravity="center_horizontal"android:layout_width="wrap_content"android:layout_height="wrap_content" /><TextViewandroid:id="@+id/tv_tips"android:layout_width="wrap_content"android:layout_marginTop="20dp"android:textColor="#fff"android:textSize="16sp"android:layout_gravity="center_horizontal"android:text="标题一"android:layout_height="wrap_content" /></LinearLayout>

MyFragment代码

package cn.humanetplan.myapp;import android.os.Bundle;import android.text.TextUtils;import android.view.View;import android.widget.ImageView;import android.widget.TextView;import cn.humanetplan.myapp.Bases.BaseFragment;/*** Created by xiaobo on /7/18.*/public class MyFragment extends BaseFragment {ImageView iv;TextView tv;@Overrideprotected int setContentLayout() {return R.layout.frag_mine;}@Overrideprotected void init(View view) {iv= (ImageView) view.findViewById(R.id.iv_girl);tv= (TextView) view.findViewById(R.id.tv_tips);InitData();}/*** 接收Fragment传过来的参数,更新视图*/private void InitData() {DataBean bean=null;if (getArguments()!=null){bean= (DataBean) getArguments().getSerializable("dataBean");if (bean!=null){iv.setImageResource(bean.getResourceId());tv.setText(TextUtils.isEmpty(bean.getTips())?"这张图片还没有添加任何说明":bean.getTips());}}}/*** 带参数新建fragment* @param dataBean 需要传过来的参数DataBean* @return*/public static MyFragment getMyFragmentInstance(DataBean dataBean){MyFragment myFragment=new MyFragment();Bundle bundle=new Bundle();bundle.putSerializable("dataBean",dataBean);myFragment.setArguments(bundle);return myFragment;}}

再贴一下BaseActivity与BaseFragment以及shape画的圆角背景的代码

BaseActivity

package cn.humanetplan.myapp.Bases;import android.app.Activity;import android.app.ProgressDialog;import android.content.Context;import android.graphics.drawable.Drawable;import android.os.Build;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.view.WindowManager;import android.view.inputmethod.InputMethodManager;import android.widget.EditText;import android.widget.RadioButton;import android.widget.Toast;import java.lang.reflect.Field;import java.util.ArrayList;import java.util.List;public abstract class BaseActivity extends AppCompatActivity {public static int IsFirstToClassfy = 0;public ProgressDialog loginDialog;public List<Activity> logActivityList = new ArrayList<>();@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);//设置软件盘弹出后不挡住输入框getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);setContentView(setContentLayout());initState();loginDialog = new ProgressDialog(this);loginDialog.setTitle("提示:");loginDialog.setMessage("正在加载中...请稍后");loginDialog.setCancelable(true);init();}protected abstract int setContentLayout();protected abstract void init();protected void showToast(String msg) {Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {if (ev.getAction() == MotionEvent.ACTION_DOWN) {View v = getCurrentFocus();if (isShouldHideInput(v, ev)) {InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);if (imm != null) {imm.hideSoftInputFromWindow(v.getWindowToken(), 0);}}return super.dispatchTouchEvent(ev);}// 必不可少,否则所有的组件都不会有TouchEvent了if (getWindow().superDispatchTouchEvent(ev)) {return true;}return onTouchEvent(ev);}public boolean isShouldHideInput(View v, MotionEvent event) {if (v != null && (v instanceof EditText)) {int[] leftTop = {0, 0};//获取输入框当前的location位置v.getLocationInWindow(leftTop);int left = leftTop[0];int top = leftTop[1];int bottom = top + v.getHeight();int right = left + v.getWidth();if (event.getX() > left && event.getX() < right&& event.getY() > top && event.getY() < bottom) {// 点击的是输入框区域,保留点击EditText的事件return false;} else {return true;}}return false;}@Overrideprotected void onDestroy() {super.onDestroy();}/*** 动态的设置状态栏 实现沉浸式状态栏*/private void initState() {//当系统版本为4.4或者4.4以上时可以使用沉浸式状态栏if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//透明状态栏getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);//透明导航栏getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);}}/*** 通过反射的方式获取状态栏高度** @return*/private int getStatusBarHeight() {try {Class<?> c = Class.forName("com.android.internal.R$dimen");Object obj = c.newInstance();Field field = c.getField("status_bar_height");int x = Integer.parseInt(field.get(obj).toString());return getResources().getDimensionPixelSize(x);} catch (Exception e) {e.printStackTrace();}return 0;}}

BaseFragment

package cn.humanetplan.myapp.Bases;import android.app.ProgressDialog;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v4.app.Fragment;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.Toast;public abstract class BaseFragment extends Fragment {protected View mView;public ProgressDialog loginDialog;@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {mView = inflater.inflate(setContentLayout(), null);// ButterKnife.bind(this,mView);return mView;}@Overridepublic void onViewCreated(View view, Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);loginDialog=new ProgressDialog(getActivity());loginDialog.setTitle("提示:");loginDialog.setMessage("正在加载数据,请稍后");init(view);}protected abstract int setContentLayout();protected abstract void init(View view);protected void showToast(String msg) {Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show();}//界面是否可见@Overridepublic void setUserVisibleHint(boolean isVisibleToUser) {super.setUserVisibleHint(isVisibleToUser);if (isVisibleToUser){//可见}else {//不可见}}}

drawable画的背景frag_bg.xml

<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="/apk/res/android"><solid android:color="#3F51B5" /><corners android:radius="10dp" /></shape>

总结:这样就将上述功能基本实现了,基本上代码都贴出来了,也有相应的注释。建好相应的文件,将代买粘上,替换掉几张图片就可以运行了。上述是我的思路和实现,希望大家有什么好的方法和建议的话,能够一起分享,共同进步!

Android viewpager+fragment实现无限滚动 左右有前/后一页的部分 并fragment显示的内容是activity传过去的数据

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。