├── .gitignore ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── loader_ring.json │ ├── java │ └── xiazdong │ │ └── me │ │ └── fragmentdemo │ │ ├── BasicActivity.java │ │ ├── CommunicateActivity.java │ │ ├── Demo3Activity.java │ │ ├── DialogActivity.java │ │ ├── LazyActivity.java │ │ ├── LazyPagerAdapter.java │ │ ├── MainActivity.java │ │ ├── MainApplication.java │ │ ├── config │ │ ├── GlobalContext.java │ │ └── ThreadAwareDebugTree.java │ │ ├── db │ │ ├── CategoryMetaData.java │ │ ├── DBContract.java │ │ ├── DBHelper.java │ │ ├── DBOperator.java │ │ └── MaterialMetaData.java │ │ ├── fragment │ │ ├── CommunicateFragment1.java │ │ ├── CommunicateFragment2.java │ │ ├── Fragment1.java │ │ ├── Fragment2.java │ │ ├── Fragment3.java │ │ ├── LazyFragment.java │ │ └── ProgressDialogFragment.java │ │ ├── loader │ │ ├── CategoryLoader.java │ │ ├── ILoader.java │ │ └── MaterialLoader.java │ │ ├── provider │ │ └── DBProvider.java │ │ ├── test │ │ └── DBTestData.java │ │ ├── util │ │ └── PrefUtils.java │ │ └── viewpager │ │ ├── CategoryFragment.java │ │ ├── CategoryPagerAdapter.java │ │ ├── MaterialAdapter.java │ │ ├── MaterialFragment.java │ │ └── MaterialPagerAdapter.java │ └── res │ ├── drawable-xhdpi │ ├── weixin_2_normal.png │ └── weixin_2_selected.png │ ├── drawable │ ├── bg_dialog.xml │ └── tab_text_color.xml │ ├── layout │ ├── activity_basic.xml │ ├── activity_communicate.xml │ ├── activity_demo3.xml │ ├── activity_dialog.xml │ ├── activity_lazy.xml │ ├── activity_main.xml │ ├── category.xml │ ├── fragment_1.xml │ ├── fragment_2.xml │ ├── fragment_3.xml │ ├── fragment_communicate_fragment1.xml │ ├── fragment_communicate_fragment2.xml │ ├── fragment_lazy.xml │ ├── fragment_progress_dialog.xml │ ├── item_recyclerview.xml │ ├── material.xml │ └── tab_custom.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ ├── ic_download.png │ ├── ic_launcher.png │ └── tab_indicator.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 24 5 | buildToolsVersion "25.0.0" 6 | defaultConfig { 7 | applicationId "xiazdong.me.fragmentdemo" 8 | minSdkVersion 15 9 | targetSdkVersion 24 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 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(include: ['*.jar'], dir: 'libs') 24 | compile 'com.android.support:appcompat-v7:24.2.1' 25 | compile 'com.jakewharton:butterknife:8.5.1' 26 | compile 'com.jakewharton.timber:timber:4.5.1' 27 | compile 'com.android.support:support-v4:24.2.1' 28 | compile 'com.android.support:design:24.2.1' 29 | compile 'com.android.support:recyclerview-v7:24.2.1' 30 | compile 'com.github.JakeWharton:ViewPagerIndicator:2.4.1' 31 | compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.18' 32 | compile 'com.airbnb.android:lottie:1.5.3' 33 | compile 'org.greenrobot:eventbus:3.0.0' 34 | compile 'me.majiajie:pager-bottom-tab-strip:2.1.0' 35 | annotationProcessor 'com.zhy.fabridge:fabridge-compiler:1.0.0' 36 | compile 'com.zhy.fabridge:fabridge-api:1.0.0' 37 | annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1' 38 | debugCompile 'com.facebook.stetho:stetho:1.5.0' 39 | } 40 | -------------------------------------------------------------------------------- /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 /Users/xiazdong/tech/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 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 28 | 29 | 30 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/assets/loader_ring.json: -------------------------------------------------------------------------------- 1 | {"v":"4.6.0","fr":29.9700012207031,"ip":0,"op":49.0000019958109,"w":200,"h":200,"nm":"loading_ring_medium","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"green ring 1","ks":{"o":{"a":0,"k":100},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":0,"s":[0],"e":[360]},{"t":49.0000019958109}]},"p":{"a":0,"k":[100,100,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[200,200,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[54,54]},"p":{"a":0,"k":[0,0]},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"st","c":{"a":0,"k":[0.1771626,0.2600122,0.4705882,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":6},"lc":2,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"mn":"ADBE Vector Group"},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.644],"y":[0]},"n":["0p667_1_0p644_0"],"t":10,"s":[0],"e":[100]},{"t":50.0000020365418}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p667_1_0p333_0"],"t":-1,"s":[0],"e":[100]},{"t":37.0000015070409}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim"}],"ip":0,"op":50.0000020365418,"st":-1.00000004073083,"bm":0,"sr":1},{"ddd":0,"ind":2,"ty":4,"nm":"flamingo ring 3","parent":1,"ks":{"o":{"a":0,"k":100},"r":{"a":1,"k":[{"i":{"x":[0.785],"y":[1]},"o":{"x":[1],"y":[0]},"n":["0p785_1_1_0"],"t":17,"s":[14.2],"e":[360]},{"t":50.0000020365418}]},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[54,54]},"p":{"a":0,"k":[0,0]},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"st","c":{"a":0,"k":[0.5098039,0.9438523,0.9490196,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":6},"lc":2,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"mn":"ADBE Vector Group"},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":42,"s":[0],"e":[1]},{"t":44.0000017921567}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p833_1_0p333_0"],"t":20,"s":[0],"e":[1]},{"t":44.0000017921567}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim"}],"ip":17.0000006924242,"op":44.0000017921567,"st":-1.00000004073083,"bm":0,"sr":1},{"ddd":0,"ind":3,"ty":4,"nm":"flamingo ring 2","parent":1,"ks":{"o":{"a":0,"k":100},"r":{"a":1,"k":[{"i":{"x":[0.612],"y":[1]},"o":{"x":[1],"y":[0]},"n":["0p612_1_1_0"],"t":17,"s":[14.2],"e":[360]},{"t":50.0000020365418}]},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[54,54]},"p":{"a":0,"k":[0,0]},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"st","c":{"a":0,"k":[0.5098039,0.9438523,0.9490196,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":6},"lc":2,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"mn":"ADBE Vector Group"},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":42,"s":[0],"e":[13.7]},{"t":44.0000017921567}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p833_1_0p333_0"],"t":20,"s":[0],"e":[13.7]},{"t":44.0000017921567}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim"}],"ip":17.0000006924242,"op":44.0000017921567,"st":-1.00000004073083,"bm":0,"sr":1},{"ddd":0,"ind":4,"ty":4,"nm":"flaming ring 1","parent":1,"ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[54,54]},"p":{"a":0,"k":[0,0]},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"st","c":{"a":0,"k":[0.5098039,0.9438523,0.9490196,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":6},"lc":2,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"mn":"ADBE Vector Group"},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[1],"y":[0]},"n":["0p667_1_1_0"],"t":8,"s":[0],"e":[100]},{"t":48.0000019550801}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[1],"y":[0]},"n":["0p667_1_1_0"],"t":-1,"s":[0],"e":[100]},{"t":37.0000015070409}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim"}],"ip":15.0000006109625,"op":44.0000017921567,"st":-1.00000004073083,"bm":0,"sr":1}]} -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/BasicActivity.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.app.Fragment; 6 | import android.support.v7.app.AppCompatActivity; 7 | 8 | import butterknife.ButterKnife; 9 | import timber.log.Timber; 10 | import xiazdong.me.fragmentdemo.fragment.Fragment1; 11 | 12 | public class BasicActivity extends AppCompatActivity { 13 | 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | Timber.d("[onCreate] BEGIN"); 17 | super.onCreate(savedInstanceState); 18 | setContentView(R.layout.activity_basic); 19 | ButterKnife.bind(this); 20 | Fragment1 f1 = Fragment1.newInstance(); 21 | getSupportFragmentManager().beginTransaction() 22 | .add(R.id.container, f1, "f1") 23 | .commit(); 24 | Timber.d("[onCreate] END"); 25 | } 26 | 27 | @Override 28 | protected void onPostCreate(@Nullable Bundle savedInstanceState) { 29 | Timber.d("[onPostCreate] BEGIN"); 30 | super.onPostCreate(savedInstanceState); 31 | Timber.d("[onPostCreate] END"); 32 | } 33 | 34 | @Override 35 | public void onAttachFragment(Fragment fragment) { 36 | Timber.d("[onAttachFragment] BEGIN"); 37 | super.onAttachFragment(fragment); 38 | Timber.d("[onAttachFragment] END"); 39 | } 40 | 41 | @Override 42 | protected void onStart() { 43 | Timber.d("[onStart] BEGIN"); 44 | super.onStart(); 45 | Timber.d("[onStart] END"); 46 | } 47 | 48 | @Override 49 | protected void onResume() { 50 | Timber.d("[onResume] BEGIN"); 51 | super.onResume(); 52 | Timber.d("[onResume] END"); 53 | } 54 | 55 | @Override 56 | public void onAttachedToWindow() { 57 | Timber.d("[onAttachedToWindow] BEGIN"); 58 | super.onAttachedToWindow(); 59 | Timber.d("[onAttachedToWindow] END"); 60 | } 61 | 62 | @Override 63 | protected void onPostResume() { 64 | Timber.d("[onPostResume] BEGIN"); 65 | super.onPostResume(); 66 | Timber.d("[onPostResume] END"); 67 | } 68 | 69 | @Override 70 | protected void onPause() { 71 | Timber.d("[onPause] BEGIN"); 72 | super.onPause(); 73 | Timber.d("[onPause] END"); 74 | } 75 | 76 | @Override 77 | protected void onRestart() { 78 | Timber.d("[onRestart] BEGIN"); 79 | super.onRestart(); 80 | Timber.d("[onRestart] END"); 81 | } 82 | 83 | @Override 84 | protected void onStop() { 85 | Timber.d("[onStop] BEGIN"); 86 | super.onStop(); 87 | Timber.d("[onStop] END"); 88 | } 89 | 90 | @Override 91 | protected void onDestroy() { 92 | Timber.d("[onDestroy] BEGIN"); 93 | super.onDestroy(); 94 | Timber.d("[onDestroy] END"); 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/CommunicateActivity.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.widget.Toast; 6 | 7 | import com.zhy.fabridge.annotation.FCallbackId; 8 | 9 | import xiazdong.me.fragmentdemo.fragment.CommunicateFragment1; 10 | import xiazdong.me.fragmentdemo.fragment.CommunicateFragment2; 11 | 12 | public class CommunicateActivity extends AppCompatActivity implements CommunicateFragment1.OnFragmentInteractionListener { 13 | 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | setContentView(R.layout.activity_communicate); 18 | getSupportFragmentManager().beginTransaction().add(R.id.container1, CommunicateFragment1.newInstance("Activity Data"), "f1").commit(); 19 | getSupportFragmentManager().beginTransaction().add(R.id.container2, CommunicateFragment2.newInstance("Activity Data"), "f2").commit(); 20 | 21 | } 22 | 23 | @Override 24 | public void onFragmentInteraction(String str) { 25 | Toast.makeText(this, str, Toast.LENGTH_SHORT).show(); 26 | } 27 | 28 | @Override 29 | public void toAnotherFragment(String str) { 30 | CommunicateFragment2 f2 = (CommunicateFragment2) getSupportFragmentManager().findFragmentByTag("f2"); 31 | f2.receiveData(str); 32 | } 33 | 34 | @FCallbackId(id = CommunicateFragment1.FAB_ITEM_CLICK) 35 | public void onItemClick(String str) { 36 | Toast.makeText(this, str, Toast.LENGTH_SHORT).show(); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/Demo3Activity.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo; 2 | 3 | import android.os.Bundle; 4 | import android.support.design.widget.TabLayout; 5 | import android.support.v4.view.ViewPager; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.widget.TextView; 10 | 11 | import java.util.List; 12 | 13 | import butterknife.BindView; 14 | import butterknife.ButterKnife; 15 | import xiazdong.me.fragmentdemo.db.CategoryMetaData; 16 | import xiazdong.me.fragmentdemo.loader.CategoryLoader; 17 | import xiazdong.me.fragmentdemo.util.PrefUtils; 18 | import xiazdong.me.fragmentdemo.viewpager.CategoryFragment; 19 | import xiazdong.me.fragmentdemo.viewpager.CategoryPagerAdapter; 20 | import xiazdong.me.fragmentdemo.viewpager.MaterialFragment; 21 | 22 | public class Demo3Activity extends AppCompatActivity implements TabLayout.OnTabSelectedListener, ViewPager.OnPageChangeListener, View.OnClickListener { 23 | 24 | @BindView(R.id.tablayout) 25 | TabLayout mTabLayout; 26 | @BindView(R.id.viewpager) 27 | ViewPager mPager; 28 | @BindView(R.id.text) 29 | TextView mNoneView; 30 | 31 | private CategoryLoader mCategoryLoader; 32 | private CategoryPagerAdapter mCategoryAdapter; 33 | 34 | @Override 35 | protected void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | setContentView(R.layout.activity_demo3); 38 | ButterKnife.bind(this); 39 | mTabLayout.addOnTabSelectedListener(this); 40 | mPager.addOnPageChangeListener(this); 41 | mNoneView.setOnClickListener(this); 42 | loadTabCategory(); 43 | } 44 | 45 | private void loadTabCategory() { 46 | mCategoryLoader = new CategoryLoader(this); 47 | mCategoryLoader.setOnCategoryLoadedListener(new CategoryLoader.OnCategoryLoadedListener() { 48 | @Override 49 | public void onLoadFinished(List datas) { 50 | setTabLayout(datas); 51 | } 52 | }); 53 | mCategoryLoader.start(); 54 | } 55 | 56 | private void setTabLayout(List datas) { 57 | for (CategoryMetaData data : datas) { 58 | TabLayout.Tab tab = mTabLayout.newTab(); 59 | View customView = LayoutInflater.from(this).inflate(R.layout.tab_custom, null); 60 | TextView text = (TextView) customView.findViewById(R.id.text); 61 | text.setText(data.name); 62 | tab.setCustomView(customView); 63 | mTabLayout.addTab(tab, false); 64 | } 65 | mCategoryAdapter = new CategoryPagerAdapter(getSupportFragmentManager(), datas.size()); 66 | mPager.setAdapter(mCategoryAdapter); 67 | if (mTabLayout.getTabCount() > 0) { 68 | mTabLayout.getTabAt(1).select(); 69 | } 70 | } 71 | 72 | @Override 73 | public void onTabSelected(TabLayout.Tab tab) { 74 | mPager.setCurrentItem(tab.getPosition()); 75 | mCategoryAdapter.setCurrentTabIndex(tab.getPosition()); 76 | } 77 | 78 | @Override 79 | public void onTabUnselected(TabLayout.Tab tab) { 80 | } 81 | 82 | @Override 83 | public void onTabReselected(TabLayout.Tab tab) { 84 | } 85 | 86 | @Override 87 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 88 | 89 | } 90 | 91 | @Override 92 | public void onPageSelected(int position) { 93 | mTabLayout.getTabAt(position).select(); 94 | mCategoryAdapter.setCurrentTabIndex(position); 95 | } 96 | 97 | @Override 98 | public void onPageScrollStateChanged(int state) { 99 | 100 | } 101 | 102 | public void updateCategoryViewPager(int tabIndex) { 103 | mCategoryAdapter.setUpdateFlag(tabIndex); 104 | mCategoryAdapter.notifyDataSetChanged(); 105 | } 106 | 107 | @Override 108 | public void onClick(View v) { 109 | int currentTabIndex = mPager.getCurrentItem(); 110 | int tabIndex = PrefUtils.getInt(PrefUtils.PREFS_KEY_SELECTED_TAB, -1); 111 | int pageIndex = PrefUtils.getInt(PrefUtils.PREFS_KEY_SELECTED_PAGE, -1); 112 | int materialId = PrefUtils.getInt(PrefUtils.PREFS_KEY_SELECTED_MATERIAL, -1); 113 | if (tabIndex == -1) { 114 | return; 115 | } 116 | clearSelectedPreference(); 117 | CategoryFragment currentFragment = (CategoryFragment) mCategoryAdapter.instantiateItem(mPager, currentTabIndex); 118 | int currentPageIndex = currentFragment.getCurrentPageIndex(); 119 | if (currentTabIndex >= 2) { 120 | updateWhenTabLargerThan1(currentFragment, currentTabIndex, currentPageIndex, tabIndex, pageIndex, materialId); 121 | } else if (currentTabIndex == 1){ 122 | updateWhenTabIs1(currentFragment, currentPageIndex, tabIndex, pageIndex, materialId); 123 | } else { 124 | updateWhenTabIs0(currentFragment, currentPageIndex, tabIndex, materialId); 125 | } 126 | mNoneView.setTextColor(getResources().getColor(R.color.colorAccent)); 127 | } 128 | 129 | public void clearSelectedPreference() { 130 | PrefUtils.remove(PrefUtils.PREFS_KEY_SELECTED_TAB); 131 | PrefUtils.remove(PrefUtils.PREFS_KEY_SELECTED_PAGE); 132 | PrefUtils.remove(PrefUtils.PREFS_KEY_SELECTED_MATERIAL); 133 | } 134 | 135 | public int getCurrentTabIndex() { 136 | return mPager.getCurrentItem(); 137 | } 138 | 139 | public void updateNoneView() { 140 | mNoneView.setTextColor(getResources().getColor(android.R.color.black)); 141 | } 142 | 143 | public void updateWhenTabLargerThan1(CategoryFragment fragment, int currentTabIndex, int currentPageIndex, int tabIndex, int pageIndex, int materialId) { 144 | if (Math.abs(currentTabIndex - tabIndex) == 1) { 145 | updateCategoryViewPager(tabIndex); 146 | } else if (currentTabIndex == tabIndex){ 147 | if (pageIndex != currentPageIndex) { 148 | fragment.updateMaterialViewPager(currentPageIndex, pageIndex); 149 | } else { 150 | MaterialFragment mFragment = fragment.getMaterialFragment(pageIndex); 151 | mFragment.updateItem(materialId); 152 | } 153 | } 154 | } 155 | 156 | public void updateWhenTabIs1(CategoryFragment fragment, int currentPageIndex, int tabIndex, int pageIndex, int materialId) { 157 | if (tabIndex == 2 || tabIndex == 0) { 158 | MaterialFragment mFragment = fragment.getMaterialFragment(currentPageIndex); 159 | mFragment.updateItem(materialId); 160 | fragment.updateMaterialViewPager(currentPageIndex, -1); 161 | updateCategoryViewPager(CategoryPagerAdapter.FLAG_UPDATE_LEFT_AND_RIGHT); 162 | } else if (tabIndex == 1) { 163 | updateCategoryViewPager(0); 164 | if (currentPageIndex != pageIndex) { 165 | fragment.updateMaterialViewPager(currentPageIndex, pageIndex); 166 | } else { 167 | MaterialFragment mFragment = fragment.getMaterialFragment(pageIndex); 168 | mFragment.updateItem(materialId); 169 | } 170 | } else { 171 | updateCategoryViewPager(0); 172 | } 173 | } 174 | 175 | public void updateWhenTabIs0(CategoryFragment fragment, int currentPageIndex, int tabIndex, int materialId) { 176 | MaterialFragment mFragment = fragment.getMaterialFragment(currentPageIndex); 177 | mFragment.updateItem(materialId); 178 | fragment.updateMaterialViewPager(currentPageIndex, -1); 179 | if (tabIndex <= 1) { 180 | updateCategoryViewPager(CategoryPagerAdapter.FLAG_UPDATE_LEFT_AND_RIGHT); 181 | } 182 | } 183 | 184 | @Override 185 | protected void onDestroy() { 186 | super.onDestroy(); 187 | clearSelectedPreference(); 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/DialogActivity.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo; 2 | 3 | import android.os.SystemClock; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | import android.widget.Button; 8 | 9 | import butterknife.BindView; 10 | import butterknife.ButterKnife; 11 | import xiazdong.me.fragmentdemo.fragment.ProgressDialogFragment; 12 | 13 | public class DialogActivity extends AppCompatActivity { 14 | 15 | @BindView(R.id.btn_dialog) 16 | Button mDialogBtn; 17 | 18 | ProgressDialogFragment fragment = ProgressDialogFragment.newInstance(); 19 | @Override 20 | protected void onCreate(Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | setContentView(R.layout.activity_dialog); 23 | ButterKnife.bind(this); 24 | mDialogBtn.setOnClickListener(new View.OnClickListener() { 25 | @Override 26 | public void onClick(View v) { 27 | fragment.show(getSupportFragmentManager(), "progressDialog"); 28 | new Thread() { 29 | public void run() { 30 | SystemClock.sleep(5000); 31 | if (fragment == null) { 32 | fragment = (ProgressDialogFragment) getSupportFragmentManager().findFragmentByTag("progressDialog"); 33 | } 34 | fragment.dismiss(); 35 | } 36 | }.start(); 37 | } 38 | }); 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/LazyActivity.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo; 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.view.ViewPager; 5 | import android.support.v7.app.AppCompatActivity; 6 | 7 | import butterknife.BindView; 8 | import butterknife.ButterKnife; 9 | import me.majiajie.pagerbottomtabstrip.NavigationController; 10 | import me.majiajie.pagerbottomtabstrip.PageBottomTabLayout; 11 | import me.majiajie.pagerbottomtabstrip.item.NormalItemView; 12 | 13 | public class LazyActivity extends AppCompatActivity { 14 | 15 | @BindView(R.id.tablayout) 16 | PageBottomTabLayout mTabLayout; 17 | @BindView(R.id.viewpager) 18 | ViewPager mPager; 19 | 20 | @Override 21 | protected void onCreate(Bundle savedInstanceState) { 22 | super.onCreate(savedInstanceState); 23 | setContentView(R.layout.activity_lazy); 24 | ButterKnife.bind(this); 25 | LazyPagerAdapter adapter = new LazyPagerAdapter(getSupportFragmentManager()); 26 | mPager.setAdapter(adapter); 27 | mPager.setOffscreenPageLimit(3); 28 | NavigationController navigationController = mTabLayout.custom() 29 | .addItem(newItem(R.drawable.weixin_2_normal, R.drawable.weixin_2_selected, "微信")) 30 | .addItem(newItem(R.drawable.weixin_2_normal, R.drawable.weixin_2_selected, "通信录")) 31 | .addItem(newItem(R.drawable.weixin_2_normal, R.drawable.weixin_2_selected, "发现")) 32 | .addItem(newItem(R.drawable.weixin_2_normal, R.drawable.weixin_2_selected, "我")) 33 | .build(); 34 | navigationController.setupWithViewPager(mPager); 35 | 36 | } 37 | 38 | private NormalItemView newItem(int drawable, int checkdrawable, String text) { 39 | NormalItemView itemView = new NormalItemView(this); 40 | itemView.initialize(drawable, checkdrawable, text); 41 | itemView.setTextDefaultColor(0xff000000); 42 | itemView.setTextCheckedColor(0xff4CAF50); 43 | return itemView; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/LazyPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.app.FragmentPagerAdapter; 6 | 7 | import xiazdong.me.fragmentdemo.fragment.LazyFragment; 8 | 9 | /** 10 | * Created by xiazdong on 17/6/10. 11 | */ 12 | 13 | public class LazyPagerAdapter extends FragmentPagerAdapter { 14 | private String[] tabs = {"微信", "通讯录", "发现", "我"}; 15 | public LazyPagerAdapter(FragmentManager fm) { 16 | super(fm); 17 | } 18 | 19 | @Override 20 | public Fragment getItem(int position) { 21 | return LazyFragment.newInstance(tabs[position]); 22 | } 23 | 24 | @Override 25 | public int getCount() { 26 | return tabs.length; 27 | } 28 | 29 | @Override 30 | public CharSequence getPageTitle(int position) { 31 | return tabs[position]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.view.View; 7 | import android.widget.Button; 8 | 9 | import butterknife.BindView; 10 | import butterknife.ButterKnife; 11 | import timber.log.Timber; 12 | 13 | public class MainActivity extends AppCompatActivity implements View.OnClickListener { 14 | 15 | @BindView(R.id.btn_1) 16 | Button mButton1; 17 | @BindView(R.id.btn_2) 18 | Button mButton2; 19 | @BindView(R.id.btn_3) 20 | Button mButton3; 21 | @BindView(R.id.btn_4) 22 | Button mButton4; 23 | @BindView(R.id.btn_5) 24 | Button mButton5; 25 | 26 | @Override 27 | protected void onCreate(Bundle savedInstanceState) { 28 | super.onCreate(savedInstanceState); 29 | Timber.d("[onCreate] BEGIN"); 30 | setContentView(R.layout.activity_main); 31 | ButterKnife.bind(this); 32 | mButton1.setOnClickListener(this); 33 | mButton2.setOnClickListener(this); 34 | mButton3.setOnClickListener(this); 35 | mButton4.setOnClickListener(this); 36 | mButton5.setOnClickListener(this); 37 | } 38 | 39 | @Override 40 | public void onClick(View v) { 41 | switch (v.getId()) { 42 | case R.id.btn_1: 43 | goToActivity(BasicActivity.class); 44 | break; 45 | case R.id.btn_2: 46 | goToActivity(CommunicateActivity.class); 47 | break; 48 | case R.id.btn_3: 49 | goToActivity(Demo3Activity.class); 50 | break; 51 | case R.id.btn_4: 52 | goToActivity(DialogActivity.class); 53 | break; 54 | case R.id.btn_5: 55 | goToActivity(LazyActivity.class); 56 | break; 57 | } 58 | } 59 | 60 | void goToActivity(Class activity) { 61 | Intent intent = new Intent(this, activity); 62 | startActivity(intent); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/MainApplication.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo; 2 | 3 | import android.app.Application; 4 | import com.facebook.stetho.Stetho; 5 | import timber.log.Timber; 6 | import xiazdong.me.fragmentdemo.config.GlobalContext; 7 | import xiazdong.me.fragmentdemo.config.ThreadAwareDebugTree; 8 | import xiazdong.me.fragmentdemo.db.DBOperator; 9 | import xiazdong.me.fragmentdemo.util.PrefUtils; 10 | 11 | import static xiazdong.me.fragmentdemo.util.PrefUtils.PREFS_KEY_IS_FIRST_LAUNCH; 12 | 13 | /** 14 | * Created by xiazdong on 17/5/24. 15 | */ 16 | 17 | public class MainApplication extends Application { 18 | 19 | @Override 20 | public void onCreate() { 21 | super.onCreate(); 22 | Timber.plant(new ThreadAwareDebugTree()); 23 | if (BuildConfig.DEBUG) { 24 | Stetho.initializeWithDefaults(this); 25 | } 26 | GlobalContext.setContext(this); 27 | 28 | boolean isFirstLaunch = PrefUtils.getBoolean(PREFS_KEY_IS_FIRST_LAUNCH, true); 29 | Timber.d("is first launch = " + isFirstLaunch); 30 | if (isFirstLaunch) { 31 | DBOperator.insertData(); 32 | PrefUtils.putBoolean(PREFS_KEY_IS_FIRST_LAUNCH, false); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/config/GlobalContext.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.config; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * Created by xiazdong on 17/6/4. 7 | */ 8 | 9 | public class GlobalContext { 10 | private static Context sContext; 11 | 12 | public static Context getContext() { 13 | return sContext; 14 | } 15 | 16 | public static void setContext(Context context) { 17 | sContext = context; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/config/ThreadAwareDebugTree.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.config; 2 | 3 | import timber.log.Timber; 4 | 5 | /** 6 | * Created by xiazdong on 17/5/21. 7 | */ 8 | 9 | public class ThreadAwareDebugTree extends Timber.DebugTree { 10 | 11 | @Override 12 | protected void log(int priority, String tag, String message, Throwable t) { 13 | if (tag != null) { 14 | String threadName = Thread.currentThread().getName(); 15 | tag = "<" + threadName + "> " + tag; 16 | } 17 | super.log(priority, tag, message, t); 18 | } 19 | 20 | @Override 21 | protected String createStackElementTag(StackTraceElement element) { 22 | return super.createStackElementTag(element) + "(Line " + element.getLineNumber() + ")"; //日志显示行号 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/db/CategoryMetaData.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.db; 2 | 3 | import android.database.Cursor; 4 | 5 | /** 6 | * Created by xiazdong on 17/6/4. 7 | */ 8 | 9 | public final class CategoryMetaData { 10 | public int id; 11 | public String name; 12 | 13 | public CategoryMetaData(int id, String name) { 14 | this.id = id; 15 | this.name = name; 16 | } 17 | 18 | public static CategoryMetaData load(Cursor cursor) { 19 | int id = cursor.getInt(cursor.getColumnIndex(DBContract.Category.COLUM_NAME_ID)); 20 | String name = cursor.getString(cursor.getColumnIndex(DBContract.Category.COLUM_NAME_NAME)); 21 | return new CategoryMetaData(id, name); 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return "[" + id + "," + name + "]"; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/db/DBContract.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.db; 2 | 3 | import android.net.Uri; 4 | import android.provider.BaseColumns; 5 | 6 | import xiazdong.me.fragmentdemo.config.GlobalContext; 7 | 8 | /** 9 | * Created by xiazdong on 17/6/3. 10 | */ 11 | 12 | public final class DBContract { 13 | public static final String DB_NAME = "test.db"; 14 | public static final String BASE_CONTENT_URI = "content://" + GlobalContext.getContext().getPackageName() + ".provider.DBProvider/"; 15 | 16 | public static class Category implements BaseColumns { 17 | public static final String TABLE_NAME = "category"; 18 | public static final String COLUM_NAME_ID = "id"; 19 | public static final String COLUM_NAME_NAME = "name"; 20 | public static final Uri CONTENT_URI = Uri.parse(BASE_CONTENT_URI + TABLE_NAME); 21 | public static final String ITEM_TYPE = "vnd.android.cursor.dir/vnd.xiazdong.me.category"; 22 | } 23 | 24 | public static class Material implements BaseColumns { 25 | public static final String TABLE_NAME = "material"; 26 | public static final String COLUM_NAME_CID = "cid"; 27 | public static final String COLUM_NAME_NAME = "name"; 28 | public static final String COLUM_NAME_DOWNLOADED = "downloaded"; 29 | public static final Uri CONTENT_URI = Uri.parse(BASE_CONTENT_URI + TABLE_NAME); 30 | public static final Uri CONTENT_URI_DOWNLOADED = Uri.parse(BASE_CONTENT_URI + TABLE_NAME + "/downloaded"); 31 | public static final String ITEM_TYPE = "vnd.android.cursor.dir/vnd.xiazdong.me.material"; 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/db/DBHelper.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.db; 2 | 3 | import android.content.Context; 4 | import android.database.sqlite.SQLiteDatabase; 5 | import android.database.sqlite.SQLiteOpenHelper; 6 | 7 | import java.util.List; 8 | 9 | import xiazdong.me.fragmentdemo.test.DBTestData; 10 | 11 | import static xiazdong.me.fragmentdemo.db.DBContract.DB_NAME; 12 | 13 | public class DBHelper extends SQLiteOpenHelper { 14 | private static final int DB_VERSION = 1; 15 | private static final String SQL_CATEGORY_CREATE_TABLE = "CREATE TABLE IF NOT EXISTS " + DBContract.Category.TABLE_NAME + 16 | " (" + DBContract.Category.COLUM_NAME_ID + " INTEGER PRIMARY KEY, " 17 | + DBContract.Category.COLUM_NAME_NAME + " TEXT)"; 18 | private static final String SQL_MATERIAL_CREATE_TABLE = "CREATE TABLE IF NOT EXISTS " + DBContract.Material.TABLE_NAME + 19 | " (" + DBContract.Material._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " 20 | + DBContract.Material.COLUM_NAME_CID + " INTEGER, " 21 | + DBContract.Material.COLUM_NAME_NAME + " TEXT, " 22 | + DBContract.Material.COLUM_NAME_DOWNLOADED + " INTEGER)"; 23 | 24 | public DBHelper(Context context) { 25 | super(context, DB_NAME, null, DB_VERSION); 26 | } 27 | 28 | @Override 29 | public void onCreate(SQLiteDatabase sqLiteDatabase) { 30 | sqLiteDatabase.execSQL(SQL_CATEGORY_CREATE_TABLE); 31 | sqLiteDatabase.execSQL(SQL_MATERIAL_CREATE_TABLE); 32 | } 33 | 34 | private void insertCategoryData(CategoryMetaData data) { 35 | SQLiteDatabase db = getWritableDatabase(); 36 | String sql = "INSERT INTO " + DBContract.Category.TABLE_NAME + " (id, name) VALUES (?,?)"; 37 | db.execSQL(sql, new Object[]{data.id, data.name}); 38 | } 39 | 40 | private void insertMaterialData(MaterialMetaData data) { 41 | SQLiteDatabase db = getWritableDatabase(); 42 | String sql = "INSERT INTO " + DBContract.Material.TABLE_NAME + " (cid, name, downloaded) VALUES (?,?,?)"; 43 | db.execSQL(sql, new Object[]{data.cid, data.name, data.downloaded}); 44 | } 45 | 46 | public void insertData() { 47 | List cList = DBTestData.Category.genTestData(); 48 | List mList = DBTestData.Material.genTestData(); 49 | for (CategoryMetaData data : cList) { 50 | insertCategoryData(data); 51 | } 52 | for (MaterialMetaData data : mList) { 53 | insertMaterialData(data); 54 | } 55 | } 56 | 57 | @Override 58 | public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) { 59 | String sql1 = "DROP TABLE IF EXISTS " + DBContract.Category.TABLE_NAME; 60 | String sql2 = "DROP TABLE IF EXISTS " + DBContract.Material.TABLE_NAME; 61 | sqLiteDatabase.execSQL(sql1); 62 | sqLiteDatabase.execSQL(sql2); 63 | onCreate(sqLiteDatabase); 64 | } 65 | 66 | 67 | } -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/db/DBOperator.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.db; 2 | 3 | import android.content.ContentResolver; 4 | import android.content.ContentValues; 5 | import android.content.Context; 6 | import android.database.Cursor; 7 | import android.database.sqlite.SQLiteDatabase; 8 | import android.database.sqlite.SQLiteQueryBuilder; 9 | import android.support.v4.content.CursorLoader; 10 | import android.support.v4.content.Loader; 11 | 12 | import xiazdong.me.fragmentdemo.config.GlobalContext; 13 | 14 | /** 15 | * Created by xiazdong on 17/6/4. 16 | */ 17 | 18 | public class DBOperator { 19 | private static DBHelper mDBHelper = new DBHelper(GlobalContext.getContext()); 20 | 21 | public static void insertData() { 22 | mDBHelper.insertData(); 23 | } 24 | 25 | public static Loader loadCategorys(Context context) { 26 | return new CursorLoader(context, DBContract.Category.CONTENT_URI, null, null, null, null); 27 | } 28 | 29 | public static Loader loadMaterials(Context ctx, int cid) { 30 | return new CursorLoader(ctx, DBContract.Material.CONTENT_URI, null, "cid = ?", new String[]{String.valueOf(cid)}, null); 31 | } 32 | 33 | public static Loader loadDownloadedMaterials(Context ctx) { 34 | return new CursorLoader(ctx, DBContract.Material.CONTENT_URI, null, "downloaded = 1", null, null); 35 | } 36 | 37 | public static void updateMaterialDownloaded(int id) { 38 | ContentResolver resolver = GlobalContext.getContext().getContentResolver(); 39 | ContentValues values = new ContentValues(); 40 | values.put(DBContract.Material.COLUM_NAME_DOWNLOADED, 1); 41 | resolver.update(DBContract.Material.CONTENT_URI_DOWNLOADED, values, DBContract.Material._ID + " = " + id, null); 42 | } 43 | 44 | 45 | public static Cursor queryCategories() { 46 | SQLiteQueryBuilder builder = new SQLiteQueryBuilder(); 47 | SQLiteDatabase db = mDBHelper.getReadableDatabase(); 48 | builder.setTables(DBContract.Category.TABLE_NAME); 49 | return builder.query(db, null, null, null, null, null, null); 50 | } 51 | 52 | public static Cursor queryMaterials(String selection, String[] selectArgs) { 53 | SQLiteQueryBuilder builder = new SQLiteQueryBuilder(); 54 | SQLiteDatabase db = mDBHelper.getReadableDatabase(); 55 | builder.setTables(DBContract.Material.TABLE_NAME); 56 | return builder.query(db, null, selection, selectArgs, null, null, null); 57 | } 58 | 59 | public static int updateMaterialDownloaded(ContentValues values, String selection, String[] selectionArgs) { 60 | SQLiteDatabase db = mDBHelper.getWritableDatabase(); 61 | return db.update(DBContract.Material.TABLE_NAME, values, selection, selectionArgs); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/db/MaterialMetaData.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.db; 2 | 3 | import android.database.Cursor; 4 | import android.os.Parcel; 5 | import android.os.Parcelable; 6 | 7 | /** 8 | * Created by xiazdong on 17/6/4. 9 | */ 10 | 11 | public final class MaterialMetaData implements Parcelable { 12 | public int cid; 13 | public String name; 14 | public int downloaded; 15 | public int _id; 16 | 17 | public MaterialMetaData(int cid, String name, int downloaded) { 18 | this.cid = cid; 19 | this.name = name; 20 | this.downloaded = downloaded; 21 | } 22 | 23 | public MaterialMetaData(int _id, int cid, String name, int downloaded) { 24 | this._id = _id; 25 | this.cid = cid; 26 | this.name = name; 27 | this.downloaded = downloaded; 28 | } 29 | 30 | public static MaterialMetaData load(Cursor cursor) { 31 | int _id = cursor.getInt(cursor.getColumnIndex(DBContract.Material._ID)); 32 | int id = cursor.getInt(cursor.getColumnIndex(DBContract.Material.COLUM_NAME_CID)); 33 | String name = cursor.getString(cursor.getColumnIndex(DBContract.Material.COLUM_NAME_NAME)); 34 | int downloaded = cursor.getInt(cursor.getColumnIndex(DBContract.Material.COLUM_NAME_DOWNLOADED)); 35 | return new MaterialMetaData(_id, id, name, downloaded); 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return "[" + _id + "," + cid + "," + name + "," + downloaded + "]"; 41 | } 42 | 43 | 44 | @Override 45 | public int describeContents() { 46 | return 0; 47 | } 48 | 49 | @Override 50 | public void writeToParcel(Parcel out, int flags) { 51 | out.writeInt(cid); 52 | out.writeString(name); 53 | out.writeInt(downloaded); 54 | out.writeInt(_id); 55 | } 56 | 57 | private MaterialMetaData(Parcel in) { 58 | cid = in.readInt(); 59 | name = in.readString(); 60 | downloaded = in.readInt(); 61 | _id = in.readInt(); 62 | } 63 | 64 | public static final Parcelable.Creator CREATOR 65 | = new Parcelable.Creator() { 66 | public MaterialMetaData createFromParcel(Parcel in) { 67 | return new MaterialMetaData(in); 68 | } 69 | 70 | public MaterialMetaData[] newArray(int size) { 71 | return new MaterialMetaData[size]; 72 | } 73 | }; 74 | 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/fragment/CommunicateFragment1.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.fragment; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.support.annotation.Nullable; 7 | import android.support.v4.app.Fragment; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.Button; 12 | import android.widget.TextView; 13 | 14 | import com.zhy.fabridge.lib.Fabridge; 15 | 16 | import xiazdong.me.fragmentdemo.R; 17 | 18 | public class CommunicateFragment1 extends Fragment { 19 | private static final String ARG_PARAM1 = "param1"; 20 | public static final String FAB_ITEM_CLICK = "fab_item_click"; 21 | private String mParam1; 22 | private OnFragmentInteractionListener mListener; 23 | private Activity mActivity; 24 | 25 | public static CommunicateFragment1 newInstance(String param1) { 26 | CommunicateFragment1 fragment = new CommunicateFragment1(); 27 | Bundle args = new Bundle(); 28 | args.putString(ARG_PARAM1, param1); //activity向fragment传数据 29 | fragment.setArguments(args); 30 | return fragment; 31 | } 32 | 33 | @Override 34 | public void onCreate(@Nullable Bundle savedInstanceState) { 35 | super.onCreate(savedInstanceState); 36 | mParam1 = getArguments().getString(ARG_PARAM1); 37 | } 38 | 39 | @Override 40 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 41 | Bundle savedInstanceState) { 42 | View view = inflater.inflate(R.layout.fragment_communicate_fragment1, container, false); 43 | Button button = (Button) view.findViewById(R.id.btn_comm); 44 | Button button2 = (Button) view.findViewById(R.id.btn_comm2); 45 | Button button3 = (Button) view.findViewById(R.id.btn_comm3); 46 | TextView text = (TextView) view.findViewById(R.id.text); 47 | text.setText(mParam1); 48 | button.setOnClickListener(new View.OnClickListener() { 49 | @Override 50 | public void onClick(View v) { 51 | mListener.onFragmentInteraction("Fragment Data"); 52 | } 53 | }); 54 | button2.setOnClickListener(new View.OnClickListener() { 55 | @Override 56 | public void onClick(View v) { 57 | mListener.toAnotherFragment("Frag1 data"); 58 | } 59 | }); 60 | button3.setOnClickListener(new View.OnClickListener() { 61 | @Override 62 | public void onClick(View v) { 63 | Fabridge.call(mActivity,FAB_ITEM_CLICK,"Frag1 data fab"); 64 | } 65 | }); 66 | return view; 67 | } 68 | 69 | @Override 70 | public void onAttach(Context context) { 71 | super.onAttach(context); 72 | if (context instanceof OnFragmentInteractionListener) { 73 | mListener = (OnFragmentInteractionListener) context; 74 | mActivity = (Activity) context; 75 | } else { 76 | throw new RuntimeException(context.toString() 77 | + " must implement OnFragmentInteractionListener"); 78 | } 79 | } 80 | 81 | @Override 82 | public void onDetach() { 83 | super.onDetach(); 84 | mListener = null; 85 | } 86 | 87 | public interface OnFragmentInteractionListener { 88 | void onFragmentInteraction(String str); 89 | 90 | void toAnotherFragment(String str); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/fragment/CommunicateFragment2.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.fragment; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.v4.app.Fragment; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.TextView; 10 | 11 | import xiazdong.me.fragmentdemo.R; 12 | 13 | public class CommunicateFragment2 extends Fragment { 14 | private static final String ARG_PARAM1 = "param1"; 15 | 16 | private String mParam1; 17 | 18 | private TextView mTextView; 19 | 20 | public static CommunicateFragment2 newInstance(String param1) { 21 | CommunicateFragment2 fragment = new CommunicateFragment2(); 22 | Bundle args = new Bundle(); 23 | args.putString(ARG_PARAM1, param1); //activity向fragment传数据 24 | fragment.setArguments(args); 25 | return fragment; 26 | } 27 | 28 | @Override 29 | public void onAttach(Context context) { 30 | super.onAttach(context); 31 | mParam1 = getArguments().getString(ARG_PARAM1); 32 | } 33 | 34 | @Override 35 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 36 | Bundle savedInstanceState) { 37 | View view = inflater.inflate(R.layout.fragment_communicate_fragment2, container, false); 38 | mTextView = (TextView) view.findViewById(R.id.text); 39 | mTextView.setText(mParam1); 40 | return view; 41 | } 42 | 43 | public void receiveData(String str) { 44 | mTextView.setText(str); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/fragment/Fragment1.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.fragment; 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.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.Button; 11 | 12 | import timber.log.Timber; 13 | import xiazdong.me.fragmentdemo.R; 14 | 15 | /** 16 | * Created by xiazdong on 17/5/24. 17 | */ 18 | 19 | public class Fragment1 extends Fragment { 20 | 21 | @Override 22 | public void onAttach(Context context) { 23 | Timber.d("[onAttach] BEGIN"); 24 | super.onAttach(context); 25 | Timber.d("[onAttach] END"); 26 | } 27 | 28 | @Override 29 | public void onCreate(@Nullable Bundle savedInstanceState) { 30 | Timber.d("[onCreate] BEGIN"); 31 | super.onCreate(savedInstanceState); 32 | Timber.d("[onCreate] END"); 33 | } 34 | 35 | @Override 36 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 37 | Timber.d("[onViewCreated] BEGIN"); 38 | super.onViewCreated(view, savedInstanceState); 39 | Timber.d("[onViewCreated] END"); 40 | } 41 | 42 | @Override 43 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 44 | Timber.d("[onActivityCreated] BEGIN"); 45 | super.onActivityCreated(savedInstanceState); 46 | Timber.d("[onActivityCreated] END"); 47 | } 48 | 49 | @Nullable 50 | @Override 51 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 52 | Timber.d("[onCreateView]"); 53 | View view = inflater.inflate(R.layout.fragment_1, container, false); 54 | Button btn = (Button) view.findViewById(R.id.btn_go); 55 | btn.setOnClickListener(new View.OnClickListener() { 56 | @Override 57 | public void onClick(View v) { 58 | Fragment2 f2 = Fragment2.newInstance(); 59 | getFragmentManager().beginTransaction() 60 | .replace(R.id.container, f2, "f2") 61 | .addToBackStack(Fragment2.class.getSimpleName()) 62 | .commit(); 63 | } 64 | }); 65 | return view; 66 | } 67 | 68 | @Override 69 | public void onStart() { 70 | Timber.d("[onStart] BEGIN"); 71 | super.onStart(); 72 | Timber.d("[onStart] END"); 73 | } 74 | 75 | @Override 76 | public void onResume() { 77 | Timber.d("[onResume] BEGIN"); 78 | super.onResume(); 79 | Timber.d("[onResume] END"); 80 | } 81 | 82 | @Override 83 | public void onPause() { 84 | Timber.d("[onPause] BEGIN"); 85 | super.onPause(); 86 | Timber.d("[onPause] END"); 87 | } 88 | 89 | @Override 90 | public void onStop() { 91 | Timber.d("[onStop] BEGIN"); 92 | super.onStop(); 93 | Timber.d("[onStop] END"); 94 | } 95 | 96 | @Override 97 | public void onDestroyView() { 98 | Timber.d("[onDestroyView] BEGIN"); 99 | super.onDestroyView(); 100 | Timber.d("[onDestroyView] END"); 101 | } 102 | 103 | @Override 104 | public void onDestroy() { 105 | Timber.d("[onDestroy] BEGIN"); 106 | super.onDestroy(); 107 | Timber.d("[onDestroy] END"); 108 | } 109 | 110 | @Override 111 | public void onDetach() { 112 | Timber.d("[onDetach] BEGIN"); 113 | super.onDetach(); 114 | Timber.d("[onDetach] END"); 115 | } 116 | 117 | public static Fragment1 newInstance() { 118 | return new Fragment1(); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/fragment/Fragment2.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.fragment; 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.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.Button; 11 | 12 | import timber.log.Timber; 13 | import xiazdong.me.fragmentdemo.R; 14 | 15 | /** 16 | * Created by xiazdong on 17/5/24. 17 | */ 18 | 19 | public class Fragment2 extends Fragment { 20 | 21 | @Override 22 | public void onAttach(Context context) { 23 | Timber.d("[onAttach] BEGIN"); 24 | super.onAttach(context); 25 | Timber.d("[onAttach] END"); 26 | } 27 | 28 | @Override 29 | public void onCreate(@Nullable Bundle savedInstanceState) { 30 | Timber.d("[onCreate] BEGIN"); 31 | super.onCreate(savedInstanceState); 32 | Timber.d("[onCreate] END"); 33 | } 34 | 35 | @Override 36 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 37 | Timber.d("[onViewCreated] BEGIN"); 38 | super.onViewCreated(view, savedInstanceState); 39 | Timber.d("[onViewCreated] END"); 40 | } 41 | 42 | @Override 43 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 44 | Timber.d("[onActivityCreated] BEGIN"); 45 | super.onActivityCreated(savedInstanceState); 46 | Timber.d("[onActivityCreated] END"); 47 | } 48 | 49 | @Override 50 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 51 | Timber.d("[onCreateView]"); 52 | View view = inflater.inflate(R.layout.fragment_2, container, false); 53 | Button btn = (Button) view.findViewById(R.id.btn_go); 54 | btn.setOnClickListener(new View.OnClickListener() { 55 | @Override 56 | public void onClick(View v) { 57 | Fragment3 f3 = Fragment3.newInstance(); 58 | getFragmentManager().beginTransaction() 59 | .replace(R.id.container, f3, "f3") 60 | .addToBackStack(Fragment3.class.getSimpleName()) 61 | .commit(); 62 | } 63 | }); 64 | return view; 65 | } 66 | 67 | @Override 68 | public void onStart() { 69 | Timber.d("[onStart] BEGIN"); 70 | super.onStart(); 71 | Timber.d("[onStart] END"); 72 | } 73 | 74 | @Override 75 | public void onResume() { 76 | Timber.d("[onResume] BEGIN"); 77 | super.onResume(); 78 | Timber.d("[onResume] END"); 79 | } 80 | 81 | @Override 82 | public void onPause() { 83 | Timber.d("[onPause] BEGIN"); 84 | super.onPause(); 85 | Timber.d("[onPause] END"); 86 | } 87 | 88 | @Override 89 | public void onStop() { 90 | Timber.d("[onStop] BEGIN"); 91 | super.onStop(); 92 | Timber.d("[onStop] END"); 93 | } 94 | 95 | @Override 96 | public void onDestroyView() { 97 | Timber.d("[onDestroyView] BEGIN"); 98 | super.onDestroyView(); 99 | Timber.d("[onDestroyView] END"); 100 | } 101 | 102 | @Override 103 | public void onDestroy() { 104 | Timber.d("[onDestroy] BEGIN"); 105 | super.onDestroy(); 106 | Timber.d("[onDestroy] END"); 107 | } 108 | 109 | @Override 110 | public void onDetach() { 111 | Timber.d("[onDetach] BEGIN"); 112 | super.onDetach(); 113 | Timber.d("[onDetach] END"); 114 | } 115 | 116 | public static Fragment2 newInstance() { 117 | return new Fragment2(); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/fragment/Fragment3.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.fragment; 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.support.v4.app.FragmentManager; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.Button; 12 | 13 | import timber.log.Timber; 14 | import xiazdong.me.fragmentdemo.R; 15 | 16 | /** 17 | * Created by xiazdong on 17/5/24. 18 | */ 19 | 20 | public class Fragment3 extends Fragment { 21 | 22 | @Override 23 | public void onAttach(Context context) { 24 | Timber.d("[onAttach] BEGIN"); 25 | super.onAttach(context); 26 | Timber.d("[onAttach] END"); 27 | } 28 | 29 | @Override 30 | public void onCreate(@Nullable Bundle savedInstanceState) { 31 | Timber.d("[onCreate] BEGIN"); 32 | super.onCreate(savedInstanceState); 33 | Timber.d("[onCreate] END"); 34 | } 35 | 36 | @Override 37 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 38 | Timber.d("[onViewCreated] BEGIN"); 39 | super.onViewCreated(view, savedInstanceState); 40 | Timber.d("[onViewCreated] END"); 41 | } 42 | 43 | @Override 44 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 45 | Timber.d("[onActivityCreated] BEGIN"); 46 | super.onActivityCreated(savedInstanceState); 47 | Timber.d("[onActivityCreated] END"); 48 | } 49 | 50 | @Override 51 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 52 | Timber.d("[onCreateView]"); 53 | View view = inflater.inflate(R.layout.fragment_3, container, false); 54 | Button popBtn = (Button) view.findViewById(R.id.btn_go); 55 | popBtn.setOnClickListener(new View.OnClickListener() { 56 | @Override 57 | public void onClick(View v) { 58 | getFragmentManager().popBackStack(Fragment2.class.getSimpleName(), FragmentManager.POP_BACK_STACK_INCLUSIVE); 59 | } 60 | }); 61 | return view; 62 | } 63 | 64 | @Override 65 | public void onStart() { 66 | Timber.d("[onStart] BEGIN"); 67 | super.onStart(); 68 | Timber.d("[onStart] END"); 69 | } 70 | 71 | @Override 72 | public void onResume() { 73 | Timber.d("[onResume] BEGIN"); 74 | super.onResume(); 75 | Timber.d("[onResume] END"); 76 | } 77 | 78 | @Override 79 | public void onPause() { 80 | Timber.d("[onPause] BEGIN"); 81 | super.onPause(); 82 | Timber.d("[onPause] END"); 83 | } 84 | 85 | @Override 86 | public void onStop() { 87 | Timber.d("[onStop] BEGIN"); 88 | super.onStop(); 89 | Timber.d("[onStop] END"); 90 | } 91 | 92 | @Override 93 | public void onDestroyView() { 94 | Timber.d("[onDestroyView] BEGIN"); 95 | super.onDestroyView(); 96 | Timber.d("[onDestroyView] END"); 97 | } 98 | 99 | @Override 100 | public void onDestroy() { 101 | Timber.d("[onDestroy] BEGIN"); 102 | super.onDestroy(); 103 | Timber.d("[onDestroy] END"); 104 | } 105 | 106 | @Override 107 | public void onDetach() { 108 | Timber.d("[onDetach] BEGIN"); 109 | super.onDetach(); 110 | Timber.d("[onDetach] END"); 111 | } 112 | 113 | public static Fragment3 newInstance() { 114 | return new Fragment3(); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/fragment/LazyFragment.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.fragment; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.os.SystemClock; 7 | import android.support.annotation.Nullable; 8 | import android.support.v4.app.Fragment; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.widget.TextView; 13 | 14 | import xiazdong.me.fragmentdemo.R; 15 | 16 | /** 17 | * Created by xiazdong on 17/6/10. 18 | */ 19 | 20 | public class LazyFragment extends Fragment { 21 | public static final String ARG_KEY = "key"; 22 | 23 | private Context mContext; 24 | private View mRootView; 25 | private String mKey; 26 | private boolean mIsInited; 27 | private boolean mIsPrepared; 28 | @Override 29 | public void onAttach(Context context) { 30 | super.onAttach(context); 31 | this.mContext = context; 32 | mKey = getArguments().getString(ARG_KEY); 33 | } 34 | 35 | @Nullable 36 | @Override 37 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 38 | mRootView = inflater.inflate(R.layout.fragment_lazy, container, false); 39 | mIsPrepared = true; 40 | lazyLoad(); 41 | return mRootView; 42 | } 43 | 44 | public void lazyLoad() { 45 | if (getUserVisibleHint() && mIsPrepared && !mIsInited) { 46 | //异步初始化,在初始化后显示正常UI 47 | loadData(); 48 | } 49 | } 50 | 51 | private void loadData() { 52 | new Thread() { 53 | public void run() { 54 | SystemClock.sleep(1000); 55 | Activity activity = (Activity) mContext; 56 | activity.runOnUiThread(new Runnable() { 57 | @Override 58 | public void run() { 59 | if (mRootView != null) { 60 | View emptyView = mRootView.findViewById(R.id.empty); 61 | emptyView.setVisibility(View.GONE); 62 | View container = mRootView.findViewById(R.id.container); 63 | TextView text = (TextView) container.findViewById(R.id.text); 64 | text.setText(mKey); 65 | container.setVisibility(View.VISIBLE); 66 | } 67 | mIsInited = true; 68 | } 69 | }); 70 | 71 | } 72 | }.start(); 73 | } 74 | 75 | @Override 76 | public void setUserVisibleHint(boolean isVisibleToUser) { 77 | super.setUserVisibleHint(isVisibleToUser); 78 | if (isVisibleToUser) { 79 | lazyLoad(); 80 | } 81 | } 82 | 83 | public static LazyFragment newInstance(String title) { 84 | LazyFragment fragment = new LazyFragment(); 85 | Bundle bundle = new Bundle(); 86 | bundle.putString(ARG_KEY, title); 87 | fragment.setArguments(bundle); 88 | return fragment; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/fragment/ProgressDialogFragment.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.fragment; 2 | 3 | import android.graphics.Color; 4 | import android.graphics.drawable.ColorDrawable; 5 | import android.os.Bundle; 6 | import android.support.annotation.Nullable; 7 | import android.support.v4.app.DialogFragment; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.view.Window; 12 | 13 | import xiazdong.me.fragmentdemo.R; 14 | 15 | public class ProgressDialogFragment extends DialogFragment { 16 | @Nullable 17 | @Override 18 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 19 | getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE); 20 | getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); 21 | setCancelable(false); 22 | View root = inflater.inflate(R.layout.fragment_progress_dialog, container); 23 | return root; 24 | } 25 | 26 | public static ProgressDialogFragment newInstance() { 27 | return new ProgressDialogFragment(); 28 | } 29 | } -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/loader/CategoryLoader.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.loader; 2 | 3 | import android.database.Cursor; 4 | import android.os.Bundle; 5 | import android.support.v4.app.FragmentActivity; 6 | import android.support.v4.app.LoaderManager; 7 | import android.support.v4.content.Loader; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import xiazdong.me.fragmentdemo.config.GlobalContext; 13 | import xiazdong.me.fragmentdemo.db.CategoryMetaData; 14 | import xiazdong.me.fragmentdemo.db.DBOperator; 15 | 16 | /** 17 | * Created by xiazdong on 17/6/4. 18 | */ 19 | 20 | public class CategoryLoader implements ILoader, LoaderManager.LoaderCallbacks { 21 | 22 | private FragmentActivity mActivity; 23 | private OnCategoryLoadedListener mListener; 24 | 25 | public interface OnCategoryLoadedListener { 26 | void onLoadFinished(List datas); 27 | } 28 | 29 | public CategoryLoader(FragmentActivity activity) { 30 | mActivity = activity; 31 | } 32 | 33 | public void setOnCategoryLoadedListener(OnCategoryLoadedListener listener) { 34 | this.mListener = listener; 35 | } 36 | 37 | @Override 38 | public Loader onCreateLoader(int id, Bundle args) { 39 | Loader loader = null; 40 | if (id == LOADER_CATEGORY_ID) { 41 | loader = DBOperator.loadCategorys(GlobalContext.getContext()); 42 | } 43 | return loader; 44 | } 45 | 46 | @Override 47 | public void onLoadFinished(Loader loader, Cursor data) { 48 | int id = loader.getId(); 49 | if (id == LOADER_CATEGORY_ID) { 50 | List list = processCategory(data); 51 | if (mListener != null) { 52 | mListener.onLoadFinished(list); 53 | } 54 | } 55 | } 56 | 57 | @Override 58 | public void onLoaderReset(Loader loader) { 59 | } 60 | 61 | private List processCategory(Cursor cursor) { 62 | List categoryList = new ArrayList<>(); 63 | while (cursor.moveToNext()) { 64 | categoryList.add(CategoryMetaData.load(cursor)); 65 | } 66 | return categoryList; 67 | } 68 | 69 | @Override 70 | public void start() { 71 | mActivity.getSupportLoaderManager().restartLoader(LOADER_CATEGORY_ID, null, this); 72 | } 73 | 74 | @Override 75 | public void destroy() { 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/loader/ILoader.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.loader; 2 | 3 | /** 4 | * Created by xiazdong on 17/6/4. 5 | */ 6 | 7 | public interface ILoader { 8 | public static final int LOADER_CATEGORY_ID = 1; 9 | public static final int LOADER_MATERIAL_ID = 2; 10 | 11 | public void start(); 12 | 13 | public void destroy(); 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/loader/MaterialLoader.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.loader; 2 | 3 | import android.database.Cursor; 4 | import android.os.Bundle; 5 | import android.support.v4.app.Fragment; 6 | import android.support.v4.app.LoaderManager; 7 | import android.support.v4.content.Loader; 8 | 9 | import java.util.ArrayList; 10 | 11 | import xiazdong.me.fragmentdemo.config.GlobalContext; 12 | import xiazdong.me.fragmentdemo.db.DBOperator; 13 | import xiazdong.me.fragmentdemo.db.MaterialMetaData; 14 | 15 | /** 16 | * Created by xiazdong on 17/6/4. 17 | */ 18 | 19 | public class MaterialLoader implements ILoader, LoaderManager.LoaderCallbacks { 20 | private int mCategoryId; 21 | private Fragment mFragment; 22 | 23 | private OnMaterialLoadedListener mListener; 24 | 25 | public MaterialLoader(Fragment fragment, int cid) { 26 | this.mFragment = fragment; 27 | mCategoryId = cid; 28 | } 29 | 30 | public void setOnMaterialLoadedListener(OnMaterialLoadedListener listener) { 31 | this.mListener = listener; 32 | } 33 | 34 | @Override 35 | public Loader onCreateLoader(int id, Bundle args) { 36 | Loader loader = null; 37 | if (id == LOADER_MATERIAL_ID) { 38 | if (mCategoryId != 0) { 39 | loader = DBOperator.loadMaterials(GlobalContext.getContext(), mCategoryId); 40 | } else { 41 | loader = DBOperator.loadDownloadedMaterials(GlobalContext.getContext()); 42 | } 43 | } 44 | return loader; 45 | } 46 | 47 | @Override 48 | public void onLoadFinished(Loader loader, Cursor data) { 49 | int id = loader.getId(); 50 | ArrayList list = null; 51 | if (id == LOADER_MATERIAL_ID) { 52 | list = processMaterial(data); 53 | } 54 | if (mListener != null) { 55 | mListener.onLoadFinished(list); 56 | } 57 | } 58 | 59 | @Override 60 | public void onLoaderReset(Loader loader) { 61 | 62 | } 63 | 64 | @Override 65 | public void start() { 66 | mFragment.getLoaderManager().restartLoader(LOADER_MATERIAL_ID, null, this); 67 | } 68 | 69 | @Override 70 | public void destroy() { 71 | 72 | } 73 | 74 | public ArrayList processMaterial(Cursor cursor) { 75 | ArrayList materialList = new ArrayList<>(); 76 | while (cursor.moveToNext()) { 77 | materialList.add(MaterialMetaData.load(cursor)); 78 | } 79 | return materialList; 80 | } 81 | 82 | public interface OnMaterialLoadedListener { 83 | void onLoadFinished(ArrayList datas); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/provider/DBProvider.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.provider; 2 | 3 | import android.content.ContentProvider; 4 | import android.content.ContentValues; 5 | import android.content.UriMatcher; 6 | import android.database.Cursor; 7 | import android.net.Uri; 8 | import android.support.annotation.NonNull; 9 | import android.support.annotation.Nullable; 10 | 11 | import xiazdong.me.fragmentdemo.db.DBContract; 12 | import xiazdong.me.fragmentdemo.db.DBOperator; 13 | 14 | /** 15 | * Created by xiazdong on 17/6/4. 16 | */ 17 | 18 | public class DBProvider extends ContentProvider { 19 | 20 | private String AUTHORITY = ".provider.DBProvider"; 21 | private UriMatcher mMatcher; 22 | 23 | private static final int CODE_CATEGORIES = 0x01; 24 | private static final int CODE_MATERIALS = 0x02; 25 | private static final int CODE_MATERIAL_DOWNLOADED = 0x03; 26 | 27 | @Override 28 | public boolean onCreate() { 29 | AUTHORITY = getContext().getPackageName() + AUTHORITY; 30 | mMatcher = new UriMatcher(UriMatcher.NO_MATCH); 31 | mMatcher.addURI(AUTHORITY, DBContract.Category.TABLE_NAME, CODE_CATEGORIES); 32 | mMatcher.addURI(AUTHORITY, DBContract.Material.TABLE_NAME, CODE_MATERIALS); 33 | mMatcher.addURI(AUTHORITY, DBContract.Material.TABLE_NAME + "/downloaded", CODE_MATERIAL_DOWNLOADED); 34 | return true; 35 | } 36 | 37 | @Nullable 38 | @Override 39 | public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { 40 | switch (mMatcher.match(uri)) { 41 | case CODE_CATEGORIES: 42 | return DBOperator.queryCategories(); 43 | case CODE_MATERIALS: 44 | return DBOperator.queryMaterials(selection, selectionArgs); 45 | default: 46 | throw new IllegalArgumentException("Unknow URI: " + uri); 47 | } 48 | } 49 | 50 | @Nullable 51 | @Override 52 | public String getType(@NonNull Uri uri) { 53 | int code = mMatcher.match(uri); 54 | switch (code) { 55 | case CODE_CATEGORIES: 56 | return DBContract.Category.ITEM_TYPE; 57 | case CODE_MATERIALS: 58 | case CODE_MATERIAL_DOWNLOADED: 59 | return DBContract.Material.ITEM_TYPE; 60 | default: 61 | throw new IllegalArgumentException("Unknow URI: " + uri); 62 | } 63 | } 64 | 65 | @Nullable 66 | @Override 67 | public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { 68 | return null; 69 | } 70 | 71 | @Override 72 | public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) { 73 | return 0; 74 | } 75 | 76 | @Override 77 | public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) { 78 | switch (mMatcher.match(uri)) { 79 | case CODE_MATERIAL_DOWNLOADED: 80 | return DBOperator.updateMaterialDownloaded(values, selection, selectionArgs); 81 | default: 82 | throw new IllegalArgumentException("Unknow URI: " + uri); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/test/DBTestData.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.test; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Random; 6 | 7 | import xiazdong.me.fragmentdemo.db.CategoryMetaData; 8 | import xiazdong.me.fragmentdemo.db.MaterialMetaData; 9 | 10 | /** 11 | * 生成测试数据 12 | * Created by xiazdong on 17/6/4. 13 | */ 14 | 15 | public final class DBTestData { 16 | public static class Category { 17 | private static String[] names = {"已下载", "变妆", "动物", "氛围", "变脸"}; 18 | 19 | private static CategoryMetaData getMetaData(int id, String name) { 20 | return new CategoryMetaData(id, name); 21 | } 22 | 23 | public static List genTestData() { 24 | ArrayList list = new ArrayList<>(); 25 | for (int i = 0; i < names.length; i++) { 26 | list.add(getMetaData(i, names[i])); 27 | } 28 | return list; 29 | } 30 | } 31 | 32 | public static class Material { 33 | private static int[] count = {0, 20, 15, 15, 15}; 34 | 35 | private static MaterialMetaData getMetaData(int cid, String name, int downloaded) { 36 | return new MaterialMetaData(cid, name, downloaded); 37 | } 38 | 39 | public static List genTestData() { 40 | ArrayList list = new ArrayList<>(); 41 | for (int i = 0; i < count.length; i++) { 42 | for (int j = 0; j < count[i]; j++) { 43 | String name = i + "-" + j; 44 | int downloaded = 0; 45 | list.add(getMetaData(i, name, downloaded)); 46 | } 47 | } 48 | return list; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/util/PrefUtils.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.util; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | 6 | import xiazdong.me.fragmentdemo.config.GlobalContext; 7 | 8 | /** 9 | * Created by xiazdong on 17/6/5. 10 | */ 11 | 12 | public final class PrefUtils { 13 | public static final String PREFS_KEY_SELECTED_MATERIAL = "selected_material"; 14 | public static final String PREFS_KEY_SELECTED_PAGE = "selected_page"; 15 | public static final String PREFS_KEY_SELECTED_TAB = "selected_tab"; 16 | public static final String PREFS_KEY_IS_FIRST_LAUNCH = "is_first_launch"; 17 | 18 | public static void putBoolean(String key, boolean value) { 19 | SharedPreferences sp = GlobalContext.getContext().getSharedPreferences("test", 20 | Context.MODE_PRIVATE); 21 | sp.edit().putBoolean(key, value).commit(); 22 | } 23 | 24 | 25 | public static boolean getBoolean(String key, boolean defValue) { 26 | SharedPreferences sp = GlobalContext.getContext().getSharedPreferences("test", 27 | Context.MODE_PRIVATE); 28 | return sp.getBoolean(key, defValue); 29 | } 30 | 31 | 32 | public static void putString(String key, String value) { 33 | SharedPreferences sp = GlobalContext.getContext().getSharedPreferences("test", 34 | Context.MODE_PRIVATE); 35 | sp.edit().putString(key, value).commit(); 36 | } 37 | 38 | 39 | public static String getString(String key, String defValue) { 40 | SharedPreferences sp = GlobalContext.getContext().getSharedPreferences("test", 41 | Context.MODE_PRIVATE); 42 | return sp.getString(key, defValue); 43 | } 44 | 45 | 46 | public static void putInt(String key, int value) { 47 | SharedPreferences sp = GlobalContext.getContext().getSharedPreferences("test", 48 | Context.MODE_PRIVATE); 49 | sp.edit().putInt(key, value).commit(); 50 | } 51 | 52 | 53 | public static int getInt(String key, int defValue) { 54 | SharedPreferences sp = GlobalContext.getContext().getSharedPreferences("test", 55 | Context.MODE_PRIVATE); 56 | return sp.getInt(key, defValue); 57 | } 58 | 59 | 60 | public static void remove(String key) { 61 | SharedPreferences sp = GlobalContext.getContext().getSharedPreferences("test", 62 | Context.MODE_PRIVATE); 63 | sp.edit().remove(key).commit(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/viewpager/CategoryFragment.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.viewpager; 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.support.v4.view.ViewPager; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | 12 | import com.viewpagerindicator.CirclePageIndicator; 13 | 14 | import java.util.ArrayList; 15 | 16 | import timber.log.Timber; 17 | import xiazdong.me.fragmentdemo.Demo3Activity; 18 | import xiazdong.me.fragmentdemo.R; 19 | import xiazdong.me.fragmentdemo.db.MaterialMetaData; 20 | import xiazdong.me.fragmentdemo.loader.MaterialLoader; 21 | 22 | /** 23 | * Created by xiazdong on 17/6/4. 24 | */ 25 | 26 | public class CategoryFragment extends Fragment { 27 | private static final String ARG_KEY_POSITION = "position"; 28 | private Demo3Activity mActivity; 29 | private int mTabIndex; 30 | private MaterialLoader mMaterialLoader; 31 | 32 | private ViewPager mPager; 33 | private CirclePageIndicator mIndicator; 34 | private MaterialPagerAdapter mMaterialAdapter; 35 | 36 | @Override 37 | public void onAttach(Context context) { 38 | super.onAttach(context); 39 | this.mActivity = (Demo3Activity) context; 40 | mTabIndex = getArguments().getInt(ARG_KEY_POSITION); 41 | } 42 | 43 | @Nullable 44 | @Override 45 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 46 | View root = inflater.inflate(R.layout.category, container, false); 47 | mPager = (ViewPager) root.findViewById(R.id.pager); 48 | mIndicator = (CirclePageIndicator) root.findViewById(R.id.indicator); 49 | mMaterialAdapter = new MaterialPagerAdapter(getChildFragmentManager(), mTabIndex); 50 | mPager.setAdapter(mMaterialAdapter); 51 | mIndicator.setViewPager(mPager); 52 | return root; 53 | } 54 | 55 | @Override 56 | public void onResume() { 57 | super.onResume(); 58 | Timber.d("[onResume] tab = " + mTabIndex); 59 | loadMaterials(); 60 | } 61 | 62 | private void loadMaterials() { 63 | mMaterialLoader = new MaterialLoader(this, mTabIndex); 64 | mMaterialLoader.setOnMaterialLoadedListener(new MaterialLoader.OnMaterialLoadedListener() { 65 | @Override 66 | public void onLoadFinished(ArrayList datas) { 67 | Timber.d("load tab's material, tab = " + mTabIndex + ", " + datas); 68 | mMaterialAdapter.setSourceData(datas); 69 | updateMaterialViewPager(mActivity.getCurrentTabIndex(), -1); 70 | } 71 | }); 72 | mMaterialLoader.start(); 73 | } 74 | 75 | public static CategoryFragment newInstance(int position) { 76 | CategoryFragment fragment = new CategoryFragment(); 77 | Bundle bundle = new Bundle(); 78 | bundle.putInt(ARG_KEY_POSITION, position); 79 | fragment.setArguments(bundle); 80 | return fragment; 81 | } 82 | 83 | public void updateMaterialViewPager(int currentPageIndex, int pageIndex) { 84 | mMaterialAdapter.setUpdatePage(currentPageIndex, pageIndex); 85 | mMaterialAdapter.notifyDataSetChanged(); 86 | } 87 | 88 | public int getIndex() { 89 | return mTabIndex; 90 | } 91 | 92 | public int getCurrentPageIndex() { 93 | return mPager.getCurrentItem(); 94 | } 95 | 96 | public MaterialFragment getMaterialFragment(int pageIndex) { 97 | return mMaterialAdapter.getMaterialFragment(mPager, pageIndex); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/viewpager/CategoryPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.viewpager; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.app.FragmentStatePagerAdapter; 6 | import android.view.ViewGroup; 7 | 8 | import timber.log.Timber; 9 | 10 | /** 11 | * Created by xiazdong on 17/6/4. 12 | */ 13 | 14 | public class CategoryPagerAdapter extends FragmentStatePagerAdapter { 15 | private int mTabCount; 16 | /** 17 | * mUpdateFlag决定了对某个Fragment,getItemPosition返回的是POSITION_NONE还是POSITION_UNCHANGED 18 | * 1. FLAG_UPDATE_LEFT_AND_RIGHT: 只更新mCurrentTabIndex相邻的tab 19 | * 2. FLAG_UPDATE_ALL: 更新所有tab 20 | * 3. >=0的整数,只更新这个索引的tab 21 | * 22 | * 所以每次要调用adapter.notifyDataSetChanged()之前要调用setUpdateFlag()设置更新策略。 23 | */ 24 | private int mUpdateFlag = -3; 25 | private int mCurrentTabIndex; //始终为当前滑到的tab索引 26 | 27 | public static final int FLAG_UPDATE_LEFT_AND_RIGHT = -1; 28 | 29 | public CategoryPagerAdapter(FragmentManager fm, int count) { 30 | super(fm); 31 | this.mTabCount = count; 32 | } 33 | 34 | @Override 35 | public Fragment getItem(int position) { 36 | return CategoryFragment.newInstance(position); 37 | } 38 | 39 | @Override 40 | public int getCount() { 41 | return mTabCount; 42 | } 43 | 44 | @Override 45 | public Object instantiateItem(ViewGroup container, int position) { 46 | Timber.d("[instantiateItem] " + position); 47 | return super.instantiateItem(container, position); 48 | } 49 | 50 | @Override 51 | public void destroyItem(ViewGroup container, int position, Object object) { 52 | super.destroyItem(container, position, object); 53 | Timber.d("[destroyItem] tab = " + position); 54 | } 55 | 56 | @Override 57 | public int getItemPosition(Object object) { 58 | CategoryFragment fragment = (CategoryFragment) object; 59 | if (mUpdateFlag == FLAG_UPDATE_LEFT_AND_RIGHT) { 60 | if (mCurrentTabIndex != fragment.getIndex()) { 61 | return POSITION_NONE; 62 | } 63 | } else { 64 | if (mUpdateFlag == fragment.getIndex()) { 65 | return POSITION_NONE; 66 | } 67 | } 68 | return super.getItemPosition(object); 69 | } 70 | 71 | public void setUpdateFlag(int flag) { 72 | this.mUpdateFlag = flag; 73 | } 74 | 75 | public void setCurrentTabIndex(int tabIndex) { 76 | this.mCurrentTabIndex = tabIndex; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/viewpager/MaterialAdapter.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.viewpager; 2 | 3 | import android.view.View; 4 | import android.widget.ImageView; 5 | import android.widget.TextView; 6 | 7 | import com.chad.library.adapter.base.BaseQuickAdapter; 8 | import com.chad.library.adapter.base.BaseViewHolder; 9 | 10 | import java.util.List; 11 | 12 | import timber.log.Timber; 13 | import xiazdong.me.fragmentdemo.R; 14 | import xiazdong.me.fragmentdemo.config.GlobalContext; 15 | import xiazdong.me.fragmentdemo.db.MaterialMetaData; 16 | import xiazdong.me.fragmentdemo.util.PrefUtils; 17 | 18 | /** 19 | * Created by xiazdong on 17/6/4. 20 | */ 21 | 22 | public class MaterialAdapter extends BaseQuickAdapter { 23 | public MaterialAdapter(int layoutResId, List data) { 24 | super(layoutResId, data); 25 | } 26 | 27 | @Override 28 | protected void convert(BaseViewHolder helper, MaterialMetaData item) { 29 | int position = helper.getLayoutPosition(); 30 | helper.setText(R.id.text, item.name); 31 | TextView text = helper.getView(R.id.text); 32 | ImageView download = helper.getView(R.id.download); 33 | int selectedId = PrefUtils.getInt(PrefUtils.PREFS_KEY_SELECTED_MATERIAL, -1); 34 | MaterialMetaData data = mData.get(position); 35 | Timber.d("convert " + data.name); 36 | if (data._id == selectedId) { 37 | download.setVisibility(View.GONE); 38 | text.setTextColor(GlobalContext.getContext().getResources().getColor(R.color.colorAccent)); 39 | } else { 40 | download.setImageResource(R.mipmap.ic_download); 41 | download.setVisibility(data.downloaded == 1 ? View.GONE : View.VISIBLE); 42 | text.setTextColor(GlobalContext.getContext().getResources().getColor(android.R.color.black)); 43 | } 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/viewpager/MaterialFragment.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.viewpager; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.v4.app.Fragment; 6 | import android.support.v7.widget.GridLayoutManager; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.support.v7.widget.SimpleItemAnimator; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | 13 | import com.chad.library.adapter.base.BaseQuickAdapter; 14 | import com.chad.library.adapter.base.listener.OnItemClickListener; 15 | 16 | import java.util.ArrayList; 17 | 18 | import timber.log.Timber; 19 | import xiazdong.me.fragmentdemo.Demo3Activity; 20 | import xiazdong.me.fragmentdemo.R; 21 | import xiazdong.me.fragmentdemo.db.DBOperator; 22 | import xiazdong.me.fragmentdemo.db.MaterialMetaData; 23 | import xiazdong.me.fragmentdemo.util.PrefUtils; 24 | 25 | /** 26 | * Created by xiazdong on 17/6/4. 27 | */ 28 | 29 | public class MaterialFragment extends Fragment { 30 | 31 | private static final String ARG_KEY_LIST = "material_in_page"; 32 | private static final String ARG_KEY_TAB_INDEX = "tab_index"; 33 | private static final String ARG_KEY_PAGE_INDEX = "page_index"; 34 | 35 | private int mTabIndex; 36 | private int mPageIndex; 37 | private ArrayList mData; 38 | 39 | private RecyclerView mRecyclerView; 40 | private MaterialAdapter mAdapter; 41 | private Demo3Activity mActivity; 42 | 43 | @Override 44 | public void onAttach(Context context) { 45 | super.onAttach(context); 46 | this.mActivity = (Demo3Activity) context; 47 | mTabIndex = getArguments().getInt(ARG_KEY_TAB_INDEX); 48 | mPageIndex = getArguments().getInt(ARG_KEY_PAGE_INDEX); 49 | mData = getArguments().getParcelableArrayList(ARG_KEY_LIST); 50 | } 51 | 52 | @Override 53 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 54 | View root = inflater.inflate(R.layout.material, container, false); 55 | mRecyclerView = (RecyclerView) root.findViewById(R.id.recyclerview); 56 | ((SimpleItemAnimator) mRecyclerView.getItemAnimator()).setSupportsChangeAnimations(false); 57 | mAdapter = new MaterialAdapter(R.layout.item_recyclerview, mData); 58 | Timber.d("[onCreateView] tab = " + mTabIndex + ", page = " + mPageIndex + ", " + mData.toString()); 59 | mRecyclerView.setLayoutManager(new GridLayoutManager(mActivity, MaterialPagerAdapter.COLUMN)); 60 | mRecyclerView.addOnItemTouchListener(new OnItemClickListener() { 61 | @Override 62 | public void onSimpleItemClick(BaseQuickAdapter adapter, View view, int position) { 63 | int oldTabIndex = PrefUtils.getInt(PrefUtils.PREFS_KEY_SELECTED_TAB, -1); 64 | int oldPageIndex = PrefUtils.getInt(PrefUtils.PREFS_KEY_SELECTED_PAGE, -1); 65 | int oldSelectedId = PrefUtils.getInt(PrefUtils.PREFS_KEY_SELECTED_MATERIAL, -1); 66 | int oldPosition = getPositionByMaterialId(oldSelectedId); 67 | 68 | int tabIndex = getTabIndex(); 69 | int pageIndex = getPageIndex(); 70 | mActivity.updateNoneView(); 71 | if (oldTabIndex == tabIndex && oldPageIndex == pageIndex && oldPosition == position) 72 | return; 73 | updateCurrentPage(adapter, position, oldPosition); 74 | if (oldTabIndex == -1) { 75 | updateWhenNoOldSelected(); 76 | } 77 | if (tabIndex >= 2) { 78 | updateWhenTabLargerThan2(oldTabIndex, oldPageIndex, tabIndex, pageIndex); 79 | } else if (tabIndex == 1) { 80 | updateWhenTabIs1(oldTabIndex, oldPageIndex, tabIndex, pageIndex); 81 | } else if (tabIndex == 0) { 82 | updateWhenTabIs0(oldTabIndex, oldPageIndex, tabIndex, pageIndex); 83 | } 84 | } 85 | }); 86 | mRecyclerView.setAdapter(mAdapter); 87 | return root; 88 | } 89 | 90 | private void updateCurrentPage(BaseQuickAdapter adapter, int position, int oldPosition) { 91 | MaterialMetaData data = mData.get(position); 92 | adapter.notifyItemChanged(position); 93 | DBOperator.updateMaterialDownloaded(data._id); 94 | PrefUtils.putInt(PrefUtils.PREFS_KEY_SELECTED_MATERIAL, data._id); 95 | PrefUtils.putInt(PrefUtils.PREFS_KEY_SELECTED_PAGE, mPageIndex); 96 | PrefUtils.putInt(PrefUtils.PREFS_KEY_SELECTED_TAB, mTabIndex); 97 | data.downloaded = 1; 98 | /** 99 | * 如果同一页找到了原来选择的元素,那么更新 100 | */ 101 | if (oldPosition != -1) { 102 | adapter.notifyItemChanged(oldPosition); 103 | } 104 | } 105 | 106 | private void updateWhenNoOldSelected() { 107 | int tabIndex = getTabIndex(); 108 | /** 109 | * 如果原来没选择元素 110 | * 1. 当前tab=1,那么更新tab0 111 | * 2. 当前tab=0,那么更新tab1 112 | */ 113 | if (tabIndex == 1) { 114 | mActivity.updateCategoryViewPager(0); 115 | } else if (tabIndex == 0) { 116 | mActivity.updateCategoryViewPager(1); 117 | } 118 | return; 119 | } 120 | 121 | private void updateWhenTabLargerThan2(int oldTabIndex, int oldPageIndex, int tabIndex, int pageIndex) { 122 | CategoryFragment cFragment = (CategoryFragment) getParentFragment(); 123 | /** 124 | * 1. 原来选择的元素的tab=现在选择的元素tab 125 | * 如果不在同一页,那么更新old page 126 | * 2. 如果原来选择的元素tab在相邻页 127 | * 更新该页 128 | */ 129 | if (oldTabIndex == tabIndex) { 130 | if (oldPageIndex != pageIndex) { 131 | cFragment.updateMaterialViewPager(mPageIndex, oldPageIndex); 132 | } 133 | } else if (Math.abs(tabIndex - oldTabIndex) == 1) { 134 | mActivity.updateCategoryViewPager(oldTabIndex); 135 | } else if (oldTabIndex == 0) { 136 | cFragment.updateMaterialViewPager(mPageIndex, -1); 137 | mActivity.updateCategoryViewPager(CategoryPagerAdapter.FLAG_UPDATE_LEFT_AND_RIGHT); 138 | } 139 | } 140 | 141 | private void updateWhenTabIs1(int oldTabIndex, int oldPageIndex, int tabIndex, int pageIndex) { 142 | CategoryFragment cFragment = (CategoryFragment) getParentFragment(); 143 | /** 144 | * 1. 如果原来选择的元素tab==现在的tab 145 | * 更新已下载tab 146 | * 如果不在当前页,那么刷新那一页 147 | * 2. 如果原来选择的tab是tab 0 148 | * 更新除了当前page的其他页 149 | * 3. 如果原来选择的tab是tab 2 150 | * 更新左右两个tab 151 | */ 152 | if (oldTabIndex == tabIndex) { 153 | mActivity.updateCategoryViewPager(0); 154 | if (oldPageIndex != pageIndex) { 155 | cFragment.updateMaterialViewPager(mPageIndex, oldPageIndex); 156 | } 157 | } else if (oldTabIndex == 0) { 158 | cFragment.updateMaterialViewPager(mPageIndex, -1); 159 | mActivity.updateCategoryViewPager(CategoryPagerAdapter.FLAG_UPDATE_LEFT_AND_RIGHT); 160 | } else if (oldTabIndex == 2) { 161 | mActivity.updateCategoryViewPager(CategoryPagerAdapter.FLAG_UPDATE_LEFT_AND_RIGHT); 162 | } else { 163 | mActivity.updateCategoryViewPager(0); 164 | } 165 | } 166 | 167 | private void updateWhenTabIs0(int oldTabIndex, int oldPageIndex, int tabIndex, int pageIndex) { 168 | CategoryFragment cFragment = (CategoryFragment) getParentFragment(); 169 | mActivity.updateCategoryViewPager(CategoryPagerAdapter.FLAG_UPDATE_LEFT_AND_RIGHT); 170 | /** 171 | * 1. 如果原来选择的tab=当前tab 172 | * 如果原来选择元素页不是当前页,更新那一页 173 | * 2. 如果原来选择的tab不是当前tab 174 | * 更新除了当前页以外的所有页 175 | */ 176 | if (oldTabIndex == tabIndex) { 177 | if (oldPageIndex != pageIndex) { 178 | cFragment.updateMaterialViewPager(mPageIndex, oldPageIndex); 179 | } 180 | } else { 181 | cFragment.updateMaterialViewPager(mPageIndex, -1); 182 | } 183 | } 184 | 185 | public static MaterialFragment newInstance(int tabIndex, int pageIndex, ArrayList data) { 186 | MaterialFragment fragment = new MaterialFragment(); 187 | Bundle bundle = new Bundle(); 188 | bundle.putInt(ARG_KEY_TAB_INDEX, tabIndex); 189 | bundle.putInt(ARG_KEY_PAGE_INDEX, pageIndex); 190 | bundle.putParcelableArrayList(ARG_KEY_LIST, data); 191 | fragment.setArguments(bundle); 192 | return fragment; 193 | } 194 | 195 | private int getPositionByMaterialId(int id) { 196 | if (id < 0) return -1; 197 | for (int i = 0; i < mData.size(); i++) { 198 | MaterialMetaData data = mData.get(i); 199 | if (data._id == id) { 200 | return i; 201 | } 202 | } 203 | return -1; 204 | } 205 | 206 | public void setSourceData(ArrayList data) { 207 | this.mData = data; 208 | if (mRecyclerView != null && mRecyclerView.getAdapter() != null) { 209 | mAdapter = new MaterialAdapter(R.layout.item_recyclerview, mData); 210 | mRecyclerView.setAdapter(mAdapter); 211 | } 212 | } 213 | 214 | public int getPageIndex() { 215 | return mPageIndex; 216 | } 217 | 218 | public int getTabIndex() { 219 | return mTabIndex; 220 | } 221 | 222 | public void updateItem(int materialId) { 223 | int position = getPositionByMaterialId(materialId); 224 | if (position != -1) { 225 | mAdapter.notifyItemChanged(position); 226 | } 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /app/src/main/java/xiazdong/me/fragmentdemo/viewpager/MaterialPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package xiazdong.me.fragmentdemo.viewpager; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.app.FragmentPagerAdapter; 6 | import android.view.ViewGroup; 7 | 8 | import java.util.ArrayList; 9 | 10 | import timber.log.Timber; 11 | import xiazdong.me.fragmentdemo.db.MaterialMetaData; 12 | 13 | /** 14 | * Created by xiazdong on 17/6/4. 15 | */ 16 | 17 | public class MaterialPagerAdapter extends FragmentPagerAdapter { 18 | 19 | public static final int COUNT = 8; 20 | public static final int COLUMN = 4; 21 | 22 | private int mTabIndex; 23 | private ArrayList mData; 24 | 25 | /** 26 | * mUpdatePageIndex为要更新的page 27 | * mCurrentPageIndex为当前是哪个page 28 | * 1、mUpdatePageIndex=-1,那么除了mCurrentPageIndex,其他都更新 29 | * 2、>=0,那么只更新该索引 30 | */ 31 | private int mCurrentPageIndex = -1; 32 | private int mUpdatePageIndex = -1; 33 | 34 | public MaterialPagerAdapter(FragmentManager fm, int tabIndex) { 35 | super(fm); 36 | this.mTabIndex = tabIndex; 37 | } 38 | 39 | public void setSourceData(ArrayList data) { 40 | this.mData = data; 41 | } 42 | 43 | @Override 44 | public Fragment getItem(int position) { 45 | return MaterialFragment.newInstance(mTabIndex, position, getMaterials(position)); 46 | } 47 | 48 | @Override 49 | public Object instantiateItem(ViewGroup container, int position) { 50 | MaterialFragment fragment = (MaterialFragment) super.instantiateItem(container, position); 51 | Timber.d("[instantiateItem], tab = " + mTabIndex + ", page = " + position + ", material = " + getMaterials(position)); 52 | fragment.setSourceData(getMaterials(position)); 53 | return fragment; 54 | } 55 | 56 | @Override 57 | public int getCount() { 58 | if (mData == null || mData.size() == 0) return 0; 59 | int offset = mData.size() % COUNT; 60 | int page = mData.size() / COUNT; 61 | if (offset == 0) { 62 | return page; 63 | } else { 64 | return page + 1; 65 | } 66 | } 67 | 68 | public ArrayList getMaterials(int index) { 69 | int begin = index * COUNT; 70 | int end = Math.min(mData.size(), begin + COUNT); 71 | return new ArrayList<>(mData.subList(begin, end)); 72 | } 73 | 74 | @Override 75 | public int getItemPosition(Object object) { 76 | MaterialFragment fragment = (MaterialFragment) object; 77 | int pageIndex = fragment.getPageIndex(); 78 | if (mUpdatePageIndex == -1) { 79 | if (mCurrentPageIndex != pageIndex) { 80 | return POSITION_NONE; 81 | } 82 | } 83 | if (mUpdatePageIndex == pageIndex) { 84 | return POSITION_NONE; 85 | } 86 | return super.getItemPosition(object); 87 | } 88 | 89 | @Override 90 | public void destroyItem(ViewGroup container, int position, Object object) { 91 | super.destroyItem(container, position, object); 92 | Timber.d("[destroyItem], tab = " + mTabIndex + ", page = " + position); 93 | } 94 | 95 | public void setUpdatePage(int currentPageIndex, int pageIndex) { 96 | this.mCurrentPageIndex = currentPageIndex; 97 | this.mUpdatePageIndex = pageIndex; 98 | } 99 | 100 | public MaterialFragment getMaterialFragment(ViewGroup container, int position) { 101 | return (MaterialFragment) super.instantiateItem(container, position); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/weixin_2_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiazdong/FragmentDemo/94a169381cfa63c1aa71dad83489c909c5276058/app/src/main/res/drawable-xhdpi/weixin_2_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/weixin_2_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiazdong/FragmentDemo/94a169381cfa63c1aa71dad83489c909c5276058/app/src/main/res/drawable-xhdpi/weixin_2_selected.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/tab_text_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_basic.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_communicate.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_demo3.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 22 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 |