├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── LazyFragment.iml ├── README.md ├── app ├── .gitignore ├── app.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── mr_immortalz │ │ └── com │ │ └── lazefragment │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── mr_immortalz │ │ │ └── com │ │ │ └── lazefragment │ │ │ ├── BaseFragment.java │ │ │ ├── FirstFragment.java │ │ │ ├── LogUtil.java │ │ │ ├── MainActivity.java │ │ │ ├── SecondFragment.java │ │ │ ├── ShowAdapter.java │ │ │ ├── ThirdFragment.java │ │ │ └── ViewPagerIndicator.java │ └── res │ │ ├── drawable │ │ ├── bg.xml │ │ └── lxh_jiujie.png │ │ ├── layout │ │ ├── activity_intent.xml │ │ ├── activity_main.xml │ │ ├── adapter_show_item.xml │ │ ├── fragment_first.xml │ │ ├── fragment_second.xml │ │ └── fragment_third.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── mr_immortalz │ └── com │ └── lazefragment │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | .DS_Store 6 | /build 7 | /captures 8 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | LazyFragment -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 47 | 48 | 49 | 50 | 1.8 51 | 52 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LazyFragment.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LazyFragment 2 | Fragment实现懒加载 3 | 博客说明 http://blog.csdn.net/mr_immortalz/article/details/51015196 4 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.1" 6 | 7 | defaultConfig { 8 | applicationId "mr_immortalz.com.lazefragment" 9 | minSdkVersion 15 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:23.1.1' 26 | } 27 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in H:\android_sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/mr_immortalz/com/lazefragment/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package mr_immortalz.com.lazefragment; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/java/mr_immortalz/com/lazefragment/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package mr_immortalz.com.lazefragment; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.util.SparseArray; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | 12 | /** 13 | * Created by asus on 2016/3/26. 14 | */ 15 | public abstract class BaseFragment extends Fragment { 16 | 17 | private boolean isVisible = false;//当前Fragment是否可见 18 | private boolean isInitView = false;//是否与View建立起映射关系 19 | private boolean isFirstLoad = true;//是否是第一次加载数据 20 | 21 | private View convertView; 22 | private SparseArray mViews; 23 | 24 | @Nullable 25 | @Override 26 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 27 | LogUtil.m(" " + this.getClass().getSimpleName()); 28 | convertView = inflater.inflate(getLayoutId(), container, false); 29 | mViews = new SparseArray<>(); 30 | initView(); 31 | isInitView = true; 32 | lazyLoadData(); 33 | return convertView; 34 | } 35 | 36 | @Override 37 | public void onViewCreated(View view, Bundle savedInstanceState) { 38 | super.onViewCreated(view, savedInstanceState); 39 | LogUtil.m(" " + this.getClass().getSimpleName()); 40 | } 41 | 42 | @Override 43 | public void onAttach(Context context) { 44 | super.onAttach(context); 45 | LogUtil.m("context" + " " + this.getClass().getSimpleName()); 46 | 47 | } 48 | 49 | @Override 50 | public void setUserVisibleHint(boolean isVisibleToUser) { 51 | LogUtil.m("isVisibleToUser " + isVisibleToUser + " " + this.getClass().getSimpleName()); 52 | if (isVisibleToUser) { 53 | isVisible = true; 54 | lazyLoadData(); 55 | 56 | } else { 57 | isVisible = false; 58 | } 59 | super.setUserVisibleHint(isVisibleToUser); 60 | } 61 | 62 | private void lazyLoadData() { 63 | if (isFirstLoad) { 64 | LogUtil.m("第一次加载 " + " isInitView " + isInitView + " isVisible " + isVisible + " " + this.getClass().getSimpleName()); 65 | } else { 66 | LogUtil.m("不是第一次加载" + " isInitView " + isInitView + " isVisible " + isVisible + " " + this.getClass().getSimpleName()); 67 | } 68 | if (!isFirstLoad || !isVisible || !isInitView) { 69 | LogUtil.m("不加载" + " " + this.getClass().getSimpleName()); 70 | return; 71 | } 72 | 73 | LogUtil.m("完成数据第一次加载"+ " " + this.getClass().getSimpleName()); 74 | initData(); 75 | isFirstLoad = false; 76 | } 77 | 78 | /** 79 | * 加载页面布局文件 80 | * @return 81 | */ 82 | protected abstract int getLayoutId(); 83 | 84 | /** 85 | * 让布局中的view与fragment中的变量建立起映射 86 | */ 87 | protected abstract void initView(); 88 | 89 | /** 90 | * 加载要显示的数据 91 | */ 92 | protected abstract void initData(); 93 | 94 | /** 95 | * fragment中可以通过这个方法直接找到需要的view,而不需要进行类型强转 96 | * @param viewId 97 | * @param 98 | * @return 99 | */ 100 | protected E findView(int viewId) { 101 | if (convertView != null) { 102 | E view = (E) mViews.get(viewId); 103 | if (view == null) { 104 | view = (E) convertView.findViewById(viewId); 105 | mViews.put(viewId, view); 106 | } 107 | return view; 108 | } 109 | return null; 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /app/src/main/java/mr_immortalz/com/lazefragment/FirstFragment.java: -------------------------------------------------------------------------------- 1 | package mr_immortalz.com.lazefragment; 2 | 3 | import android.widget.GridView; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * Created by asus on 2016/3/26. 10 | */ 11 | public class FirstFragment extends BaseFragment { 12 | private GridView gridView; 13 | private ShowAdapter showAdapter; 14 | private List mlist; 15 | 16 | 17 | @Override 18 | protected int getLayoutId() { 19 | return R.layout.fragment_first; 20 | } 21 | 22 | @Override 23 | protected void initView() { 24 | gridView = findView(R.id.gridview); 25 | } 26 | 27 | @Override 28 | protected void initData() { 29 | mlist = new ArrayList<>(); 30 | for (int i=0;i<30;i++){ 31 | mlist.add("show "+i); 32 | } 33 | showAdapter = new ShowAdapter(getContext(),mlist); 34 | gridView.setAdapter(showAdapter); 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/mr_immortalz/com/lazefragment/LogUtil.java: -------------------------------------------------------------------------------- 1 | package mr_immortalz.com.lazefragment; 2 | 3 | import android.util.Log; 4 | 5 | /** 6 | */ 7 | public class LogUtil { 8 | /** 9 | * 默认的tag 10 | */ 11 | public static final String defaultTag = "dota"; 12 | public static final int VERBOSE = 1; 13 | public static final int DEBUG = 2; 14 | public static final int INFO = 3; 15 | public static final int WARN = 4; 16 | public static final int ERROR = 5; 17 | public static final int NOTHING = 6; 18 | /** 19 | * 下面这个变量定义日志级别 20 | */ 21 | public static final int LEVEL = VERBOSE; 22 | 23 | 24 | public static void v(String tag, String msg) { 25 | if (LEVEL <= VERBOSE) { 26 | Log.v(tag, msg); 27 | } 28 | } 29 | 30 | public static void d(String tag, String msg) { 31 | if (LEVEL <= DEBUG) { 32 | Log.d(tag, msg); 33 | } 34 | } 35 | 36 | public static void i(String tag, String msg) { 37 | if (LEVEL <= INFO) { 38 | Log.i(tag, msg); 39 | } 40 | } 41 | 42 | public static void w(String tag, String msg) { 43 | if (LEVEL <= WARN) { 44 | Log.w(tag, msg); 45 | } 46 | } 47 | 48 | public static void e(String tag, String msg) { 49 | if (LEVEL <= ERROR) { 50 | Log.e(tag, msg); 51 | } 52 | } 53 | 54 | public static void v(String msg) { 55 | if (LEVEL <= VERBOSE) { 56 | Log.v(defaultTag, msg); 57 | } 58 | } 59 | 60 | public static void d(String msg) { 61 | if (LEVEL <= DEBUG) { 62 | Log.d(defaultTag, msg); 63 | } 64 | } 65 | 66 | public static void i(String msg) { 67 | if (LEVEL <= INFO) { 68 | Log.i(defaultTag, msg); 69 | } 70 | } 71 | 72 | public static void w(String msg) { 73 | if (LEVEL <= WARN) { 74 | Log.w(defaultTag, msg); 75 | } 76 | } 77 | 78 | public static void e(String msg) { 79 | if (LEVEL <= ERROR) { 80 | Log.e(defaultTag, msg); 81 | } 82 | } 83 | 84 | public static void m(String msg){ 85 | String methodName = new Exception().getStackTrace()[1].getMethodName(); 86 | Log.v(defaultTag,methodName+": "+msg); 87 | } 88 | public static void m(int msg){ 89 | String methodName = new Exception().getStackTrace()[1].getMethodName(); 90 | Log.v(defaultTag,methodName+": "+msg+""); 91 | } 92 | 93 | public static void m(){ 94 | String methodName = new Exception().getStackTrace()[1].getMethodName(); 95 | Log.v(defaultTag,methodName); 96 | } 97 | 98 | public static void v(int msg) { 99 | LogUtil.v(msg + ""); 100 | } 101 | 102 | public static void d(int msg) { 103 | LogUtil.d(msg + ""); 104 | } 105 | 106 | public static void i(int msg) { 107 | LogUtil.i(msg + ""); 108 | } 109 | 110 | public static void w(int msg) { 111 | LogUtil.w(msg + ""); 112 | } 113 | 114 | public static void e(int msg) { 115 | LogUtil.e(msg + ""); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /app/src/main/java/mr_immortalz/com/lazefragment/MainActivity.java: -------------------------------------------------------------------------------- 1 | package mr_immortalz.com.lazefragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.app.Fragment; 5 | import android.support.v4.app.FragmentPagerAdapter; 6 | import android.support.v4.view.ViewPager; 7 | import android.support.v7.app.AppCompatActivity; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | public class MainActivity extends AppCompatActivity { 13 | private ViewPager viewPager; 14 | private ViewPagerIndicator indicator; 15 | private FragmentPagerAdapter mAdapter; 16 | private List mList; 17 | private List mDatas; 18 | private int itemCount = 3; 19 | 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_main); 25 | 26 | viewPager = (ViewPager) findViewById(R.id.vp); 27 | indicator = (ViewPagerIndicator) findViewById(R.id.indicator); 28 | 29 | mList = new ArrayList<>(); 30 | FirstFragment firstFragment = new FirstFragment(); 31 | SecondFragment secondFragment = new SecondFragment(); 32 | ThirdFragment thirdFragment = new ThirdFragment(); 33 | mList.add(firstFragment); 34 | mList.add(secondFragment); 35 | mList.add(thirdFragment); 36 | 37 | mDatas = new ArrayList<>(); 38 | for (int i = 0; i < itemCount; i++) { 39 | mDatas.add("i=" + i); 40 | } 41 | 42 | mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) { 43 | @Override 44 | public Fragment getItem(int position) { 45 | return mList.get(position); 46 | } 47 | 48 | @Override 49 | public int getCount() { 50 | return mList.size(); 51 | } 52 | }; 53 | 54 | viewPager.setAdapter(mAdapter); 55 | viewPager.setOffscreenPageLimit(itemCount); 56 | 57 | //将viewpager与indicator绑定 58 | indicator.setDatas(mDatas); 59 | indicator.setViewPager(viewPager); 60 | } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/mr_immortalz/com/lazefragment/SecondFragment.java: -------------------------------------------------------------------------------- 1 | package mr_immortalz.com.lazefragment; 2 | 3 | /** 4 | * Created by asus on 2016/3/26. 5 | */ 6 | public class SecondFragment extends BaseFragment { 7 | 8 | 9 | @Override 10 | protected int getLayoutId() { 11 | return R.layout.fragment_second; 12 | } 13 | 14 | @Override 15 | protected void initView() { 16 | 17 | } 18 | 19 | @Override 20 | protected void initData() { 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/mr_immortalz/com/lazefragment/ShowAdapter.java: -------------------------------------------------------------------------------- 1 | package mr_immortalz.com.lazefragment; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.BaseAdapter; 8 | import android.widget.TextView; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * Created by asus on 2016/3/26. 14 | */ 15 | public class ShowAdapter extends BaseAdapter { 16 | private Context context; 17 | private List mList; 18 | 19 | public ShowAdapter(Context context, List list) { 20 | this.context = context; 21 | mList = list; 22 | } 23 | 24 | @Override 25 | public int getCount() { 26 | return mList.size(); 27 | } 28 | 29 | @Override 30 | public Object getItem(int position) { 31 | return mList.get(position); 32 | } 33 | 34 | @Override 35 | public long getItemId(int position) { 36 | return position; 37 | } 38 | 39 | @Override 40 | public View getView(int position, View convertView, ViewGroup parent) { 41 | View view = LayoutInflater.from(context).inflate(R.layout.adapter_show_item, null); 42 | TextView tv = (TextView) view.findViewById(R.id.tv_adapter); 43 | tv.setText(mList.get(position)); 44 | return view; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/mr_immortalz/com/lazefragment/ThirdFragment.java: -------------------------------------------------------------------------------- 1 | package mr_immortalz.com.lazefragment; 2 | 3 | /** 4 | * Created by asus on 2016/3/26. 5 | */ 6 | public class ThirdFragment extends BaseFragment { 7 | 8 | 9 | @Override 10 | protected int getLayoutId() { 11 | return R.layout.fragment_third; 12 | } 13 | 14 | @Override 15 | protected void initView() { 16 | 17 | } 18 | 19 | @Override 20 | protected void initData() { 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/mr_immortalz/com/lazefragment/ViewPagerIndicator.java: -------------------------------------------------------------------------------- 1 | package mr_immortalz.com.lazefragment; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Paint; 6 | import android.graphics.RectF; 7 | import android.os.Build; 8 | import android.support.v4.view.ViewPager; 9 | import android.util.AttributeSet; 10 | import android.util.TypedValue; 11 | import android.view.Gravity; 12 | import android.view.View; 13 | import android.widget.LinearLayout; 14 | import android.widget.TextView; 15 | 16 | import java.util.List; 17 | 18 | /** 19 | * Created by asus on 2016/3/22. 20 | */ 21 | public class ViewPagerIndicator extends LinearLayout { 22 | private ViewPager mViewPager; 23 | 24 | private int width; 25 | private int height; 26 | private int visibleItemCount = 3; 27 | private int itemCount = 3; 28 | 29 | //绘制框框 30 | private Paint paint; 31 | private float mWidth = 0; 32 | private float mHeight = 0; 33 | private float mLeft = 0; 34 | private float mTop = 0; 35 | private float radiusX = 10; 36 | private float radiusY = 10; 37 | private int mPadding = 8; 38 | 39 | private List mDatas; 40 | private boolean isSetData = false; 41 | private Context context; 42 | private int currentPosition; 43 | private boolean isAutoSelect = false;//判断是否进行切换 44 | private float rebounceOffset; 45 | 46 | public ViewPagerIndicator(Context context) { 47 | super(context); 48 | this.context = context; 49 | init(); 50 | } 51 | 52 | 53 | public ViewPagerIndicator(Context context, AttributeSet attrs) { 54 | super(context, attrs); 55 | this.context = context; 56 | init(); 57 | } 58 | 59 | public ViewPagerIndicator(Context context, AttributeSet attrs, int defStyleAttr) { 60 | super(context, attrs, defStyleAttr); 61 | this.context = context; 62 | init(); 63 | 64 | } 65 | 66 | private void init() { 67 | //LogUtil.m(); 68 | this.setBackgroundDrawable(getResources().getDrawable(R.drawable.bg)); 69 | paint = new Paint(); 70 | paint.setStyle(Paint.Style.FILL); 71 | paint.setColor(getResources().getColor(R.color.white)); 72 | paint.setAntiAlias(true); 73 | } 74 | 75 | @Override 76 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 77 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 78 | width = getMeasuredWidth(); 79 | height = getMeasuredHeight(); 80 | mWidth = width / visibleItemCount; 81 | mHeight = height; 82 | //LogUtil.m("width " + width + " height " + height); 83 | } 84 | 85 | @Override 86 | protected void onSizeChanged(int w, int h, int oldw, int oldh) { 87 | //LogUtil.m(); 88 | super.onSizeChanged(w, h, oldw, oldh); 89 | if (isSetData) { 90 | isSetData = false; 91 | this.removeAllViews(); 92 | //添加TextView 93 | for (int i = 0; i < mDatas.size(); i++) { 94 | TextView tv = new TextView(context); 95 | tv.setPadding(mPadding, mPadding, mPadding, mPadding); 96 | tv.setText(mDatas.get(i)); 97 | LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, 98 | LayoutParams.MATCH_PARENT); 99 | lp.width = width / visibleItemCount; 100 | lp.height = height; 101 | tv.setGravity(Gravity.CENTER); 102 | tv.setTextColor(getResources().getColor(R.color.font_red)); 103 | tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14); 104 | tv.setLayoutParams(lp); 105 | final int finalI = i; 106 | tv.setOnClickListener(new OnClickListener() { 107 | @Override 108 | public void onClick(View v) { 109 | if (mViewPager != null) { 110 | mViewPager.setCurrentItem(finalI); 111 | } 112 | } 113 | }); 114 | this.addView(tv); 115 | } 116 | setTitleColor(); 117 | } 118 | 119 | } 120 | 121 | @Override 122 | protected void onFinishInflate() { 123 | super.onFinishInflate(); 124 | } 125 | 126 | @Override 127 | protected void onDraw(Canvas canvas) { 128 | //LogUtil.m(); 129 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 130 | //drawRoundRect需要的最低API是21 131 | canvas.drawRoundRect(mLeft + mPadding, mTop + mPadding, mLeft + mWidth - mPadding, mTop + mHeight - mPadding, radiusX, radiusY, paint); 132 | } else { 133 | canvas.drawRoundRect(new RectF(mLeft + mPadding, mTop + mPadding, mLeft + mWidth - mPadding, mTop + mHeight - mPadding), radiusX, radiusX, paint); 134 | //canvas.drawRect(mLeft + mPadding, mTop + mPadding, mLeft + mWidth - mPadding, mTop + mHeight - mPadding, paint); 135 | } 136 | 137 | 138 | } 139 | 140 | @Override 141 | protected void dispatchDraw(Canvas canvas) { 142 | //ogUtil.m(); 143 | super.dispatchDraw(canvas); 144 | } 145 | 146 | public void setViewPager(ViewPager viewpager, int position) { 147 | //LogUtil.m(); 148 | this.mViewPager = viewpager; 149 | this.currentPosition = position; 150 | if (mViewPager != null) { 151 | viewpager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { 152 | @Override 153 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 154 | //LogUtil.m(); 155 | //当移动的是最左边item 156 | if (isAutoSelect && currentPosition == 0) { 157 | //滑动手松开时,让最左边(即第一个)item滑动到左边缘位置 158 | if (positionOffset > rebounceOffset / 2) { 159 | mLeft = (position + (positionOffset - rebounceOffset / 2) * 2) * mWidth; 160 | } else if (positionOffset > rebounceOffset / 3 && positionOffset < rebounceOffset / 2) { 161 | //让最左边(即第一个)item 向右回弹一部分距离 162 | mLeft = (position + (rebounceOffset / 2) - positionOffset) * mWidth * 6 / 12; 163 | } else { 164 | //让最左边(即最后一个)item 向左回弹到边缘位置 165 | mLeft = (position + positionOffset) * mWidth * 6 / 12; 166 | } 167 | invalidate(); 168 | } else if (isAutoSelect && currentPosition == itemCount - 1) { 169 | //当移动的是最右边(即最后一个)item 170 | 171 | //滑动手松开时,让最右边(即最后一个)item滑动到右边缘位置 172 | if (positionOffset >= rebounceOffset && positionOffset < (1 - (1 - rebounceOffset) / 2)) { 173 | // 174 | mLeft = (position + positionOffset / (1 - (1 - rebounceOffset) / 2)) * mWidth; 175 | //当item数大于visibleItem可见数,本控件(本质LinearLayout)才滚动 176 | if (visibleItemCount < itemCount) { 177 | scrollTo((int) (mWidth * positionOffset / (1 - (1 - rebounceOffset) / 2) + (position - visibleItemCount + 1) * mWidth), 0); 178 | } 179 | if ((mLeft + mWidth) > (getChildCount() * mWidth)) { 180 | //当(mLeft + mWidth)大于最边缘的宽度时,设置 181 | mLeft = (itemCount - 1) * mWidth; 182 | } 183 | } else if (positionOffset > (1 - (1 - rebounceOffset) / 2) && positionOffset < (1 - (1 - rebounceOffset) / 4)) { 184 | //让最右边(即最后一个)item 向左回弹一部分距离 185 | 186 | //当item数大于visibleItem可见数,且本控件未滚动到指定位置,则设置控件滚动到指定位置 187 | if (visibleItemCount < itemCount && getScrollX() != (itemCount - visibleItemCount) * mWidth) { 188 | scrollTo((int) ((itemCount - visibleItemCount) * mWidth), 0); 189 | } 190 | mLeft = (position + 1) * mWidth - (positionOffset - (1 - (1 - rebounceOffset) / 2)) * mWidth * 7 / 12; 191 | } else { 192 | //让最右边(即最后一个)item 向右回弹到边缘位置 193 | 194 | //因为onPageScrolled 最后positionOffset会变成0,所以这里需要判断一下 195 | //当positionOffset = 0 时,设置mLeft位置 196 | if (positionOffset != 0) { 197 | mLeft = (position + 1) * mWidth - (1.0f - positionOffset) * mWidth * 7 / 12; 198 | if (mLeft > (itemCount - 1) * mWidth) { 199 | mLeft = (itemCount - 1) * mWidth; 200 | } 201 | } else { 202 | mLeft = (itemCount - 1) * mWidth; 203 | } 204 | 205 | } 206 | invalidate(); 207 | } else { 208 | //当移动的是中间item 209 | scrollTo(position, positionOffset); 210 | rebounceOffset = positionOffset; 211 | } 212 | setTitleColor(); 213 | } 214 | 215 | @Override 216 | public void onPageSelected(int position) { 217 | //LogUtil.m("position " + position); 218 | currentPosition = position; 219 | } 220 | 221 | @Override 222 | public void onPageScrollStateChanged(int state) { 223 | //LogUtil.m("state " + state); 224 | if (state == 2) { 225 | //当state = 2时,表示手松开,viewpager开启自动滑动 226 | isAutoSelect = true; 227 | } 228 | if (state == 0) { 229 | //当state = 0时,表示viewpager滑动停止 230 | isAutoSelect = false; 231 | } 232 | } 233 | }); 234 | } 235 | } 236 | 237 | 238 | public void setViewPager(ViewPager viewpager) { 239 | //LogUtil.m(); 240 | setViewPager(viewpager, 0); 241 | } 242 | 243 | /** 244 | * 正常滑动 245 | * @param position 246 | * @param positionOffset 247 | */ 248 | private void scrollTo(int position, float positionOffset) { 249 | //item数量大于可见item,linearlayout才滑动 250 | if (visibleItemCount < itemCount) { 251 | if (positionOffset > 0 && position > (visibleItemCount - 2)) { 252 | this.scrollTo((int) (mWidth * positionOffset + (position - visibleItemCount + 1) * mWidth), 0); 253 | } 254 | } 255 | mLeft = (position + positionOffset) * mWidth; 256 | invalidate(); 257 | } 258 | 259 | /** 260 | * 设置字体颜色 261 | */ 262 | private void setTitleColor() { 263 | if (getChildCount() > 0) { 264 | for (int i = 0; i < getChildCount(); i++) { 265 | if (i == currentPosition) { 266 | ((TextView) getChildAt(currentPosition)).setTextColor(getResources().getColor(R.color.font_red)); 267 | } else { 268 | ((TextView) getChildAt(i)).setTextColor(getResources().getColor(R.color.font_white)); 269 | } 270 | } 271 | } 272 | } 273 | 274 | /** 275 | * 设置内容数据 276 | * 277 | * @param mDatas 278 | */ 279 | public void setDatas(List mDatas) { 280 | //LogUtil.m(); 281 | this.isSetData = true; 282 | this.mDatas = mDatas; 283 | this.itemCount = mDatas.size(); 284 | if (itemCount < visibleItemCount) { 285 | visibleItemCount = itemCount; 286 | } 287 | 288 | } 289 | } 290 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/lxh_jiujie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImmortalZ/LazyFragment/253f25afd1a1774e203eda3974f8fafddac44253/app/src/main/res/drawable/lxh_jiujie.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_intent.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 |