├── .gitignore ├── .idea ├── gradle.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── LICENSE ├── README.md ├── _config.yml ├── app ├── .gitignore ├── build.gradle ├── libs │ └── RePluginSdk-1.2.0.jar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── xujiaji │ │ └── wanandroid │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-web.png │ ├── java │ │ └── com │ │ │ ├── google │ │ │ └── common │ │ │ │ └── base │ │ │ │ └── Optional.java │ │ │ └── xujiaji │ │ │ └── wanandroid │ │ │ ├── RefreshLoadViewModel.java │ │ │ ├── adapter │ │ │ ├── FlexboxBindingAdapter.java │ │ │ ├── FragmentsPagerAdapter.java │ │ │ ├── ImageBindingAdapter.java │ │ │ ├── RefreshCircleStyleBindingAdapter.java │ │ │ ├── RotationBindingAdapter.java │ │ │ └── VersionBindingAdapter.java │ │ │ ├── base │ │ │ ├── App.java │ │ │ ├── BaseActivity.java │ │ │ ├── BaseFragment.java │ │ │ ├── BaseRefreshClickChildViewModel.java │ │ │ ├── BaseRefreshViewModel.java │ │ │ └── BaseViewModel.java │ │ │ ├── behavior │ │ │ ├── BottomNavigationBehavior.java │ │ │ ├── BottomNavigationFABBehavior.java │ │ │ └── FABScrollBehavior.java │ │ │ ├── config │ │ │ ├── C.java │ │ │ └── PicConfig.java │ │ │ ├── di │ │ │ ├── ActivityBindingModule.java │ │ │ ├── AppComponent.java │ │ │ ├── AppModule.java │ │ │ ├── NetModule.java │ │ │ └── ViewModelSubComponent.java │ │ │ ├── helper │ │ │ ├── ActivityResultHelper.java │ │ │ ├── AnimHelper.java │ │ │ ├── BottomNavigationHelper.java │ │ │ ├── CheckHelper.java │ │ │ ├── ClassHelper.java │ │ │ ├── ClipHelper.java │ │ │ ├── EmptyViewHelper.java │ │ │ ├── FabPopLayoutHelper.java │ │ │ ├── GlideImageLoader.java │ │ │ ├── InputHelper.java │ │ │ ├── ParseDateFormat.java │ │ │ ├── PrefHelper.java │ │ │ ├── RefreshLoadHelper.java │ │ │ ├── ToastHelper.java │ │ │ ├── ToolbarHelper.java │ │ │ ├── TypeFaceHelper.java │ │ │ ├── UpdateHelper.java │ │ │ └── ViewHelper.java │ │ │ ├── model │ │ │ ├── FragmentModel.java │ │ │ └── RefreshLoadModel.java │ │ │ ├── module │ │ │ ├── about │ │ │ │ └── AboutActivity.java │ │ │ ├── category_detail │ │ │ │ ├── CategoryDetailActivity.java │ │ │ │ ├── CategoryDetailModule.java │ │ │ │ └── CategoryDetailViewModel.java │ │ │ ├── license │ │ │ │ ├── LicenseActivity.java │ │ │ │ ├── LicenseAdapter.java │ │ │ │ └── LicenseViewModel.java │ │ │ ├── like │ │ │ │ ├── LikeActivity.java │ │ │ │ ├── LikeAdapter.java │ │ │ │ └── LikeViewModel.java │ │ │ ├── login │ │ │ │ ├── LoginActivity.java │ │ │ │ ├── LoginModule.java │ │ │ │ └── LoginViewModel.java │ │ │ ├── main │ │ │ │ ├── MainActivity.java │ │ │ │ ├── MainModule.java │ │ │ │ ├── MainViewModel.java │ │ │ │ └── fragment │ │ │ │ │ ├── AccountDrawerFragment.java │ │ │ │ │ ├── MenuDrawerFragment.java │ │ │ │ │ ├── boxes │ │ │ │ │ ├── MainBoxesAdapter.java │ │ │ │ │ ├── MainBoxesFragment.java │ │ │ │ │ └── MainBoxesViewModel.java │ │ │ │ │ ├── friend_link │ │ │ │ │ ├── FriendLinkAdapter.java │ │ │ │ │ ├── FriendLinkFragment.java │ │ │ │ │ └── FriendLinkViewModel.java │ │ │ │ │ ├── openapis │ │ │ │ │ ├── OpenAPISAdapter.java │ │ │ │ │ ├── OpenAPISFragment.java │ │ │ │ │ └── OpenAPISViewModel.java │ │ │ │ │ ├── post_tree │ │ │ │ │ ├── PostTreeAdapter.java │ │ │ │ │ ├── PostTreeFragment.java │ │ │ │ │ └── PostTreeViewModel.java │ │ │ │ │ ├── posts │ │ │ │ │ ├── MainBlogPostsAdapter.java │ │ │ │ │ ├── MainBlogPostsFragment.java │ │ │ │ │ └── MainBlogPostsViewModel.java │ │ │ │ │ ├── project_category │ │ │ │ │ ├── ProjectCategoryAdapter.java │ │ │ │ │ ├── ProjectCategoryFragment.java │ │ │ │ │ └── ProjectCategoryViewModel.java │ │ │ │ │ ├── projects │ │ │ │ │ ├── MainProjectsAdapter.java │ │ │ │ │ ├── MainProjectsFragment.java │ │ │ │ │ └── MainProjectsViewModel.java │ │ │ │ │ └── web_nav │ │ │ │ │ ├── WebNavFragment.java │ │ │ │ │ └── WebNavViewModel.java │ │ │ ├── read │ │ │ │ ├── ReadActivity.java │ │ │ │ ├── ReadModule.java │ │ │ │ └── ReadViewModel.java │ │ │ ├── set │ │ │ │ ├── SettingsActivity.java │ │ │ │ └── SettingsViewModel.java │ │ │ └── splash │ │ │ │ └── SplashActivity.java │ │ │ ├── repository │ │ │ ├── bean │ │ │ │ ├── BannerBean.java │ │ │ │ ├── BlogPostBean.java │ │ │ │ ├── BoxBean.java │ │ │ │ ├── FriendLinkBean.java │ │ │ │ ├── LicenseBean.java │ │ │ │ ├── PageBean.java │ │ │ │ ├── Result.java │ │ │ │ ├── ThreeAPIBean.java │ │ │ │ ├── TreeBean.java │ │ │ │ ├── UserBean.java │ │ │ │ ├── VersionBean.java │ │ │ │ └── WebNavBean.java │ │ │ ├── local │ │ │ │ └── LocalData.java │ │ │ └── remote │ │ │ │ ├── API.java │ │ │ │ ├── DataCallback.java │ │ │ │ ├── DataCallbackImp.java │ │ │ │ ├── Net.java │ │ │ │ ├── NetCallback.java │ │ │ │ └── NetLiveEvent.java │ │ │ ├── util │ │ │ ├── ApkUtil.java │ │ │ ├── FileUtil.java │ │ │ ├── NetUtil.java │ │ │ ├── StatusBarUtil.java │ │ │ └── UpdateAppHttpUtil.java │ │ │ └── wedgit │ │ │ └── AvatarLayout.java │ └── res │ │ ├── color │ │ └── search_tab_highlighter.xml │ │ ├── drawable-nodpi │ │ └── ic_launcher_web.png │ │ ├── drawable │ │ ├── bottom_border.xml │ │ ├── btn_round.xml │ │ ├── btn_rounded_outline.xml │ │ ├── gradient_bottom_2_top.xml │ │ ├── ic_add.xml │ │ ├── ic_arrow_drop.xml │ │ ├── ic_arrow_right.xml │ │ ├── ic_back.xml │ │ ├── ic_clean.xml │ │ ├── ic_cloud_off.xml │ │ ├── ic_heart_full.xml │ │ ├── ic_home_blog_post.xml │ │ ├── ic_home_box.xml │ │ ├── ic_home_project.xml │ │ ├── ic_internet.xml │ │ ├── ic_link.xml │ │ ├── ic_nav_api.xml │ │ ├── ic_nav_category_project.xml │ │ ├── ic_nav_collect_links.xml │ │ ├── ic_nav_exit.xml │ │ ├── ic_nav_heart.xml │ │ ├── ic_nav_home.xml │ │ ├── ic_nav_i.xml │ │ ├── ic_nav_links.xml │ │ ├── ic_nav_login.xml │ │ ├── ic_nav_logout.xml │ │ ├── ic_nav_navigation.xml │ │ ├── ic_nav_set.xml │ │ ├── ic_nav_share_project.xml │ │ ├── ic_nav_system.xml │ │ ├── ic_pen.xml │ │ ├── ic_search.xml │ │ ├── ic_switch.xml │ │ ├── ic_todo_list.xml │ │ ├── love.xml │ │ ├── ripple_theme.xml │ │ ├── ripple_theme_small.xml │ │ ├── ripple_white.xml │ │ ├── ripple_white_small.xml │ │ ├── scrollbar_thumb.xml │ │ ├── scrollbar_track.xml │ │ └── splash_screen_drawable.xml │ │ ├── layout │ │ ├── activity_about.xml │ │ ├── activity_category_detail.xml │ │ ├── activity_license.xml │ │ ├── activity_like.xml │ │ ├── activity_login.xml │ │ ├── activity_main.xml │ │ ├── activity_read.xml │ │ ├── activity_settings.xml │ │ ├── appbar.xml │ │ ├── drawer_fragment_account.xml │ │ ├── drawer_fragment_menu.xml │ │ ├── drawer_header.xml │ │ ├── fragment_container.xml │ │ ├── item_blog_post.xml │ │ ├── item_box.xml │ │ ├── item_friend_link.xml │ │ ├── item_layout_home_banner.xml │ │ ├── item_licenses.xml │ │ ├── item_open_api.xml │ │ ├── item_open_api_section.xml │ │ ├── item_post_tree.xml │ │ ├── item_post_tree_tag.xml │ │ ├── item_project_category.xml │ │ ├── layout_add_own_project.xml │ │ ├── layout_avatar.xml │ │ ├── layout_refresh.xml │ │ ├── line_full.xml │ │ ├── nav_menu.xml │ │ ├── no_item_error.xml │ │ └── webview.xml │ │ ├── menu │ │ ├── drawer_menu.xml │ │ ├── navigation.xml │ │ └── search_menu.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── error_item_pic.png │ │ ├── ic_default_head.png │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ ├── ic_launcher_round.png │ │ └── placeholder_item_pic.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── ic_launcher_background.xml │ │ ├── ids.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── xujiaji │ └── wanandroid │ └── ExampleUnitTest.kt ├── banner ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── youth │ │ └── banner │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── youth │ │ └── banner │ │ ├── Banner.java │ │ ├── BannerConfig.java │ │ ├── BannerScroller.java │ │ ├── Transformer.java │ │ ├── WeakHandler.java │ │ ├── listener │ │ ├── OnBannerClickListener.java │ │ └── OnBannerListener.java │ │ ├── loader │ │ ├── ImageLoader.java │ │ └── ImageLoaderInterface.java │ │ ├── transformer │ │ ├── ABaseTransformer.java │ │ ├── AccordionTransformer.java │ │ ├── BackgroundToForegroundTransformer.java │ │ ├── CubeInTransformer.java │ │ ├── CubeOutTransformer.java │ │ ├── DefaultTransformer.java │ │ ├── DepthPageTransformer.java │ │ ├── FlipHorizontalTransformer.java │ │ ├── FlipVerticalTransformer.java │ │ ├── ForegroundToBackgroundTransformer.java │ │ ├── RotateDownTransformer.java │ │ ├── RotateUpTransformer.java │ │ ├── ScaleInOutTransformer.java │ │ ├── StackTransformer.java │ │ ├── TabletTransformer.java │ │ ├── ZoomInTransformer.java │ │ ├── ZoomOutSlideTransformer.java │ │ └── ZoomOutTranformer.java │ │ └── view │ │ └── BannerViewPager.java │ └── res │ ├── animator │ └── scale_with_alpha.xml │ ├── drawable │ ├── black_background.xml │ ├── gray_radius.xml │ ├── no_banner.png │ └── white_radius.xml │ ├── layout │ └── banner.xml │ └── values │ ├── attr.xml │ └── ids.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── json ├── licenses.json ├── plugin_list.json └── version.json ├── pybridge ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── python │ │ ├── bootstrap.py │ │ ├── html_test.py │ │ ├── html_to_json.py │ │ ├── parser_links.py │ │ └── stdlib.zip │ ├── java │ └── com │ │ └── jventura │ │ └── pybridge │ │ ├── AssetExtractor.java │ │ ├── PyBridge.java │ │ └── PyManager.java │ ├── jni │ ├── Android.mk │ ├── Application.mk │ └── pybridge.c │ ├── libs │ ├── armeabi-v7a │ │ ├── libcrystax.so │ │ ├── libpybridge.so │ │ └── libpython3.5m.so │ └── x86 │ │ ├── libcrystax.so │ │ ├── libpybridge.so │ │ └── libpython3.5m.so │ └── res │ └── values │ ├── colors.xml │ ├── dimens.xml │ └── strings.xml ├── settings.gradle └── xu.jks /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/libraries 5 | /.idea/modules.xml 6 | /.idea/workspace.xml 7 | .DS_Store 8 | /build 9 | /captures 10 | .externalNativeBuild 11 | /keystore.properties 12 | .idea/caches/ 13 | .idea/encodings.xml 14 | app/release/ 15 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-architect 2 | show_downloads: ture 3 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/libs/RePluginSdk-1.2.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/app/libs/RePluginSdk-1.2.0.jar -------------------------------------------------------------------------------- /app/src/androidTest/java/com/xujiaji/wanandroid/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid 2 | 3 | import android.support.test.InstrumentationRegistry 4 | import android.support.test.runner.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getTargetContext() 22 | assertEquals("com.xujiaji.wanandroid", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/RefreshLoadViewModel.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid; 2 | 3 | import android.databinding.ObservableList; 4 | 5 | /** 6 | * author: xujiaji 7 | * created on: 2018/8/7 14:04 8 | * description: 9 | */ 10 | public interface RefreshLoadViewModel { 11 | public ObservableList getList(); 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/adapter/FlexboxBindingAdapter.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.adapter; 2 | 3 | import android.content.Context; 4 | import android.databinding.BindingAdapter; 5 | import android.os.Build; 6 | import android.support.v4.content.ContextCompat; 7 | import android.view.Gravity; 8 | import android.view.ViewGroup; 9 | import android.widget.TextView; 10 | 11 | import com.google.android.flexbox.FlexboxLayout; 12 | import com.xujiaji.wanandroid.R; 13 | import com.xujiaji.wanandroid.helper.ViewHelper; 14 | import com.xujiaji.wanandroid.module.main.fragment.post_tree.PostTreeViewModel; 15 | import com.xujiaji.wanandroid.repository.bean.TreeBean; 16 | 17 | /** 18 | * author: xujiaji 19 | * 20 | * created on: 2018/8/19 18:26 21 | * description: 22 | */ 23 | public class FlexboxBindingAdapter { 24 | 25 | @BindingAdapter(value = {"fullFlexData", "postTreeViewModel"}) 26 | public static void fullFlexData(FlexboxLayout layout, TreeBean treeBean, PostTreeViewModel viewModel) { 27 | layout.removeAllViews(); 28 | if (treeBean.getChildren() == null || treeBean.getChildren().size() == 0) return; 29 | Context context = layout.getContext(); 30 | for (TreeBean tree : treeBean.getChildren()) { 31 | TextView textView = new TextView(context); 32 | textView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewHelper.dpToPx(context, 40))); 33 | textView.setTextColor(ContextCompat.getColor(context, R.color.textSecondary)); 34 | textView.setBackgroundResource(R.drawable.btn_rounded_outline); 35 | textView.setGravity(Gravity.CENTER); 36 | textView.setFocusable(true); 37 | textView.setClickable(true); 38 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 39 | textView.setForeground(ContextCompat.getDrawable(context, R.drawable.ripple_theme_small)); 40 | } 41 | textView.setText(tree.getName()); 42 | textView.setOnClickListener(v -> viewModel.mTagClickEvent.setValue(treeBean.setCheckedChild(tree))); 43 | layout.addView(textView); 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/adapter/FragmentsPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.adapter; 2 | 3 | import android.support.annotation.Nullable; 4 | import android.support.v4.app.Fragment; 5 | import android.support.v4.app.FragmentManager; 6 | import android.support.v4.app.FragmentStatePagerAdapter; 7 | 8 | import com.xujiaji.wanandroid.model.FragmentModel; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * author: xujiaji 14 | * created on: 2018/8/4 0:09 15 | * description: 16 | */ 17 | public class FragmentsPagerAdapter extends FragmentStatePagerAdapter { 18 | private List fragments; 19 | 20 | public FragmentsPagerAdapter(FragmentManager fm, List fragments) { 21 | super(fm); 22 | this.fragments = fragments; 23 | } 24 | 25 | @Override 26 | public Fragment getItem(int position) { 27 | return fragments.get(position).getFragment(); 28 | } 29 | 30 | @Override 31 | public int getCount() { 32 | return fragments.size(); 33 | } 34 | 35 | @Nullable 36 | @Override 37 | public CharSequence getPageTitle(int position) { 38 | return fragments.get(position).getTitle(); 39 | } 40 | 41 | public void remove(FragmentModel model) { 42 | if (fragments != null) { 43 | fragments.remove(model); 44 | notifyDataSetChanged(); 45 | } 46 | } 47 | 48 | public void remove(int position) { 49 | if (fragments != null) { 50 | fragments.remove(position); 51 | notifyDataSetChanged(); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/adapter/RefreshCircleStyleBindingAdapter.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.adapter; 2 | 3 | import android.databinding.BindingAdapter; 4 | import android.support.v4.widget.SwipeRefreshLayout; 5 | 6 | import com.xujiaji.wanandroid.R; 7 | 8 | /** 9 | * author: xujiaji 10 | * created on: 2018/8/19 14:12 11 | * description: 为SwipeRefreshLayout添加下拉圈圈的风格 12 | */ 13 | public class RefreshCircleStyleBindingAdapter { 14 | @BindingAdapter("addCircleStyle") 15 | public static void addCircleStyle(SwipeRefreshLayout refreshLayout, boolean isSet) { 16 | if (isSet) { 17 | refreshLayout.setColorSchemeResources(R.color.colorAccent, R.color.colorPrimaryDark, R.color.colorPrimary); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/adapter/RotationBindingAdapter.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.adapter; 2 | 3 | import android.databinding.BindingAdapter; 4 | import android.view.View; 5 | 6 | /** 7 | * author: xujiaji 8 | * created on: 2018/8/19 14:03 9 | * description: 10 | */ 11 | public class RotationBindingAdapter { 12 | @BindingAdapter("rotationAnim") 13 | public static void rotationAnim(View view, int rotation) { 14 | if (view.getRotation() == rotation) return; 15 | view.animate().setDuration(400).rotation(rotation).start(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/adapter/VersionBindingAdapter.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.adapter; 2 | 3 | import android.databinding.BindingAdapter; 4 | import android.widget.TextView; 5 | 6 | import com.xujiaji.mvvmquick.util.VersionUtil; 7 | import com.xujiaji.wanandroid.base.App; 8 | 9 | /** 10 | * author: xujiaji 11 | * created on: 2018/8/29 23:29 12 | * description: 13 | */ 14 | public class VersionBindingAdapter { 15 | 16 | @BindingAdapter("displayVersion") 17 | public static void displayVersion(TextView textView, boolean display) { 18 | if (!display) return; 19 | textView.setText(String.format("Version %s", VersionUtil.getVersionName(App.getInstance()))); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/base/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.base; 2 | 3 | import android.arch.lifecycle.AndroidViewModel; 4 | import android.databinding.ViewDataBinding; 5 | 6 | import com.umeng.analytics.MobclickAgent; 7 | import com.xujiaji.mvvmquick.base.MQActivity; 8 | 9 | /** 10 | * author: xujiaji 11 | * created on: 2018/8/6 11:01 12 | * description: 13 | */ 14 | public abstract class BaseActivity extends MQActivity { 15 | 16 | @Override 17 | protected void onResume() { 18 | super.onResume(); 19 | // MobclickAgent.onResume(this); 20 | } 21 | 22 | @Override 23 | protected void onPause() { 24 | super.onPause(); 25 | // MobclickAgent.onPause(this); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/base/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.base; 2 | 3 | import android.databinding.ViewDataBinding; 4 | import android.support.annotation.NonNull; 5 | 6 | import com.umeng.analytics.MobclickAgent; 7 | import com.xujiaji.mvvmquick.base.MQFragment; 8 | import com.xujiaji.mvvmquick.base.MQViewModel; 9 | 10 | /** 11 | * author: xujiaji 12 | * created on: 2018/8/5 21:07 13 | * description: 14 | */ 15 | public abstract class BaseFragment extends MQFragment { 16 | 17 | @Override 18 | public void onResume() { 19 | super.onResume(); 20 | // MobclickAgent.onPageStart(this.getClass().getSimpleName()); 21 | } 22 | 23 | @Override 24 | public void onPause() { 25 | super.onPause(); 26 | // MobclickAgent.onPageEnd(this.getClass().getSimpleName()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/base/BaseRefreshClickChildViewModel.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.base; 2 | 3 | import android.app.Application; 4 | import android.databinding.ObservableArrayList; 5 | import android.databinding.ObservableList; 6 | import android.support.annotation.NonNull; 7 | 8 | import com.xujiaji.mvvmquick.lifecycle.SingleLiveEvent; 9 | import com.xujiaji.wanandroid.repository.remote.Net; 10 | 11 | /** 12 | * author: xujiaji 13 | * created on: 2018/8/18 22:15 14 | * description: 点击事件触发的不是一级item的情况下 15 | */ 16 | public class BaseRefreshClickChildViewModel extends BaseRefreshViewModel { 17 | 18 | public final SingleLiveEvent mClickChildEvent = new SingleLiveEvent<>(); 19 | 20 | public BaseRefreshClickChildViewModel(@NonNull Application application) { 21 | super(application); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/base/BaseRefreshViewModel.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.base; 2 | 3 | import android.app.Application; 4 | import android.databinding.ObservableArrayList; 5 | import android.databinding.ObservableList; 6 | import android.support.annotation.NonNull; 7 | 8 | import com.xujiaji.mvvmquick.lifecycle.SingleLiveEvent; 9 | import com.xujiaji.wanandroid.repository.remote.Net; 10 | 11 | /** 12 | * author: xujiaji 13 | * created on: 2018/8/18 22:15 14 | * description: 15 | */ 16 | public class BaseRefreshViewModel extends BaseViewModel { 17 | 18 | public final ObservableList items = new ObservableArrayList<>(); 19 | public final SingleLiveEvent mClickEvent = new SingleLiveEvent<>(); 20 | /** 21 | * 更新时的第一页页码 22 | */ 23 | public static final int UPDATE_INDEX = 0; 24 | /** 25 | * 加载初始偏移度 26 | */ 27 | public static final int INIT_LOAD_OFFSET = 0; 28 | 29 | public BaseRefreshViewModel(@NonNull Application application) { 30 | super(application); 31 | } 32 | 33 | @Override 34 | public int timeout() { 35 | return Net.TIME_OUT_READ; 36 | } 37 | 38 | @Override 39 | public int initLoadOffset() { 40 | return INIT_LOAD_OFFSET; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/base/BaseViewModel.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.base; 2 | 3 | import android.app.Application; 4 | import android.support.annotation.NonNull; 5 | 6 | import com.xujiaji.mvvmquick.base.MQViewModel; 7 | import com.xujiaji.wanandroid.repository.remote.Net; 8 | 9 | import javax.inject.Inject; 10 | 11 | import dagger.Lazy; 12 | 13 | /** 14 | * author: xujiaji 15 | * created on: 2018/8/6 10:15 16 | * description: 17 | */ 18 | public class BaseViewModel extends MQViewModel { 19 | 20 | @Inject 21 | protected Lazy net; 22 | 23 | public BaseViewModel(@NonNull Application application) { 24 | super(application); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/config/C.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.config; 2 | 3 | /** 4 | * author: xujiaji 5 | * created on: 2018/8/12 0:20 6 | * description: 配置一些静态常量 7 | */ 8 | public class C { 9 | 10 | /** 11 | * 未知错误 12 | */ 13 | public static final int ERROR_UNKNOWN = -200; 14 | 15 | /** 16 | * NULL 数据 17 | */ 18 | public static final int ERROR_NULL_DATA = -201; 19 | 20 | /** 21 | * 请检查网络 22 | */ 23 | public static final int ERROR_CHECK_LOCAL_NETWORK = -202; 24 | 25 | /** 26 | * 连接超时 27 | */ 28 | public static final int ERROR_CONNECT_OUT_TIME = -203; 29 | 30 | } 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/config/PicConfig.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.config; 2 | 3 | import com.bumptech.glide.request.RequestOptions; 4 | import com.xujiaji.wanandroid.R; 5 | 6 | /** 7 | * author: xujiaji 8 | * created on: 2018/8/7 9:35 9 | * description: 10 | */ 11 | public class PicConfig { 12 | public static RequestOptions itemOptions = new RequestOptions() 13 | .placeholder(R.mipmap.placeholder_item_pic) 14 | .error(R.mipmap.error_item_pic); 15 | 16 | 17 | public static RequestOptions headOptions = new RequestOptions() 18 | .placeholder(R.mipmap.ic_default_head) 19 | .error(R.mipmap.ic_default_head); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/di/AppComponent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 XuJiaji 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xujiaji.wanandroid.di; 18 | 19 | import android.app.Application; 20 | 21 | 22 | import com.xujiaji.wanandroid.base.App; 23 | 24 | import javax.inject.Singleton; 25 | 26 | import dagger.BindsInstance; 27 | import dagger.Component; 28 | import dagger.android.AndroidInjector; 29 | import dagger.android.support.AndroidSupportInjectionModule; 30 | 31 | /** 32 | * author: xujiaji 33 | * created on: 2018/6/12 11:51 34 | * description: 35 | */ 36 | @Singleton 37 | @Component(modules = { 38 | AndroidSupportInjectionModule.class, 39 | AppModule.class, 40 | ActivityBindingModule.class 41 | }) 42 | public interface AppComponent extends AndroidInjector 43 | { 44 | @Component.Builder 45 | interface Builder 46 | { 47 | @BindsInstance Builder application(Application application); 48 | AppComponent build(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/helper/ActivityResultHelper.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.helper; 2 | 3 | import android.content.Intent; 4 | 5 | import com.xujiaji.mvvmquick.base.MQQuickAdapter; 6 | import com.xujiaji.mvvmquick.util.LogUtil; 7 | import com.xujiaji.wanandroid.module.read.ReadActivity; 8 | import com.xujiaji.wanandroid.repository.bean.BlogPostBean; 9 | 10 | import static android.app.Activity.RESULT_OK; 11 | 12 | /** 13 | * author: xujiaji 14 | * created on: 2018/8/14 23:32 15 | * description: 16 | */ 17 | public class ActivityResultHelper { 18 | 19 | // 处理从阅读界面返回文章列表时的数据处理 20 | public static void handlePost(int requestCode, int resultCode, Intent data, MQQuickAdapter adapter) { 21 | if (requestCode == ReadActivity.ACTIVITY_REQUEST_CODE && resultCode == RESULT_OK) { 22 | BlogPostBean postBean = data.getParcelableExtra(BlogPostBean.class.getSimpleName()); 23 | if (postBean == null || adapter.getData().size() < postBean.getIndex()) return; 24 | LogUtil.e3("更新Item index = " + postBean.getIndex()); 25 | adapter.getData().remove(postBean.getIndex()); 26 | adapter.getData().add(postBean.getIndex(), postBean); 27 | adapter.notifyItemChanged(postBean.getIndex()); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/helper/CheckHelper.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.helper; 2 | 3 | import android.text.TextUtils; 4 | 5 | /** 6 | * author: xujiaji 7 | * created on: 2018/8/10 10:09 8 | * description: 9 | */ 10 | public class CheckHelper { 11 | public static boolean isEmailValid(String email) { 12 | return !TextUtils.isEmpty(email) && android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches(); 13 | } 14 | 15 | public static boolean isPasswordValid(String password) { 16 | return password.length() > 5; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/helper/ClassHelper.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.helper; 2 | 3 | import android.support.design.widget.CollapsingToolbarLayout; 4 | import android.text.TextPaint; 5 | 6 | import java.lang.reflect.Field; 7 | 8 | /** 9 | * author: xujiaji 10 | * created on: 2018/9/15 0:30 11 | * description: 12 | */ 13 | public class ClassHelper { 14 | 15 | /** 16 | * 通过反射得到CollapsingToolbarLayout中标题的画笔。通过它得到标题变化中的颜色 17 | */ 18 | public static TextPaint getCollapsingTitlePaint(CollapsingToolbarLayout collapsing) { 19 | try { 20 | Class clazz = Class.forName("android.support.design.widget.CollapsingToolbarLayout"); 21 | Field fieldTextHelper = clazz.getDeclaredField("collapsingTextHelper"); 22 | fieldTextHelper.setAccessible(true); 23 | Object obj = fieldTextHelper.get(collapsing); 24 | 25 | Class clazzHelper = Class.forName("android.support.design.widget.CollapsingTextHelper"); 26 | Field fieldTextPaint = clazzHelper.getDeclaredField("textPaint"); 27 | fieldTextPaint.setAccessible(true); 28 | return (TextPaint) fieldTextPaint.get(obj); 29 | } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { 30 | e.printStackTrace(); 31 | return null; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/helper/ClipHelper.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.helper; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * author: xujiaji 7 | * created on: 2018/8/20 22:55 8 | * description: 9 | */ 10 | public class ClipHelper { 11 | public static boolean copyToClipboard(Context context, String text) { 12 | android.content.ClipboardManager clipboard = (android.content.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); 13 | android.content.ClipData clip = android.content.ClipData.newPlainText("Copied Text", text); 14 | if (clipboard == null) return false; 15 | clipboard.setPrimaryClip(clip); 16 | return true; 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/helper/EmptyViewHelper.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.helper; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.text.TextUtils; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.widget.TextView; 8 | 9 | import com.chad.library.adapter.base.BaseQuickAdapter; 10 | import com.xujiaji.wanandroid.R; 11 | 12 | /** 13 | * author: xujiaji 14 | * created on: 2018/8/25 22:59 15 | * description: 16 | */ 17 | public class EmptyViewHelper { 18 | 19 | public static void initEmpty(RecyclerView viewGroup) { 20 | if (viewGroup.getAdapter() instanceof BaseQuickAdapter) { 21 | ((BaseQuickAdapter) viewGroup.getAdapter()).setEmptyView(R.layout.no_item_archived, viewGroup); 22 | } 23 | } 24 | 25 | public static void setErrEmpty(RecyclerView viewGroup, String errInfo) { 26 | if (viewGroup.getAdapter() instanceof BaseQuickAdapter) { 27 | View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.no_item_error, viewGroup, false); 28 | TextView textView = view.findViewById(R.id.errInfo); 29 | if (TextUtils.isEmpty(errInfo)) { 30 | textView.setVisibility(View.GONE); 31 | } else { 32 | textView.setText(errInfo); 33 | } 34 | ((BaseQuickAdapter) viewGroup.getAdapter()).setEmptyView(view); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/helper/FabPopLayoutHelper.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.helper; 2 | 3 | import android.support.design.widget.FloatingActionButton; 4 | import android.view.View; 5 | 6 | /** 7 | * author: xujiaji 8 | * created on: 2018/8/8 12:26 9 | * description: 10 | */ 11 | public class FabPopLayoutHelper { 12 | 13 | private static boolean rotate = false; 14 | 15 | public static void initPopLayout(FloatingActionButton fab, View backDrop, View ... popLayouts) { 16 | rotate = false; 17 | if (popLayouts == null || popLayouts.length == 0 || backDrop == null) return; 18 | 19 | for (View ll: popLayouts) { 20 | AnimHelper.initShowOut(ll); 21 | } 22 | 23 | fab.setOnClickListener(new View.OnClickListener() { 24 | @Override 25 | public void onClick(View v) { 26 | toggleFabMode(fab, popLayouts, backDrop); 27 | } 28 | }); 29 | 30 | backDrop.setOnClickListener(new View.OnClickListener() { 31 | @Override 32 | public void onClick(View v) { 33 | toggleFabMode(fab, popLayouts, backDrop); 34 | } 35 | }); 36 | 37 | } 38 | 39 | 40 | private static void toggleFabMode(View v, View[] popLayouts, View backDrop) { 41 | 42 | rotate = AnimHelper.rotateFab(v, !rotate); 43 | v.setTag(rotate); 44 | if (rotate) { 45 | for (View ll: popLayouts) { 46 | AnimHelper.showIn(ll); 47 | } 48 | backDrop.setVisibility(View.VISIBLE); 49 | } else { 50 | for (View ll: popLayouts) { 51 | AnimHelper.showOut(ll); 52 | } 53 | backDrop.setVisibility(View.GONE); 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/helper/GlideImageLoader.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.helper; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.widget.ImageView; 7 | 8 | import com.bumptech.glide.Glide; 9 | import com.xujiaji.wanandroid.R; 10 | import com.xujiaji.wanandroid.config.PicConfig; 11 | import com.xujiaji.wanandroid.repository.bean.BannerBean; 12 | import com.youth.banner.loader.ImageLoader; 13 | import com.youth.banner.loader.ImageLoaderInterface; 14 | 15 | public class GlideImageLoader implements ImageLoaderInterface { 16 | 17 | @Override 18 | public void displayImage(Context context, Object bannerData, View view) { 19 | BannerBean bannerBean = (BannerBean) bannerData; 20 | //Glide 加载图片简单用法 21 | Glide.with(context) 22 | .applyDefaultRequestOptions(PicConfig.itemOptions) 23 | .load(bannerBean.getImagePath()) 24 | .into((ImageView) view.findViewById(R.id.bannerImg)); 25 | } 26 | 27 | @Override 28 | public View createImageView(Context context) { 29 | return LayoutInflater.from(context).inflate(R.layout.item_layout_home_banner, null); 30 | } 31 | 32 | //提供createImageView 方法,如果不用可以不重写这个方法,主要是方便自定义ImageView的创建 33 | // @Override 34 | // public ImageView createImageView(Context context) { 35 | // //使用fresco,需要创建它提供的ImageView,当然你也可以用自己自定义的具有图片加载功能的ImageView 36 | // SimpleDraweeView simpleDraweeView=new SimpleDraweeView(context); 37 | // return simpleDraweeView; 38 | // } 39 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/helper/ToastHelper.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.helper; 2 | 3 | import android.widget.Toast; 4 | 5 | import com.xujiaji.wanandroid.R; 6 | import com.xujiaji.wanandroid.base.App; 7 | 8 | import es.dmoral.toasty.Toasty; 9 | 10 | /** 11 | * author: xujiaji 12 | * created on: 2018/8/9 15:01 13 | * description: 14 | */ 15 | public class ToastHelper { 16 | 17 | public static void info(String msg) { 18 | Toasty.info(App.getInstance(), msg, Toast.LENGTH_SHORT, true).show(); 19 | } 20 | 21 | public static void success(String msg) { 22 | Toasty.success(App.getInstance(), msg, Toast.LENGTH_SHORT, true).show(); 23 | } 24 | 25 | public static void error(String msg) { 26 | Toasty.error(App.getInstance(), msg, Toast.LENGTH_SHORT, true).show(); 27 | } 28 | 29 | public static void warning(String msg) { 30 | Toasty.warning(App.getInstance(), msg, Toast.LENGTH_SHORT, true).show(); 31 | } 32 | 33 | public static void successCollect() { 34 | success(App.getInstance().getString(R.string.success_collect)); 35 | } 36 | 37 | public static void successUncollect() { 38 | success(App.getInstance().getString(R.string.success_uncollect)); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/helper/TypeFaceHelper.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.helper; 2 | 3 | import android.content.Context; 4 | import android.graphics.Typeface; 5 | import android.widget.TextView; 6 | 7 | /** 8 | * Created by Kosh on 17/12/15 10:25 PM 9 | */ 10 | public class TypeFaceHelper { 11 | 12 | private static Typeface typeFace; 13 | 14 | public static void generateTypeface(Context context) { 15 | typeFace = Typeface.createFromAsset(context.getAssets(), "fonts/app_font.ttf"); 16 | } 17 | 18 | public static void applyTypeface(TextView textView) { 19 | textView.setTypeface(typeFace); 20 | } 21 | 22 | public static Typeface getTypeface() { 23 | return typeFace; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/helper/UpdateHelper.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.helper; 2 | 3 | import android.app.Activity; 4 | 5 | /** 6 | * author: xujiaji 7 | * created on: 2018/8/26 23:57 8 | * description: 9 | */ 10 | public class UpdateHelper { 11 | public static void handle(Activity activity) { 12 | // UpdateAppManager updateAppManager = new UpdateAppManager 13 | // .Builder() 14 | // .setActivity(activity) 15 | // .setHttpManager(new UpdateAppHttpUtil()) 16 | // .build(); 17 | // updateAppManager.showDialogFragment(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/model/FragmentModel.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.model; 2 | 3 | import com.xujiaji.wanandroid.base.BaseFragment; 4 | 5 | /** 6 | * author: xujiaji 7 | * created on: 2018/8/4 0:13 8 | * description: 9 | */ 10 | public class FragmentModel { 11 | private String title; 12 | private BaseFragment fragment; 13 | 14 | public FragmentModel(String title, BaseFragment fragment) { 15 | this.title = title; 16 | this.fragment = fragment; 17 | } 18 | 19 | public String getTitle() { 20 | return title; 21 | } 22 | 23 | public BaseFragment getFragment() { 24 | return fragment; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/model/RefreshLoadModel.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.model; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | /** 6 | * author: xujiaji 7 | * created on: 2018/8/7 12:20 8 | * description: 9 | */ 10 | public class RefreshLoadModel { 11 | 12 | @NotNull 13 | public final T data; 14 | @NotNull 15 | public final boolean isRefresh;//是不是刷新就是加载 16 | 17 | public RefreshLoadModel(@NotNull T data, @NotNull boolean isRefresh) { 18 | this.data = data; 19 | this.isRefresh = isRefresh; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/about/AboutActivity.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.about; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.annotation.NonNull; 7 | 8 | import com.xujiaji.mvvmquick.base.NoneViewModel; 9 | import com.xujiaji.wanandroid.base.BaseActivity; 10 | import com.xujiaji.wanandroid.databinding.ActivityAboutBinding; 11 | import com.xujiaji.wanandroid.helper.ToolbarHelper; 12 | import com.xujiaji.wanandroid.module.license.LicenseActivity; 13 | 14 | /** 15 | * author: xujiaji 16 | * created on: 2018/8/29 22:50 17 | * description: 18 | */ 19 | public class AboutActivity extends BaseActivity { 20 | 21 | public static void launch(Context context) { 22 | context.startActivity(new Intent(context, AboutActivity.class)); 23 | } 24 | 25 | @Override 26 | protected void onCreate(Bundle savedInstanceState) { 27 | ToolbarHelper.initTranslucent(this); 28 | super.onCreate(savedInstanceState); 29 | } 30 | 31 | @Override 32 | public void onBinding(@NonNull ActivityAboutBinding binding) { 33 | ToolbarHelper.initMarginTopDiffBar(binding.btnBack); 34 | binding.btnBack.setOnClickListener(v -> finish()); 35 | binding.btnLookLibraries.setOnClickListener(v -> LicenseActivity.launch(AboutActivity.this)); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/category_detail/CategoryDetailModule.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.category_detail; 2 | 3 | import com.xujiaji.mvvmquick.di.FragmentScoped; 4 | import com.xujiaji.wanandroid.module.main.fragment.posts.MainBlogPostsFragment; 5 | import com.youth.banner.Banner; 6 | 7 | import dagger.BindsOptionalOf; 8 | import dagger.Module; 9 | import dagger.Provides; 10 | import dagger.android.ContributesAndroidInjector; 11 | 12 | /** 13 | * author: xujiaji 14 | * created on: 2018/9/15 12:41 15 | * description: 16 | */ 17 | @Module 18 | public abstract class CategoryDetailModule { 19 | 20 | 21 | @FragmentScoped 22 | @ContributesAndroidInjector 23 | abstract MainBlogPostsFragment contributeMainBlogPostsFragment(); 24 | 25 | 26 | @Provides 27 | public static MainBlogPostsFragment provideBlogModel() { 28 | return new MainBlogPostsFragment(); 29 | } 30 | 31 | @BindsOptionalOf 32 | public abstract Banner optionalBanner(); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/category_detail/CategoryDetailViewModel.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.category_detail; 2 | 3 | import android.app.Application; 4 | import android.support.annotation.NonNull; 5 | 6 | import com.xujiaji.wanandroid.base.BaseViewModel; 7 | 8 | import javax.inject.Inject; 9 | import javax.inject.Singleton; 10 | 11 | /** 12 | * author: xujiaji 13 | * created on: 2018/9/15 0:41 14 | * description: 15 | */ 16 | @Singleton 17 | public class CategoryDetailViewModel extends BaseViewModel { 18 | 19 | // public final ObservableField thumb = new ObservableField<>(); 20 | 21 | @Inject 22 | public CategoryDetailViewModel(@NonNull Application application) { 23 | super(application); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/license/LicenseAdapter.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.license; 2 | 3 | import com.xujiaji.mvvmquick.base.MQQuickAdapter; 4 | import com.xujiaji.mvvmquick.base.MQViewHolder; 5 | import com.xujiaji.mvvmquick.callback.GeneralClickCallback; 6 | import com.xujiaji.wanandroid.R; 7 | import com.xujiaji.wanandroid.databinding.ItemLicensesBinding; 8 | import com.xujiaji.wanandroid.repository.bean.LicenseBean; 9 | 10 | import javax.inject.Inject; 11 | 12 | /** 13 | * author: xujiaji 14 | * created on: 2018/8/30 19:50 15 | * description: 16 | */ 17 | public class LicenseAdapter extends MQQuickAdapter { 18 | 19 | @Inject 20 | LicenseViewModel mViewModel; 21 | 22 | @Inject 23 | public LicenseAdapter() { 24 | super(R.layout.item_licenses); 25 | } 26 | 27 | @Override 28 | protected void onBinding(ItemLicensesBinding binding) { 29 | binding.setCallback((GeneralClickCallback) mViewModel.mClickEvent::setValue); 30 | } 31 | 32 | @Override 33 | protected void convert(MQViewHolder helper, LicenseBean item) { 34 | helper.binding.setLicenseBean(item); 35 | helper.binding.executePendingBindings(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/license/LicenseViewModel.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.license; 2 | 3 | import android.app.Application; 4 | import android.support.annotation.NonNull; 5 | 6 | import com.xujiaji.wanandroid.base.BaseRefreshViewModel; 7 | import com.xujiaji.wanandroid.repository.bean.LicenseBean; 8 | import com.xujiaji.wanandroid.repository.remote.NetLiveEvent; 9 | 10 | import java.util.List; 11 | 12 | import javax.inject.Inject; 13 | import javax.inject.Singleton; 14 | 15 | /** 16 | * author: xujiaji 17 | * created on: 2018/8/30 19:35 18 | * description: 19 | */ 20 | @Singleton 21 | public class LicenseViewModel extends BaseRefreshViewModel { 22 | 23 | private final NetLiveEvent> mLicensesData = new NetLiveEvent<>(); 24 | 25 | @Inject 26 | public LicenseViewModel(@NonNull Application application) { 27 | super(application); 28 | } 29 | 30 | @Override 31 | public void onListRefresh() { 32 | mLicensesData.setValue(net.get().getLicenses()); 33 | } 34 | 35 | public NetLiveEvent> getObservableLicensesData() { 36 | mLicensesData.setValue(net.get().getLicenses()); 37 | return mLicensesData; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/like/LikeAdapter.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.like; 2 | 3 | import android.support.annotation.Nullable; 4 | 5 | import com.xujiaji.mvvmquick.base.MQQuickAdapter; 6 | import com.xujiaji.mvvmquick.base.MQViewHolder; 7 | import com.xujiaji.mvvmquick.base.MQViewModel; 8 | import com.xujiaji.mvvmquick.callback.GeneralClickCallback; 9 | import com.xujiaji.wanandroid.R; 10 | import com.xujiaji.wanandroid.databinding.ItemBlogPostBinding; 11 | import com.xujiaji.wanandroid.module.main.fragment.posts.MainBlogPostsViewModel; 12 | import com.xujiaji.wanandroid.repository.bean.BlogPostBean; 13 | 14 | import javax.inject.Inject; 15 | 16 | /** 17 | * author: xujiaji 18 | * created on: 2018/8/6 11:22 19 | * description: 20 | */ 21 | public class LikeAdapter extends MQQuickAdapter { 22 | 23 | @Inject 24 | LikeViewModel mViewModel; 25 | 26 | @Inject 27 | public LikeAdapter() { 28 | super(R.layout.item_blog_post); 29 | } 30 | 31 | @Override 32 | protected void onBinding(ItemBlogPostBinding binding) { 33 | binding.setCallback((GeneralClickCallback) mViewModel.mClickEvent::setValue); 34 | } 35 | 36 | @Override 37 | protected void convert(MQViewHolder helper, BlogPostBean item) { 38 | item.setIndex(getData().indexOf(item)); 39 | helper.binding.setBlogPost(item); 40 | helper.binding.executePendingBindings(); 41 | } 42 | 43 | @Nullable 44 | @Override 45 | protected MQViewModel getViewModel() { 46 | return mViewModel; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/like/LikeViewModel.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.like; 2 | 3 | import android.app.Application; 4 | import android.arch.lifecycle.MutableLiveData; 5 | import android.databinding.ObservableList; 6 | import android.support.annotation.NonNull; 7 | 8 | import com.xujiaji.mvvmquick.lifecycle.SingleLiveEvent; 9 | import com.xujiaji.wanandroid.RefreshLoadViewModel; 10 | import com.xujiaji.wanandroid.base.BaseRefreshViewModel; 11 | import com.xujiaji.wanandroid.model.RefreshLoadModel; 12 | import com.xujiaji.wanandroid.repository.bean.BlogPostBean; 13 | import com.xujiaji.wanandroid.repository.bean.PageBean; 14 | import com.xujiaji.wanandroid.repository.bean.Result; 15 | 16 | import javax.inject.Inject; 17 | import javax.inject.Singleton; 18 | 19 | /** 20 | * author: xujiaji 21 | * created on: 2018/8/28 20:05 22 | * description: 23 | */ 24 | @Singleton 25 | public class LikeViewModel extends BaseRefreshViewModel implements RefreshLoadViewModel { 26 | 27 | private final SingleLiveEvent>>>> mCollectsLiveData = new SingleLiveEvent<>(); 28 | 29 | 30 | @Inject 31 | public LikeViewModel(@NonNull Application application) { 32 | super(application); 33 | } 34 | 35 | @Override 36 | public void onListRefresh() { 37 | super.onListRefresh(); 38 | mCollectsLiveData.setValue(new RefreshLoadModel<>(net.get().getCollects(UPDATE_INDEX), true)); 39 | } 40 | 41 | @Override 42 | public void onListLoad(int offset) { 43 | mCollectsLiveData.postValue(new RefreshLoadModel<>(net.get().getCollects(offset), false)); 44 | } 45 | 46 | 47 | public SingleLiveEvent>>>> getObservableCollects() { 48 | mCollectsLiveData.setValue(new RefreshLoadModel<>(net.get().getCollects(UPDATE_INDEX), true)); 49 | return mCollectsLiveData; 50 | } 51 | 52 | @Override 53 | public ObservableList getList() { 54 | return items; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/login/LoginModule.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.login; 2 | 3 | import dagger.Module; 4 | 5 | /** 6 | * author: xujiaji 7 | * created on: 2018/8/9 22:17 8 | * description: 9 | */ 10 | @Module 11 | public class LoginModule { 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/login/LoginViewModel.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.login; 2 | 3 | import android.app.Application; 4 | import android.arch.lifecycle.MutableLiveData; 5 | import android.support.annotation.NonNull; 6 | 7 | import com.xujiaji.mvvmquick.lifecycle.SingleLiveEvent; 8 | import com.xujiaji.wanandroid.base.BaseViewModel; 9 | import com.xujiaji.wanandroid.repository.bean.Result; 10 | import com.xujiaji.wanandroid.repository.bean.UserBean; 11 | import com.xujiaji.wanandroid.repository.remote.NetLiveEvent; 12 | 13 | import javax.inject.Inject; 14 | import javax.inject.Singleton; 15 | 16 | /** 17 | * author: xujiaji 18 | * created on: 2018/8/11 19:22 19 | * description: 20 | */ 21 | @Singleton 22 | public class LoginViewModel extends BaseViewModel { 23 | 24 | private final NetLiveEvent mRegisterUserBean = new NetLiveEvent<>(); 25 | private final NetLiveEvent mLoginUserBean = new NetLiveEvent<>(); 26 | 27 | @Inject 28 | public LoginViewModel(@NonNull Application application) { 29 | super(application); 30 | } 31 | 32 | public NetLiveEvent postObservableLogin(String username, String password) { 33 | mLoginUserBean.setValue(net.get().postLogin(username, password)); 34 | return mLoginUserBean; 35 | } 36 | 37 | public NetLiveEvent postObservableRegister(String username, String password) { 38 | mRegisterUserBean.setValue(net.get().postRegister(username, password)); 39 | return mRegisterUserBean; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/main/fragment/MenuDrawerFragment.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.main.fragment; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.design.widget.NavigationView; 5 | import android.view.MenuItem; 6 | 7 | import com.xujiaji.mvvmquick.base.MQViewModel; 8 | import com.xujiaji.mvvmquick.di.ActivityScoped; 9 | import com.xujiaji.wanandroid.R; 10 | import com.xujiaji.wanandroid.base.BaseFragment; 11 | import com.xujiaji.wanandroid.databinding.DrawerFragmentMenuBinding; 12 | import com.xujiaji.wanandroid.helper.ToastHelper; 13 | import com.xujiaji.wanandroid.module.main.MainActivity; 14 | 15 | import javax.inject.Inject; 16 | 17 | /** 18 | * author: xujiaji 19 | * created on: 2018/8/4 9:50 20 | * description: 21 | */ 22 | @ActivityScoped 23 | public class MenuDrawerFragment extends BaseFragment implements NavigationView.OnNavigationItemSelectedListener { 24 | 25 | @Inject 26 | MainActivity mainActivity; 27 | 28 | @Inject 29 | public MenuDrawerFragment() {} 30 | 31 | @Override 32 | public void onBinding(@NonNull DrawerFragmentMenuBinding binding) { 33 | binding.mainNav.setNavigationItemSelectedListener(this); 34 | } 35 | 36 | @Override 37 | public boolean onNavigationItemSelected(@NonNull MenuItem item) { 38 | mainActivity.changeBottomNavigation(item.getItemId()); 39 | return true; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/main/fragment/boxes/MainBoxesAdapter.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.main.fragment.boxes; 2 | 3 | import com.xujiaji.mvvmquick.base.MQQuickAdapter; 4 | import com.xujiaji.mvvmquick.base.MQViewHolder; 5 | import com.xujiaji.mvvmquick.callback.GeneralClickCallback; 6 | import com.xujiaji.wanandroid.R; 7 | import com.xujiaji.wanandroid.databinding.ItemBoxBinding; 8 | import com.xujiaji.wanandroid.repository.bean.BoxBean; 9 | 10 | import javax.inject.Inject; 11 | 12 | /** 13 | * author: xujiaji 14 | * created on: 2018/8/15 10:46 15 | * description: 16 | */ 17 | public class MainBoxesAdapter extends MQQuickAdapter { 18 | 19 | private MainBoxesViewModel mViewModel; 20 | 21 | @Inject 22 | public MainBoxesAdapter(MainBoxesViewModel viewModel) { 23 | super(R.layout.item_box); 24 | this.mViewModel = viewModel; 25 | } 26 | 27 | @Override 28 | protected void onBinding(ItemBoxBinding binding) { 29 | binding.setCallback((GeneralClickCallback) mViewModel.mClickEvent::setValue); 30 | binding.setClickGithubCallback((GeneralClickCallback) mViewModel.mClickGithubEvent::setValue); 31 | } 32 | 33 | @Override 34 | protected void convert(MQViewHolder helper, BoxBean item) { 35 | helper.binding.setBoxBean(item); 36 | helper.binding.executePendingBindings(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/main/fragment/boxes/MainBoxesViewModel.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.main.fragment.boxes; 2 | 3 | import android.app.Application; 4 | import android.support.annotation.NonNull; 5 | 6 | import com.xujiaji.mvvmquick.lifecycle.SingleLiveEvent; 7 | import com.xujiaji.wanandroid.base.BaseRefreshViewModel; 8 | import com.xujiaji.wanandroid.repository.bean.BoxBean; 9 | import com.xujiaji.wanandroid.repository.remote.NetLiveEvent; 10 | 11 | import java.util.List; 12 | 13 | import javax.inject.Inject; 14 | import javax.inject.Singleton; 15 | 16 | /** 17 | * author: xujiaji 18 | * created on: 2018/8/15 10:52 19 | * description: 20 | */ 21 | @Singleton 22 | public class MainBoxesViewModel extends BaseRefreshViewModel { 23 | 24 | public final SingleLiveEvent mClickGithubEvent = new SingleLiveEvent<>(); 25 | 26 | private final NetLiveEvent> mBoxes = new NetLiveEvent<>(); 27 | 28 | @Inject 29 | public MainBoxesViewModel(@NonNull Application application) { 30 | super(application); 31 | } 32 | 33 | @Override 34 | public void onListRefresh() { 35 | super.onListRefresh(); 36 | mBoxes.setValue(net.get().getBoxes()); 37 | } 38 | 39 | public NetLiveEvent> getBoxes() { 40 | mBoxes.setValue(net.get().getBoxes()); 41 | return mBoxes; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/main/fragment/friend_link/FriendLinkAdapter.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.main.fragment.friend_link; 2 | 3 | import com.xujiaji.mvvmquick.base.MQQuickAdapter; 4 | import com.xujiaji.mvvmquick.base.MQViewHolder; 5 | import com.xujiaji.mvvmquick.callback.GeneralClickCallback; 6 | import com.xujiaji.wanandroid.R; 7 | import com.xujiaji.wanandroid.databinding.ItemFriendLinkBinding; 8 | import com.xujiaji.wanandroid.repository.bean.FriendLinkBean; 9 | 10 | import javax.inject.Inject; 11 | 12 | /** 13 | * author: xujiaji 14 | * created on: 2018/8/19 17:18 15 | * description: 16 | */ 17 | public class FriendLinkAdapter extends MQQuickAdapter { 18 | 19 | @Inject 20 | FriendLinkViewModel mViewModel; 21 | 22 | @Inject 23 | public FriendLinkAdapter() { 24 | super(R.layout.item_friend_link); 25 | } 26 | 27 | @Override 28 | protected void onBinding(ItemFriendLinkBinding binding) { 29 | binding.setCallback((GeneralClickCallback) mViewModel.mClickEvent::setValue); 30 | } 31 | 32 | @Override 33 | protected void convert(MQViewHolder helper, FriendLinkBean item) { 34 | helper.binding.setFriendLinkBean(item); 35 | helper.binding.executePendingBindings(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/main/fragment/friend_link/FriendLinkFragment.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.main.fragment.friend_link; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.v7.widget.GridLayoutManager; 5 | import android.text.TextUtils; 6 | 7 | import com.xujiaji.mvvmquick.di.ActivityScoped; 8 | import com.xujiaji.wanandroid.base.BaseFragment; 9 | import com.xujiaji.wanandroid.databinding.LayoutRefreshBinding; 10 | import com.xujiaji.wanandroid.helper.EmptyViewHelper; 11 | import com.xujiaji.wanandroid.module.read.ReadActivity; 12 | import com.xujiaji.wanandroid.repository.bean.FriendLinkBean; 13 | import com.xujiaji.wanandroid.repository.remote.DataCallbackImp; 14 | 15 | import java.util.List; 16 | 17 | import javax.inject.Inject; 18 | 19 | /** 20 | * author: xujiaji 21 | * created on: 2018/8/22 17:22 22 | * description: 23 | */ 24 | @ActivityScoped 25 | public class FriendLinkFragment extends BaseFragment { 26 | 27 | @Inject 28 | FriendLinkAdapter mAdapter; 29 | 30 | @Inject 31 | public FriendLinkFragment() {} 32 | 33 | @Override 34 | public void onBinding(@NonNull LayoutRefreshBinding binding) { 35 | binding.setNoLine(true); 36 | } 37 | 38 | @Override 39 | public void onObserveViewModel(@NonNull FriendLinkViewModel viewModel) { 40 | super.onObserveViewModel(viewModel); 41 | binding.setRefreshViewModel(viewModel); 42 | binding.list.setLayoutManager(new GridLayoutManager(getActivity(), 2)); 43 | mAdapter.bindToRecyclerView(binding.list); 44 | EmptyViewHelper.initEmpty(binding.list); 45 | 46 | viewModel.getObservableFriendLinksData().observeData(this, new DataCallbackImp>(binding.refresh) { 47 | @Override 48 | public void success(List bean) { 49 | viewModel.items.clear(); 50 | viewModel.items.addAll(bean); 51 | } 52 | }); 53 | 54 | viewModel.mClickEvent.observe(this, friendLinkBean -> ReadActivity.launch(FriendLinkFragment.this, TextUtils.isEmpty(friendLinkBean.getTitle()) ? friendLinkBean.getUrl() : friendLinkBean.getTitle(), friendLinkBean.getUrl())); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/main/fragment/friend_link/FriendLinkViewModel.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.main.fragment.friend_link; 2 | 3 | import android.app.Application; 4 | import android.support.annotation.NonNull; 5 | 6 | import com.xujiaji.wanandroid.base.BaseRefreshViewModel; 7 | import com.xujiaji.wanandroid.repository.bean.FriendLinkBean; 8 | import com.xujiaji.wanandroid.repository.remote.NetLiveEvent; 9 | 10 | import java.util.List; 11 | 12 | import javax.inject.Inject; 13 | import javax.inject.Singleton; 14 | 15 | /** 16 | * author: xujiaji 17 | * created on: 2018/8/25 12:40 18 | * description: 19 | */ 20 | @Singleton 21 | public class FriendLinkViewModel extends BaseRefreshViewModel { 22 | 23 | private final NetLiveEvent> mFriendLinksData = new NetLiveEvent<>(); 24 | 25 | @Inject 26 | public FriendLinkViewModel(@NonNull Application application) { 27 | super(application); 28 | } 29 | 30 | @Override 31 | public void onListRefresh() { 32 | mFriendLinksData.setValue(net.get().getFriendLinks()); 33 | } 34 | 35 | public NetLiveEvent> getObservableFriendLinksData() { 36 | mFriendLinksData.setValue(net.get().getFriendLinks()); 37 | return mFriendLinksData; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/main/fragment/openapis/OpenAPISFragment.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.main.fragment.openapis; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.chad.library.adapter.base.entity.MultiItemEntity; 6 | import com.xujiaji.mvvmquick.di.ActivityScoped; 7 | import com.xujiaji.wanandroid.base.BaseFragment; 8 | import com.xujiaji.wanandroid.databinding.LayoutRefreshBinding; 9 | import com.xujiaji.wanandroid.helper.EmptyViewHelper; 10 | import com.xujiaji.wanandroid.module.read.ReadActivity; 11 | import com.xujiaji.wanandroid.repository.bean.ThreeAPIBean; 12 | import com.xujiaji.wanandroid.repository.remote.DataCallbackImp; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | import javax.inject.Inject; 18 | 19 | /** 20 | * author: xujiaji 21 | * created on: 2018/8/18 21:29 22 | * description: 23 | */ 24 | @ActivityScoped 25 | public class OpenAPISFragment extends BaseFragment { 26 | 27 | OpenAPISAdapter mAdapter; 28 | 29 | @Inject 30 | public OpenAPISFragment() {} 31 | 32 | @Override 33 | public void onBinding(@NonNull LayoutRefreshBinding binding) { 34 | 35 | } 36 | 37 | @Override 38 | public void onObserveViewModel(@NonNull OpenAPISViewModel viewModel) { 39 | super.onObserveViewModel(viewModel); 40 | binding.setRefreshViewModel(viewModel); 41 | mAdapter = new OpenAPISAdapter(viewModel); 42 | mAdapter.bindToRecyclerView(binding.list); 43 | EmptyViewHelper.initEmpty(binding.list); 44 | 45 | viewModel.getObservableThreeAPIS().observeData(this, new DataCallbackImp>(binding.refresh) { 46 | @Override 47 | public void success(List bean) { 48 | ArrayList src = new ArrayList<>(); 49 | for (ThreeAPIBean t : bean) { 50 | src.add(t); 51 | t.setSubItems(t.getLinks()); 52 | } 53 | mAdapter.setNewData(src); 54 | mAdapter.expandAll(); 55 | } 56 | }); 57 | 58 | viewModel.mClickChildEvent.observe(this, linkBean -> ReadActivity.launch(OpenAPISFragment.this, linkBean.getName(), linkBean.getUrl())); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/main/fragment/openapis/OpenAPISViewModel.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.main.fragment.openapis; 2 | 3 | import android.app.Application; 4 | import android.support.annotation.NonNull; 5 | 6 | import com.xujiaji.mvvmquick.lifecycle.SingleLiveEvent; 7 | import com.xujiaji.wanandroid.base.BaseRefreshClickChildViewModel; 8 | import com.xujiaji.wanandroid.base.BaseRefreshViewModel; 9 | import com.xujiaji.wanandroid.repository.bean.ThreeAPIBean; 10 | import com.xujiaji.wanandroid.repository.remote.NetLiveEvent; 11 | 12 | import java.util.List; 13 | 14 | import javax.inject.Inject; 15 | import javax.inject.Singleton; 16 | 17 | /** 18 | * author: xujiaji 19 | * created on: 2018/8/18 22:47 20 | * description: 21 | */ 22 | @Singleton 23 | public class OpenAPISViewModel extends BaseRefreshClickChildViewModel { 24 | 25 | private final NetLiveEvent> mThreeAPIListData = new NetLiveEvent<>(); 26 | 27 | @Inject 28 | public OpenAPISViewModel(@NonNull Application application) { 29 | super(application); 30 | } 31 | 32 | @Override 33 | public void onListRefresh() { 34 | mThreeAPIListData.setValue(net.get().getThreeAPIBean()); 35 | } 36 | 37 | public NetLiveEvent> getObservableThreeAPIS() { 38 | mThreeAPIListData.setValue(net.get().getThreeAPIBean()); 39 | return mThreeAPIListData; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/main/fragment/post_tree/PostTreeAdapter.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.main.fragment.post_tree; 2 | 3 | import com.xujiaji.mvvmquick.base.MQQuickAdapter; 4 | import com.xujiaji.mvvmquick.base.MQViewHolder; 5 | import com.xujiaji.mvvmquick.callback.GeneralClickCallback; 6 | import com.xujiaji.wanandroid.R; 7 | import com.xujiaji.wanandroid.databinding.ItemPostTreeBinding; 8 | import com.xujiaji.wanandroid.repository.bean.TreeBean; 9 | 10 | import javax.inject.Inject; 11 | 12 | /** 13 | * author: xujiaji 14 | * created on: 2018/8/19 17:18 15 | * description: 16 | */ 17 | public class PostTreeAdapter extends MQQuickAdapter { 18 | 19 | @Inject 20 | PostTreeViewModel mViewModel; 21 | 22 | @Inject 23 | public PostTreeAdapter() { 24 | super(R.layout.item_post_tree); 25 | } 26 | 27 | @Override 28 | protected void onBinding(ItemPostTreeBinding binding) { 29 | binding.setCallback((GeneralClickCallback) mViewModel.mClickEvent::setValue); 30 | binding.setViewModel(mViewModel); 31 | } 32 | 33 | @Override 34 | protected void convert(MQViewHolder helper, TreeBean item) { 35 | helper.binding.setPostTree(item); 36 | helper.binding.executePendingBindings(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/main/fragment/post_tree/PostTreeFragment.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.main.fragment.post_tree; 2 | 3 | import android.arch.lifecycle.Observer; 4 | import android.support.annotation.NonNull; 5 | import android.support.annotation.Nullable; 6 | 7 | import com.xujiaji.mvvmquick.di.ActivityScoped; 8 | import com.xujiaji.wanandroid.base.BaseFragment; 9 | import com.xujiaji.wanandroid.databinding.LayoutRefreshBinding; 10 | import com.xujiaji.wanandroid.helper.EmptyViewHelper; 11 | import com.xujiaji.wanandroid.helper.ToastHelper; 12 | import com.xujiaji.wanandroid.module.category_detail.CategoryDetailActivity; 13 | import com.xujiaji.wanandroid.repository.bean.TreeBean; 14 | import com.xujiaji.wanandroid.repository.remote.DataCallbackImp; 15 | 16 | import java.util.List; 17 | 18 | import javax.inject.Inject; 19 | 20 | /** 21 | * author: xujiaji 22 | * created on: 2018/8/19 17:08 23 | * description: 24 | */ 25 | @ActivityScoped 26 | public class PostTreeFragment extends BaseFragment { 27 | 28 | @Inject 29 | PostTreeAdapter mAdapter; 30 | 31 | @Inject 32 | public PostTreeFragment() {} 33 | 34 | @Override 35 | public void onBinding(@NonNull LayoutRefreshBinding binding) { 36 | mAdapter.bindToRecyclerView(binding.list); 37 | EmptyViewHelper.initEmpty(binding.list); 38 | } 39 | 40 | @Override 41 | public void onObserveViewModel(@NonNull PostTreeViewModel viewModel) { 42 | super.onObserveViewModel(viewModel); 43 | binding.setRefreshViewModel(viewModel); 44 | viewModel.getObservablePostTree().observeData(this, new DataCallbackImp>(binding.refresh) { 45 | 46 | @Override 47 | public void success(List bean) { 48 | viewModel.items.clear(); 49 | viewModel.items.addAll(bean); 50 | } 51 | }); 52 | 53 | viewModel.mTagClickEvent.observe(this, new Observer() { 54 | @Override 55 | public void onChanged(@Nullable TreeBean treeBean) { 56 | // ToastHelper.info(treeBean.getName()); 57 | CategoryDetailActivity.launch(getActivity(), treeBean); 58 | } 59 | }); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/main/fragment/post_tree/PostTreeViewModel.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.main.fragment.post_tree; 2 | 3 | import android.app.Application; 4 | import android.support.annotation.NonNull; 5 | 6 | import com.xujiaji.mvvmquick.lifecycle.SingleLiveEvent; 7 | import com.xujiaji.wanandroid.base.BaseRefreshViewModel; 8 | import com.xujiaji.wanandroid.repository.bean.TreeBean; 9 | import com.xujiaji.wanandroid.repository.remote.NetLiveEvent; 10 | 11 | import java.util.List; 12 | 13 | import javax.inject.Inject; 14 | import javax.inject.Singleton; 15 | 16 | /** 17 | * author: xujiaji 18 | * created on: 2018/8/19 17:08 19 | * description: 20 | */ 21 | @Singleton 22 | public class PostTreeViewModel extends BaseRefreshViewModel { 23 | 24 | private NetLiveEvent> mPostTreeData = new NetLiveEvent<>(); 25 | public final SingleLiveEvent mTagClickEvent = new SingleLiveEvent<>(); 26 | 27 | @Inject 28 | public PostTreeViewModel(@NonNull Application application) { 29 | super(application); 30 | } 31 | 32 | @Override 33 | public void onListRefresh() { 34 | mPostTreeData.setValue(net.get().getPostTree()); 35 | } 36 | 37 | public NetLiveEvent> getObservablePostTree() { 38 | mPostTreeData.setValue(net.get().getPostTree()); 39 | return mPostTreeData; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/main/fragment/posts/MainBlogPostsAdapter.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.main.fragment.posts; 2 | 3 | import android.support.annotation.Nullable; 4 | 5 | import com.xujiaji.mvvmquick.base.MQQuickAdapter; 6 | import com.xujiaji.mvvmquick.base.MQViewHolder; 7 | import com.xujiaji.mvvmquick.base.MQViewModel; 8 | import com.xujiaji.mvvmquick.callback.GeneralClickCallback; 9 | import com.xujiaji.mvvmquick.di.ActivityScoped; 10 | import com.xujiaji.mvvmquick.di.FragmentScoped; 11 | import com.xujiaji.wanandroid.R; 12 | import com.xujiaji.wanandroid.databinding.ItemBlogPostBinding; 13 | import com.xujiaji.wanandroid.repository.bean.BlogPostBean; 14 | 15 | import javax.inject.Inject; 16 | import javax.inject.Singleton; 17 | 18 | /** 19 | * author: xujiaji 20 | * created on: 2018/8/6 11:22 21 | * description: 22 | */ 23 | public class MainBlogPostsAdapter extends MQQuickAdapter { 24 | 25 | private final MainBlogPostsViewModel mViewModel; 26 | 27 | public MainBlogPostsAdapter(MainBlogPostsViewModel viewModel) { 28 | super(R.layout.item_blog_post); 29 | this.mViewModel = viewModel; 30 | } 31 | 32 | @Override 33 | protected void onBinding(ItemBlogPostBinding binding) { 34 | binding.setCallback((GeneralClickCallback) mViewModel.mClickEvent::setValue); 35 | binding.setTabCallback((GeneralClickCallback) mViewModel.mClickTab::setValue); 36 | } 37 | 38 | @Override 39 | protected void convert(MQViewHolder helper, BlogPostBean item) { 40 | item.setIndex(getData().indexOf(item)); 41 | helper.binding.setBlogPost(item); 42 | helper.binding.executePendingBindings(); 43 | } 44 | 45 | @Nullable 46 | @Override 47 | protected MQViewModel getViewModel() { 48 | return mViewModel; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/main/fragment/project_category/ProjectCategoryAdapter.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.main.fragment.project_category; 2 | 3 | import com.xujiaji.mvvmquick.base.MQQuickAdapter; 4 | import com.xujiaji.mvvmquick.base.MQViewHolder; 5 | import com.xujiaji.mvvmquick.callback.GeneralClickCallback; 6 | import com.xujiaji.wanandroid.R; 7 | import com.xujiaji.wanandroid.databinding.ItemProjectCategoryBinding; 8 | import com.xujiaji.wanandroid.repository.bean.TreeBean; 9 | 10 | import javax.inject.Inject; 11 | 12 | /** 13 | * author: xujiaji 14 | * created on: 2018/8/19 17:18 15 | * description: 16 | */ 17 | public class ProjectCategoryAdapter extends MQQuickAdapter { 18 | 19 | @Inject 20 | ProjectCategoryViewModel mViewModel; 21 | 22 | @Inject 23 | public ProjectCategoryAdapter() { 24 | super(R.layout.item_project_category); 25 | } 26 | 27 | @Override 28 | protected void onBinding(ItemProjectCategoryBinding binding) { 29 | binding.setCallback((GeneralClickCallback) mViewModel.mClickEvent::setValue); 30 | } 31 | 32 | @Override 33 | protected void convert(MQViewHolder helper, TreeBean item) { 34 | helper.binding.setProjectTree(item); 35 | helper.binding.executePendingBindings(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/main/fragment/project_category/ProjectCategoryFragment.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.main.fragment.project_category; 2 | 3 | import android.arch.lifecycle.Observer; 4 | import android.support.annotation.NonNull; 5 | import android.support.annotation.Nullable; 6 | 7 | import com.xujiaji.mvvmquick.di.ActivityScoped; 8 | import com.xujiaji.wanandroid.base.BaseFragment; 9 | import com.xujiaji.wanandroid.databinding.LayoutRefreshBinding; 10 | import com.xujiaji.wanandroid.helper.EmptyViewHelper; 11 | import com.xujiaji.wanandroid.helper.ToastHelper; 12 | import com.xujiaji.wanandroid.repository.bean.TreeBean; 13 | import com.xujiaji.wanandroid.repository.remote.DataCallbackImp; 14 | 15 | import java.util.List; 16 | 17 | import javax.inject.Inject; 18 | 19 | /** 20 | * author: xujiaji 21 | * created on: 2018/8/22 13:44 22 | * description: 23 | */ 24 | @ActivityScoped 25 | public class ProjectCategoryFragment extends BaseFragment { 26 | 27 | @Inject 28 | ProjectCategoryAdapter mAdapter; 29 | 30 | @Inject 31 | public ProjectCategoryFragment() {} 32 | 33 | @Override 34 | public void onBinding(@NonNull LayoutRefreshBinding binding) { 35 | mAdapter.bindToRecyclerView(binding.list); 36 | EmptyViewHelper.initEmpty(binding.list); 37 | } 38 | 39 | @Override 40 | public void onObserveViewModel(@NonNull ProjectCategoryViewModel viewModel) { 41 | binding.setRefreshViewModel(viewModel); 42 | viewModel.getObservableProjectTree().observeData(this, new DataCallbackImp>(binding.refresh) { 43 | @Override 44 | public void success(List bean) { 45 | viewModel.items.clear(); 46 | viewModel.items.addAll(bean); 47 | } 48 | }); 49 | 50 | viewModel.mClickEvent.observe(this, new Observer() { 51 | @Override 52 | public void onChanged(@Nullable TreeBean treeBean) { 53 | ToastHelper.info(treeBean.getName()); 54 | } 55 | }); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/main/fragment/project_category/ProjectCategoryViewModel.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.main.fragment.project_category; 2 | 3 | import android.app.Application; 4 | import android.support.annotation.NonNull; 5 | 6 | import com.xujiaji.mvvmquick.lifecycle.SingleLiveEvent; 7 | import com.xujiaji.wanandroid.base.BaseRefreshViewModel; 8 | import com.xujiaji.wanandroid.repository.bean.TreeBean; 9 | import com.xujiaji.wanandroid.repository.remote.NetLiveEvent; 10 | 11 | import java.util.List; 12 | 13 | import javax.inject.Inject; 14 | import javax.inject.Singleton; 15 | 16 | /** 17 | * author: xujiaji 18 | * created on: 2018/8/19 17:08 19 | * description: 20 | */ 21 | @Singleton 22 | public class ProjectCategoryViewModel extends BaseRefreshViewModel { 23 | 24 | private NetLiveEvent> mProjectCategoryData = new NetLiveEvent<>(); 25 | 26 | @Inject 27 | public ProjectCategoryViewModel(@NonNull Application application) { 28 | super(application); 29 | } 30 | 31 | @Override 32 | public void onListRefresh() { 33 | mProjectCategoryData.setValue(net.get().getProjectTree()); 34 | } 35 | 36 | public NetLiveEvent> getObservableProjectTree() { 37 | mProjectCategoryData.setValue(net.get().getProjectTree()); 38 | return mProjectCategoryData; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/main/fragment/projects/MainProjectsAdapter.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.main.fragment.projects; 2 | 3 | import android.support.annotation.Nullable; 4 | 5 | import com.xujiaji.mvvmquick.base.MQQuickAdapter; 6 | import com.xujiaji.mvvmquick.base.MQViewHolder; 7 | import com.xujiaji.mvvmquick.base.MQViewModel; 8 | import com.xujiaji.mvvmquick.callback.GeneralClickCallback; 9 | import com.xujiaji.wanandroid.R; 10 | import com.xujiaji.wanandroid.databinding.ItemBlogPostBinding; 11 | import com.xujiaji.wanandroid.module.main.fragment.posts.MainBlogPostsViewModel; 12 | import com.xujiaji.wanandroid.repository.bean.BlogPostBean; 13 | 14 | import javax.inject.Inject; 15 | 16 | /** 17 | * author: xujiaji 18 | * created on: 2018/8/6 11:22 19 | * description: 20 | */ 21 | public class MainProjectsAdapter extends MQQuickAdapter { 22 | 23 | private final MainProjectsViewModel mViewModel; 24 | 25 | @Inject 26 | public MainProjectsAdapter(MainProjectsViewModel viewModel) { 27 | super(R.layout.item_blog_post); 28 | this.mViewModel = viewModel; 29 | } 30 | 31 | @Override 32 | protected void onBinding(ItemBlogPostBinding binding) { 33 | binding.setCallback((GeneralClickCallback) mViewModel.mClickEvent::setValue); 34 | } 35 | 36 | @Override 37 | protected void convert(MQViewHolder helper, BlogPostBean item) { 38 | item.setIndex(getData().indexOf(item)); 39 | helper.binding.setHideTag(true); 40 | helper.binding.setBlogPost(item); 41 | helper.binding.executePendingBindings(); 42 | } 43 | 44 | @Nullable 45 | @Override 46 | protected MQViewModel getViewModel() { 47 | return mViewModel; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/main/fragment/projects/MainProjectsFragment.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.main.fragment.projects; 2 | 3 | import android.content.Intent; 4 | import android.support.annotation.NonNull; 5 | import android.support.v4.content.ContextCompat; 6 | import android.support.v7.widget.DividerItemDecoration; 7 | 8 | import com.xujiaji.mvvmquick.di.ActivityScoped; 9 | import com.xujiaji.wanandroid.base.BaseFragment; 10 | import com.xujiaji.wanandroid.databinding.LayoutRefreshBinding; 11 | import com.xujiaji.wanandroid.helper.ActivityResultHelper; 12 | import com.xujiaji.wanandroid.helper.RefreshLoadHelper; 13 | import com.xujiaji.wanandroid.module.read.ReadActivity; 14 | 15 | import javax.inject.Inject; 16 | 17 | /** 18 | * author: xujiaji 19 | * created on: 2018/8/5 21:06 20 | * description: 21 | */ 22 | @ActivityScoped 23 | public class MainProjectsFragment extends BaseFragment { 24 | @Inject 25 | MainProjectsAdapter mAdapter; 26 | 27 | @Inject 28 | public MainProjectsFragment() {} 29 | 30 | @Override 31 | public void onBinding(@NonNull LayoutRefreshBinding binding) { 32 | RefreshLoadHelper.init(mAdapter, binding.list); 33 | } 34 | 35 | @Override 36 | public void onObserveViewModel(@NonNull MainProjectsViewModel viewModel) { 37 | super.onObserveViewModel(viewModel); 38 | binding.setRefreshViewModel(viewModel); 39 | viewModel.getObservableProjects().observe(this, RefreshLoadHelper.listener(this, binding.list, mAdapter, binding.refresh, viewModel)); 40 | viewModel.mClickEvent.observe(this, blogPostBean -> ReadActivity.launch(this, blogPostBean)); 41 | } 42 | 43 | @Override 44 | public void onActivityResult(int requestCode, int resultCode, Intent data) { 45 | super.onActivityResult(requestCode, resultCode, data); 46 | ActivityResultHelper.handlePost(requestCode, resultCode, data, mAdapter); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/main/fragment/projects/MainProjectsViewModel.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.main.fragment.projects; 2 | 3 | import android.app.Application; 4 | import android.arch.lifecycle.MutableLiveData; 5 | import android.databinding.ObservableList; 6 | import android.support.annotation.NonNull; 7 | 8 | import com.xujiaji.mvvmquick.lifecycle.SingleLiveEvent; 9 | import com.xujiaji.wanandroid.RefreshLoadViewModel; 10 | import com.xujiaji.wanandroid.base.BaseRefreshViewModel; 11 | import com.xujiaji.wanandroid.model.RefreshLoadModel; 12 | import com.xujiaji.wanandroid.repository.bean.BlogPostBean; 13 | import com.xujiaji.wanandroid.repository.bean.PageBean; 14 | import com.xujiaji.wanandroid.repository.bean.Result; 15 | 16 | import javax.inject.Inject; 17 | import javax.inject.Singleton; 18 | 19 | /** 20 | * author: xujiaji 21 | * created on: 2018/8/5 23:35 22 | * description: 23 | */ 24 | @Singleton 25 | public class MainProjectsViewModel extends BaseRefreshViewModel implements RefreshLoadViewModel{ 26 | 27 | public final SingleLiveEvent>>>> projectsLiveData = new SingleLiveEvent<>(); 28 | 29 | @Inject 30 | public MainProjectsViewModel(@NonNull Application application) { 31 | super(application); 32 | } 33 | 34 | public SingleLiveEvent>>>> getObservableProjects() { 35 | projectsLiveData.setValue(new RefreshLoadModel<>(net.get().getProjects(UPDATE_INDEX), true)); 36 | return projectsLiveData; 37 | } 38 | 39 | @Override 40 | public void onListRefresh() { 41 | super.onListRefresh(); 42 | projectsLiveData.setValue(new RefreshLoadModel<>(net.get().getProjects(UPDATE_INDEX), true)); 43 | } 44 | 45 | @Override 46 | public void onListLoad(int offset) { 47 | projectsLiveData.postValue(new RefreshLoadModel<>(net.get().getProjects(offset), false)); 48 | } 49 | 50 | @Override 51 | public ObservableList getList() { 52 | return items; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/main/fragment/web_nav/WebNavViewModel.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.main.fragment.web_nav; 2 | 3 | import android.app.Application; 4 | import android.support.annotation.NonNull; 5 | 6 | import com.xujiaji.mvvmquick.lifecycle.SingleLiveEvent; 7 | import com.xujiaji.wanandroid.base.BaseRefreshClickChildViewModel; 8 | import com.xujiaji.wanandroid.base.BaseRefreshViewModel; 9 | import com.xujiaji.wanandroid.repository.bean.ThreeAPIBean; 10 | import com.xujiaji.wanandroid.repository.bean.WebNavBean; 11 | import com.xujiaji.wanandroid.repository.remote.NetLiveEvent; 12 | 13 | import java.util.List; 14 | 15 | import javax.inject.Inject; 16 | import javax.inject.Singleton; 17 | 18 | /** 19 | * author: xujiaji 20 | * created on: 2018/8/18 22:47 21 | * description: 22 | */ 23 | @Singleton 24 | public class WebNavViewModel extends BaseRefreshClickChildViewModel { 25 | 26 | private final NetLiveEvent> mWebNavListData = new NetLiveEvent<>(); 27 | 28 | @Inject 29 | public WebNavViewModel(@NonNull Application application) { 30 | super(application); 31 | } 32 | 33 | @Override 34 | public void onListRefresh() { 35 | mWebNavListData.setValue(net.get().getWebNavs()); 36 | } 37 | 38 | public NetLiveEvent> getObservableWebNavs() { 39 | mWebNavListData.setValue(net.get().getWebNavs()); 40 | return mWebNavListData; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/read/ReadModule.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.read; 2 | 3 | import dagger.Module; 4 | 5 | /** 6 | * author: xujiaji 7 | * created on: 2018/8/7 22:00 8 | * description: 9 | */ 10 | @Module 11 | public class ReadModule { 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/read/ReadViewModel.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.read; 2 | 3 | import android.app.Application; 4 | import android.support.annotation.NonNull; 5 | 6 | import com.xujiaji.wanandroid.base.BaseViewModel; 7 | import com.xujiaji.wanandroid.repository.remote.NetLiveEvent; 8 | 9 | import javax.inject.Inject; 10 | import javax.inject.Singleton; 11 | 12 | /** 13 | * author: xujiaji 14 | * created on: 2018/8/7 22:48 15 | * description: 16 | */ 17 | @Singleton 18 | public class ReadViewModel extends BaseViewModel { 19 | 20 | private final NetLiveEvent mCollect = new NetLiveEvent<>(); 21 | private final NetLiveEvent mUncollect = new NetLiveEvent<>(); 22 | 23 | @Inject 24 | public ReadViewModel(@NonNull Application application) { 25 | super(application); 26 | } 27 | 28 | public NetLiveEvent postObservableCollect(int id) { 29 | mCollect.setValue(net.get().postCollect(id)); 30 | return mCollect; 31 | } 32 | 33 | public NetLiveEvent postObservableUncollect(int id) { 34 | mUncollect.setValue(net.get().postUncollect(id)); 35 | return mUncollect; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/set/SettingsActivity.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.set; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.annotation.NonNull; 7 | 8 | import com.qihoo360.replugin.RePlugin; 9 | import com.qihoo360.replugin.model.PluginInfo; 10 | import com.xujiaji.mvvmquick.base.NoneViewModel; 11 | import com.xujiaji.wanandroid.base.BaseActivity; 12 | import com.xujiaji.wanandroid.databinding.ActivitySettingsBinding; 13 | import com.xujiaji.wanandroid.helper.ToolbarHelper; 14 | import com.xujiaji.wanandroid.util.FileUtil; 15 | 16 | import java.util.List; 17 | 18 | /** 19 | * author: xujiaji 20 | * created on: 2018/8/23 19:39 21 | * description: 22 | */ 23 | public class SettingsActivity extends BaseActivity { 24 | 25 | public static void launch(Context context) { 26 | context.startActivity(new Intent(context, SettingsActivity.class)); 27 | } 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | ToolbarHelper.initTranslucent(this); 32 | super.onCreate(savedInstanceState); 33 | } 34 | 35 | @Override 36 | public void onBinding(@NonNull ActivitySettingsBinding binding) { 37 | ToolbarHelper.initMarginTopDiffBar(binding.btnBack); 38 | binding.btnBack.setOnClickListener(v -> finish()); 39 | } 40 | 41 | @Override 42 | public void onObserveViewModel(@NonNull SettingsViewModel viewModel) { 43 | super.onObserveViewModel(viewModel); 44 | binding.setSettingsViewModel(viewModel); 45 | viewModel.cacheSize.set(FileUtil.getCacheSizeStr(this)); 46 | int pluginNum = 0; 47 | for (PluginInfo pluginInfo : RePlugin.getPluginInfoList()) { 48 | pluginNum += pluginInfo.isUsed() ? 1 : 0; 49 | } 50 | viewModel.pluginNum.set(pluginNum); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/set/SettingsViewModel.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.set; 2 | 3 | import android.app.Activity; 4 | import android.app.Application; 5 | import android.databinding.ObservableField; 6 | import android.databinding.ObservableInt; 7 | import android.support.annotation.NonNull; 8 | import android.view.View; 9 | 10 | import com.qihoo360.replugin.RePlugin; 11 | import com.qihoo360.replugin.model.PluginInfo; 12 | import com.xujiaji.wanandroid.base.App; 13 | import com.xujiaji.wanandroid.base.BaseViewModel; 14 | import com.xujiaji.wanandroid.helper.ToastHelper; 15 | import com.xujiaji.wanandroid.util.ApkUtil; 16 | import com.xujiaji.wanandroid.util.FileUtil; 17 | import com.xujiaji.wanandroid.util.NetUtil; 18 | 19 | import javax.inject.Inject; 20 | import javax.inject.Singleton; 21 | 22 | /** 23 | * author: xujiaji 24 | * created on: 2018/9/1 9:11 25 | * description: 26 | */ 27 | @Singleton 28 | public class SettingsViewModel extends BaseViewModel { 29 | 30 | public final ObservableField cacheSize = new ObservableField<>(); 31 | public final ObservableInt pluginNum = new ObservableInt(); 32 | 33 | 34 | @Inject 35 | public SettingsViewModel(@NonNull Application application) { 36 | super(application); 37 | } 38 | 39 | public void cleanCache(View view) { 40 | view.setEnabled(false); 41 | new Thread() { 42 | @Override 43 | public void run() { 44 | FileUtil.deleteCache(view.getContext()); 45 | ((Activity) view.getContext()).runOnUiThread(() -> { 46 | view.setEnabled(true); 47 | cacheSize.set(FileUtil.getCacheSizeStr(view.getContext())); 48 | ToastHelper.success("已清理缓存"); 49 | }); 50 | } 51 | }.start(); 52 | 53 | } 54 | 55 | public void cleanPlugin(View view) { 56 | for (PluginInfo info : RePlugin.getPluginInfoList()) { 57 | RePlugin.uninstall(info.getName()); 58 | } 59 | pluginNum.set(0); 60 | ToastHelper.success("已清除,重启生效"); 61 | } 62 | 63 | public boolean isUnInstallTodoApk() { 64 | return !ApkUtil.isInstalled(App.getInstance(), "com.xujiaji.todo"); 65 | } 66 | 67 | public void installTodoApk(View view) { 68 | NetUtil.systemBrowserOpen(view.getContext(), "https://github.com/xujiaji/Todo"); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/module/splash/SplashActivity.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.module.splash; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | 6 | import com.xujiaji.wanandroid.module.main.MainActivity; 7 | 8 | public class SplashActivity extends Activity { 9 | 10 | @Override 11 | protected void onResume() { 12 | super.onResume(); 13 | Intent intent = new Intent(SplashActivity.this, MainActivity.class); 14 | startActivity(intent); 15 | finish(); 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/repository/bean/BoxBean.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.repository.bean; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * author: xujiaji 7 | * created on: 2018/8/15 10:43 8 | * description: 9 | */ 10 | public class BoxBean { 11 | 12 | @SerializedName("thumb") 13 | private String thumb; 14 | @SerializedName("name") 15 | private String name; 16 | @SerializedName("description") 17 | private String description; 18 | @SerializedName("pkg") 19 | private String pkg; 20 | @SerializedName("start_class") 21 | private String startClass; 22 | @SerializedName("version_code") 23 | private int versionCode; 24 | @SerializedName("url") 25 | private String url; 26 | 27 | public String getUrl() { 28 | return url; 29 | } 30 | 31 | public void setUrl(String url) { 32 | this.url = url; 33 | } 34 | 35 | public int getVersionCode() { 36 | return versionCode; 37 | } 38 | 39 | public void setVersionCode(int versionCode) { 40 | this.versionCode = versionCode; 41 | } 42 | 43 | public String getStartClass() { 44 | return startClass; 45 | } 46 | 47 | public void setStartClass(String startClass) { 48 | this.startClass = startClass; 49 | } 50 | 51 | public String getThumb() { 52 | return thumb; 53 | } 54 | 55 | public void setThumb(String thumb) { 56 | this.thumb = thumb; 57 | } 58 | 59 | public String getName() { 60 | return name; 61 | } 62 | 63 | public void setName(String name) { 64 | this.name = name; 65 | } 66 | 67 | public String getDescription() { 68 | return description; 69 | } 70 | 71 | public void setDescription(String description) { 72 | this.description = description; 73 | } 74 | 75 | public String getPkg() { 76 | return pkg; 77 | } 78 | 79 | public void setPkg(String pkg) { 80 | this.pkg = pkg; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/repository/bean/FriendLinkBean.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.repository.bean; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * author: xujiaji 7 | * created on: 2018/8/25 12:33 8 | * description: 9 | */ 10 | public class FriendLinkBean { 11 | 12 | /** 13 | * url : http://www.jowanxu.top/ 14 | * title : 15 | * thumb : http://www.wanandroid.com/blogimgs/2c1d0ec6-092d-45e9-94c2-17d7a99dea0a.png 16 | */ 17 | 18 | @SerializedName("url") 19 | private String url; 20 | @SerializedName("title") 21 | private String title; 22 | @SerializedName("thumb") 23 | private String thumb; 24 | 25 | public String getUrl() { 26 | return url; 27 | } 28 | 29 | public void setUrl(String url) { 30 | this.url = url; 31 | } 32 | 33 | public String getTitle() { 34 | return title; 35 | } 36 | 37 | public void setTitle(String title) { 38 | this.title = title; 39 | } 40 | 41 | public String getThumb() { 42 | return thumb; 43 | } 44 | 45 | public void setThumb(String thumb) { 46 | this.thumb = thumb; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/repository/bean/LicenseBean.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.repository.bean; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * author: xujiaji 7 | * created on: 2018/8/30 19:22 8 | * description: 9 | */ 10 | public class LicenseBean { 11 | 12 | /** 13 | * thumb : https://avatars3.githubusercontent.com/u/1321838?s=400&v=4 14 | * name : Stream 15 | * author : aNNiMON 16 | * desc : Stream API from Java 8 rewritten on iterators for Java 7 and below 17 | * link : https://github.com/aNNiMON/Lightweight-Stream-API 18 | * license : Apache-2.0 19 | */ 20 | 21 | @SerializedName("thumb") 22 | private String thumb; 23 | @SerializedName("name") 24 | private String name; 25 | @SerializedName("author") 26 | private String author; 27 | @SerializedName("desc") 28 | private String desc; 29 | @SerializedName("link") 30 | private String link; 31 | @SerializedName("license") 32 | private String license; 33 | 34 | public String getThumb() { 35 | return thumb; 36 | } 37 | 38 | public void setThumb(String thumb) { 39 | this.thumb = thumb; 40 | } 41 | 42 | public String getName() { 43 | return name; 44 | } 45 | 46 | public void setName(String name) { 47 | this.name = name; 48 | } 49 | 50 | public String getAuthor() { 51 | return author; 52 | } 53 | 54 | public void setAuthor(String author) { 55 | this.author = author; 56 | } 57 | 58 | public String getDesc() { 59 | return desc; 60 | } 61 | 62 | public void setDesc(String desc) { 63 | this.desc = desc; 64 | } 65 | 66 | public String getLink() { 67 | return link; 68 | } 69 | 70 | public void setLink(String link) { 71 | this.link = link; 72 | } 73 | 74 | public String getLicense() { 75 | return license; 76 | } 77 | 78 | public void setLicense(String license) { 79 | this.license = license; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/repository/bean/Result.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.repository.bean; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * author: xujiaji 7 | * created on: 2018/8/5 23:16 8 | * description: 9 | */ 10 | public class Result { 11 | 12 | /** 13 | * data : {} 14 | * errorCode : 0 15 | * errorMsg : 16 | */ 17 | 18 | @SerializedName("data") 19 | private T data; 20 | @SerializedName("errorCode") 21 | private int errorCode; 22 | @SerializedName("errorMsg") 23 | private String errorMsg; 24 | 25 | public T getData() { 26 | return data; 27 | } 28 | 29 | public void setData(T data) { 30 | this.data = data; 31 | } 32 | 33 | public int getErrorCode() { 34 | return errorCode; 35 | } 36 | 37 | public void setErrorCode(int errorCode) { 38 | this.errorCode = errorCode; 39 | } 40 | 41 | public String getErrorMsg() { 42 | return errorMsg; 43 | } 44 | 45 | public void setErrorMsg(String errorMsg) { 46 | this.errorMsg = errorMsg; 47 | } 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/repository/bean/ThreeAPIBean.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.repository.bean; 2 | 3 | import com.chad.library.adapter.base.entity.AbstractExpandableItem; 4 | import com.chad.library.adapter.base.entity.MultiItemEntity; 5 | import com.google.gson.annotations.SerializedName; 6 | 7 | import java.util.List; 8 | 9 | import static com.xujiaji.wanandroid.module.main.fragment.openapis.OpenAPISAdapter.TYPE_API; 10 | import static com.xujiaji.wanandroid.module.main.fragment.openapis.OpenAPISAdapter.TYPE_SECTION; 11 | 12 | /** 13 | * author: xujiaji 14 | * created on: 2018/8/13 10:21 15 | * description: 16 | */ 17 | public class ThreeAPIBean extends AbstractExpandableItem implements MultiItemEntity { 18 | 19 | /** 20 | * name : 日历 21 | * links : [{"url":"https://mmp.51wnl.com/apiDetail_calandar.html","name":"万年历API文档"}] 22 | */ 23 | 24 | @SerializedName("name") 25 | private String name; 26 | @SerializedName("links") 27 | private List links; 28 | 29 | public String getName() { 30 | return name; 31 | } 32 | 33 | public void setName(String name) { 34 | this.name = name; 35 | } 36 | 37 | public List getLinks() { 38 | return links; 39 | } 40 | 41 | public void setLinks(List links) { 42 | this.links = links; 43 | } 44 | 45 | @Override 46 | public int getLevel() { 47 | return 0; 48 | } 49 | 50 | @Override 51 | public int getItemType() { 52 | return TYPE_SECTION; 53 | } 54 | 55 | public static class LinkBean implements MultiItemEntity { 56 | /** 57 | * url : https://mmp.51wnl.com/apiDetail_calandar.html 58 | * name : 万年历API文档 59 | */ 60 | 61 | @SerializedName("url") 62 | private String url; 63 | @SerializedName("name") 64 | private String name; 65 | 66 | public String getUrl() { 67 | return url; 68 | } 69 | 70 | public void setUrl(String url) { 71 | this.url = url; 72 | } 73 | 74 | public String getName() { 75 | return name; 76 | } 77 | 78 | public void setName(String name) { 79 | this.name = name; 80 | } 81 | 82 | @Override 83 | public int getItemType() { 84 | return TYPE_API; 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/repository/bean/UserBean.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.repository.bean; 2 | 3 | import android.text.TextUtils; 4 | 5 | import com.google.gson.annotations.SerializedName; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * author: xujiaji 11 | * created on: 2018/8/11 19:14 12 | * description: 13 | */ 14 | public class UserBean { 15 | 16 | /** 17 | * collectIds : [1011,3143,3224,3173,3234] 18 | * email : 19 | * icon : 20 | * id : 5603 21 | * password : pDVBxk2wRo 22 | * type : 0 23 | * username : jiajixu@qq.com 24 | */ 25 | 26 | @SerializedName("email") 27 | private String email; 28 | @SerializedName("icon") 29 | private String icon; 30 | @SerializedName("id") 31 | private int id; 32 | @SerializedName("password") 33 | private String password; 34 | @SerializedName("type") 35 | private int type; 36 | @SerializedName("username") 37 | private String username; 38 | @SerializedName("collectIds") 39 | private List collectIds; 40 | 41 | public String getEmail() { 42 | if (TextUtils.isEmpty(email)) return "Wan"; 43 | return email; 44 | } 45 | 46 | public void setEmail(String email) { 47 | this.email = email; 48 | } 49 | 50 | public String getIcon() { 51 | return icon; 52 | } 53 | 54 | public void setIcon(String icon) { 55 | this.icon = icon; 56 | } 57 | 58 | public int getId() { 59 | return id; 60 | } 61 | 62 | public void setId(int id) { 63 | this.id = id; 64 | } 65 | 66 | public String getPassword() { 67 | return password; 68 | } 69 | 70 | public void setPassword(String password) { 71 | this.password = password; 72 | } 73 | 74 | public int getType() { 75 | return type; 76 | } 77 | 78 | public void setType(int type) { 79 | this.type = type; 80 | } 81 | 82 | public String getUsername() { 83 | if (TextUtils.isEmpty(username)) return "Wan"; 84 | return username; 85 | } 86 | 87 | public void setUsername(String username) { 88 | this.username = username; 89 | } 90 | 91 | public List getCollectIds() { 92 | return collectIds; 93 | } 94 | 95 | public void setCollectIds(List collectIds) { 96 | this.collectIds = collectIds; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/repository/bean/VersionBean.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.repository.bean; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * author: xujiaji 7 | * created on: 2018/8/31 10:37 8 | * description: 9 | */ 10 | public class VersionBean { 11 | 12 | /** 13 | * version_name : 1.0.0 14 | * version_code : 1 15 | * update_info : 更新信息 16 | * file_size : 5M 17 | * constraint : false 18 | * apk_url : https://github.com/xujiaji/HappyBubble/releases/download/v1.1.4-demoApk/app-debug.apk 19 | */ 20 | 21 | @SerializedName("version_name") 22 | private String versionName; 23 | @SerializedName("version_code") 24 | private int versionCode; 25 | @SerializedName("update_info") 26 | private String updateInfo; 27 | @SerializedName("file_size") 28 | private String fileSize; 29 | @SerializedName("constraint") 30 | private boolean constraint; 31 | @SerializedName("apk_url") 32 | private String apkUrl; 33 | 34 | public String getVersionName() { 35 | return versionName; 36 | } 37 | 38 | public void setVersionName(String versionName) { 39 | this.versionName = versionName; 40 | } 41 | 42 | public int getVersionCode() { 43 | return versionCode; 44 | } 45 | 46 | public void setVersionCode(int versionCode) { 47 | this.versionCode = versionCode; 48 | } 49 | 50 | public String getUpdateInfo() { 51 | return updateInfo; 52 | } 53 | 54 | public void setUpdateInfo(String updateInfo) { 55 | this.updateInfo = updateInfo; 56 | } 57 | 58 | public String getFileSize() { 59 | return fileSize; 60 | } 61 | 62 | public void setFileSize(String fileSize) { 63 | this.fileSize = fileSize; 64 | } 65 | 66 | public boolean isConstraint() { 67 | return constraint; 68 | } 69 | 70 | public void setConstraint(boolean constraint) { 71 | this.constraint = constraint; 72 | } 73 | 74 | public String getApkUrl() { 75 | return apkUrl; 76 | } 77 | 78 | public void setApkUrl(String apkUrl) { 79 | this.apkUrl = apkUrl; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/repository/remote/DataCallback.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.repository.remote; 2 | 3 | /** 4 | * author: xujiaji 5 | * created on: 2018/8/12 0:11 6 | * description: 7 | */ 8 | public interface DataCallback { 9 | /** 10 | * 完成回调,不管成功还是失败 11 | */ 12 | void finished(); 13 | 14 | /** 15 | * 成功得到数据 16 | */ 17 | void success(T bean); 18 | 19 | /** 20 | * 失败 21 | * @param code 错误码 22 | * @param msg 错误消息 23 | */ 24 | void fail(int code, String msg); 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/repository/remote/DataCallbackImp.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.repository.remote; 2 | 3 | import android.support.v4.widget.SwipeRefreshLayout; 4 | import android.support.v7.widget.RecyclerView; 5 | 6 | import com.xujiaji.mvvmquick.util.LogUtil; 7 | import com.xujiaji.wanandroid.helper.EmptyViewHelper; 8 | import com.xujiaji.wanandroid.helper.ToastHelper; 9 | 10 | import java.lang.ref.WeakReference; 11 | 12 | /** 13 | * author: xujiaji 14 | * created on: 2018/8/12 0:33 15 | * description: 16 | */ 17 | public abstract class DataCallbackImp implements DataCallback { 18 | 19 | private boolean isToastErr = true; 20 | private WeakReference refreshLayout; 21 | 22 | public DataCallbackImp() {} 23 | 24 | public DataCallbackImp(boolean isToastErr) { 25 | this.isToastErr = isToastErr; 26 | } 27 | 28 | 29 | public DataCallbackImp(SwipeRefreshLayout refreshLayout) { 30 | this.refreshLayout = new WeakReference<>(refreshLayout); 31 | } 32 | 33 | @Override 34 | public void finished() { 35 | if (refreshLayout != null && refreshLayout.get() != null) { 36 | refreshLayout.get().setRefreshing(false); 37 | } 38 | } 39 | 40 | @Override 41 | public void fail(int code, String msg) { 42 | if (isToastErr && msg != null) { 43 | ToastHelper.error(msg); 44 | } 45 | 46 | if (refreshLayout != null && refreshLayout.get() != null) { 47 | for (int i = 0; i < refreshLayout.get().getChildCount(); i++) { 48 | if (!(refreshLayout.get().getChildAt(i) instanceof RecyclerView)) continue; 49 | RecyclerView recyclerView = (RecyclerView) refreshLayout.get().getChildAt(i); 50 | EmptyViewHelper.setErrEmpty(recyclerView, msg); 51 | return; 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/repository/remote/NetCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 XuJiaji 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xujiaji.wanandroid.repository.remote; 18 | 19 | import android.arch.lifecycle.MutableLiveData; 20 | import android.widget.Toast; 21 | 22 | import com.xujiaji.wanandroid.helper.ToastHelper; 23 | 24 | import java.net.ConnectException; 25 | import java.net.SocketTimeoutException; 26 | import java.net.UnknownHostException; 27 | import java.util.concurrent.TimeoutException; 28 | 29 | import retrofit2.Call; 30 | import retrofit2.Callback; 31 | import retrofit2.Response; 32 | 33 | /** 34 | * author: xujiaji 35 | * created on: 2018/6/12 16:42 36 | * description: 网络请求回调统一处理 37 | */ 38 | public class NetCallback implements Callback { 39 | private final MutableLiveData mutableLiveData; 40 | 41 | public NetCallback(MutableLiveData mutableLiveData) { 42 | this.mutableLiveData = mutableLiveData; 43 | } 44 | 45 | @Override 46 | public void onResponse(Call call, Response response) { 47 | mutableLiveData.setValue(response.body()); 48 | } 49 | 50 | @Override 51 | public void onFailure(Call call, Throwable t) { 52 | if (t instanceof UnknownHostException || t instanceof ConnectException) { 53 | ToastHelper.warning("请检查网络"); 54 | } else if (t instanceof TimeoutException || t instanceof SocketTimeoutException) { 55 | ToastHelper.warning("连接超时"); 56 | } else { 57 | ToastHelper.warning(t.getMessage()); 58 | } 59 | mutableLiveData.setValue(null); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/util/ApkUtil.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.util; 2 | 3 | import android.content.Context; 4 | import android.content.pm.PackageManager; 5 | import android.text.TextUtils; 6 | 7 | /** 8 | * author: xujiaji 9 | * created on: 2018/10/18 14:18 10 | * description: 11 | */ 12 | public class ApkUtil { 13 | public static boolean isInstalled(Context context, String packageName) { 14 | if (TextUtils.isEmpty(packageName)) { 15 | return false; 16 | } 17 | try { 18 | context.getPackageManager().getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES); 19 | return true; 20 | } catch (PackageManager.NameNotFoundException e) { 21 | e.printStackTrace(); 22 | return false; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/util/NetUtil.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.util; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.net.Uri; 6 | 7 | import com.annimon.stream.Stream; 8 | 9 | import java.util.Arrays; 10 | import java.util.HashSet; 11 | import java.util.List; 12 | import java.util.Set; 13 | 14 | /** 15 | * author: xujiaji 16 | * created on: 2018/8/11 18:06 17 | * description: 18 | */ 19 | public class NetUtil { 20 | public static String encodeCookie(List cookies) { 21 | final StringBuilder sb = new StringBuilder(); 22 | final Set set = new HashSet<>(); 23 | Stream.of(cookies) 24 | .map(cookie -> Arrays.asList(cookie.split(";"))) 25 | .forEach(strings -> Stream.of(strings).forEach(set::add)); 26 | Stream.of(set).forEach(cookie -> sb.append(cookie).append(";")); 27 | if (sb.length() > 0) 28 | sb.delete(sb.length() - 1, sb.length()); 29 | return sb.toString().trim(); 30 | } 31 | 32 | 33 | /** 34 | * 系统浏览器打开该链接 35 | * @param url 链接 36 | */ 37 | public static void systemBrowserOpen(Context context, String url) { 38 | try { 39 | Intent intent = new Intent("android.intent.action.VIEW"); 40 | Uri content_url = Uri.parse(url); 41 | intent.setData(content_url); 42 | context.startActivity(intent); 43 | } catch (Exception e) { 44 | e.printStackTrace(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/xujiaji/wanandroid/wedgit/AvatarLayout.java: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid.wedgit; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.content.ContextCompat; 7 | import android.util.AttributeSet; 8 | import android.view.View; 9 | import android.widget.FrameLayout; 10 | import android.widget.ImageView; 11 | 12 | import com.bumptech.glide.Glide; 13 | import com.bumptech.glide.load.engine.DiskCacheStrategy; 14 | import com.bumptech.glide.request.RequestOptions; 15 | import com.xujiaji.wanandroid.R; 16 | import com.xujiaji.wanandroid.config.PicConfig; 17 | 18 | /** 19 | * author: xujiaji 20 | * created on: 2018/8/4 11:28 21 | * description: 22 | */ 23 | public class AvatarLayout extends FrameLayout { 24 | private ImageView avatar; 25 | 26 | public AvatarLayout(@NonNull Context context) { 27 | super(context); 28 | } 29 | 30 | public AvatarLayout(@NonNull Context context, @Nullable AttributeSet attrs) { 31 | super(context, attrs); 32 | } 33 | 34 | public AvatarLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 35 | super(context, attrs, defStyleAttr); 36 | } 37 | 38 | @Override 39 | protected void onFinishInflate() { 40 | super.onFinishInflate(); 41 | View view = inflate(getContext(), R.layout.layout_avatar, this); 42 | avatar = view.findViewById(R.id.avatar); 43 | } 44 | 45 | public void setUrl(String url) { 46 | Glide.with(getContext()) 47 | .applyDefaultRequestOptions(PicConfig.headOptions) 48 | .load(url) 49 | .into(avatar); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/res/color/search_tab_highlighter.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/ic_launcher_web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/app/src/main/res/drawable-nodpi/ic_launcher_web.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bottom_border.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/btn_rounded_outline.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/gradient_bottom_2_top.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_drop.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_right.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_back.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_cloud_off.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_heart_full.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_internet.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_link.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_nav_api.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_nav_category_project.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_nav_system.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_pen.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_search.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_switch.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_todo_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | 14 | 17 | 20 | 23 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ripple_theme.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ripple_theme_small.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ripple_white.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ripple_white_small.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/scrollbar_thumb.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/scrollbar_track.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/splash_screen_drawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_license.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 12 | 13 | 17 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_like.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 12 | 13 | 17 | 20 | 21 | 22 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /app/src/main/res/layout/appbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/drawer_fragment_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_container.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_friend_link.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 10 | 11 | 14 | 15 | 16 | 17 | 24 | 25 | 31 | 32 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_layout_home_banner.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_open_api.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 13 | 14 | 15 | 16 | 22 | 23 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_open_api_section.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 22 | 23 | 30 | 31 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_post_tree.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 10 | 11 | 14 | 15 | 18 | 19 | 20 | 25 | 26 | 38 | 39 | 40 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_post_tree_tag.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_project_category.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 9 | 10 | 13 | 14 | 15 | 16 | 21 | 22 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_add_own_project.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 21 | 22 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_avatar.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_refresh.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 11 | 12 | 15 | 16 | 17 | 24 | 25 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/line_full.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/layout/no_item_error.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 23 | 24 | 31 | 32 | 39 | 40 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /app/src/main/res/layout/webview.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/menu/navigation.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/menu/search_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/error_item_pic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/app/src/main/res/mipmap-xxhdpi/error_item_pic.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_default_head.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/app/src/main/res/mipmap-xxhdpi/ic_default_head.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/placeholder_item_pic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/app/src/main/res/mipmap-xxhdpi/placeholder_item_pic.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #673ab7 4 | #512da8 5 | #7c4dff 6 | #d1c4e9 7 | #212121 8 | #727272 9 | #00000000 10 | #ffffff 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | 16dp 7 | 4dp 8 | 8dp 9 | 16dp 10 | 24dp 11 | 32dp 12 | 48dp 13 | 64dp 14 | 96dp 15 | 48dp 16 | 64dp 17 | 24dp 18 | 1px 19 | 16dp 20 | 12sp 21 | 10sp 22 | 180dp 23 | 16dp 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFBF0 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/test/java/com/xujiaji/wanandroid/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.xujiaji.wanandroid 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /banner/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /banner/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion rootProject.compileSdk 5 | 6 | defaultConfig { 7 | minSdkVersion rootProject.minSdk 8 | targetSdkVersion rootProject.targetSdk 9 | versionCode 41 10 | versionName version 11 | } 12 | buildTypes { 13 | release { 14 | minifyEnabled false 15 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 16 | } 17 | } 18 | lintOptions { 19 | abortOnError false 20 | } 21 | } 22 | 23 | dependencies { 24 | implementation fileTree(dir: 'libs', include: ['*.jar']) 25 | implementation "com.android.support:support-v4:$support" 26 | } 27 | -------------------------------------------------------------------------------- /banner/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 D:\android\android-sdk-windows/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 | -------------------------------------------------------------------------------- /banner/src/androidTest/java/com/youth/banner/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.youth.banner; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /banner/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/BannerConfig.java: -------------------------------------------------------------------------------- 1 | package com.youth.banner; 2 | 3 | 4 | public class BannerConfig { 5 | /** 6 | * indicator style 7 | */ 8 | public static final int NOT_INDICATOR = 0; 9 | public static final int CIRCLE_INDICATOR = 1; 10 | public static final int NUM_INDICATOR = 2; 11 | public static final int NUM_INDICATOR_TITLE = 3; 12 | public static final int CIRCLE_INDICATOR_TITLE = 4; 13 | public static final int CIRCLE_INDICATOR_TITLE_INSIDE = 5; 14 | /** 15 | * indicator gravity 16 | */ 17 | public static final int LEFT = 5; 18 | public static final int CENTER = 6; 19 | public static final int RIGHT = 7; 20 | 21 | /** 22 | * banner 23 | */ 24 | public static final int PADDING_SIZE = 5; 25 | public static final int TIME = 2000; 26 | public static final int DURATION = 800; 27 | public static final boolean IS_AUTO_PLAY = true; 28 | public static final boolean IS_SCROLL = true; 29 | 30 | /** 31 | * title style 32 | */ 33 | public static final int TITLE_BACKGROUND = -1; 34 | public static final int TITLE_HEIGHT = -1; 35 | public static final int TITLE_TEXT_COLOR = -1; 36 | public static final int TITLE_TEXT_SIZE = -1; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/BannerScroller.java: -------------------------------------------------------------------------------- 1 | package com.youth.banner; 2 | 3 | import android.content.Context; 4 | import android.view.animation.Interpolator; 5 | import android.widget.Scroller; 6 | 7 | public class BannerScroller extends Scroller { 8 | private int mDuration = BannerConfig.DURATION; 9 | 10 | public BannerScroller(Context context) { 11 | super(context); 12 | } 13 | 14 | public BannerScroller(Context context, Interpolator interpolator) { 15 | super(context, interpolator); 16 | } 17 | 18 | public BannerScroller(Context context, Interpolator interpolator, boolean flywheel) { 19 | super(context, interpolator, flywheel); 20 | } 21 | 22 | @Override 23 | public void startScroll(int startX, int startY, int dx, int dy, int duration) { 24 | super.startScroll(startX, startY, dx, dy, mDuration); 25 | } 26 | 27 | @Override 28 | public void startScroll(int startX, int startY, int dx, int dy) { 29 | super.startScroll(startX, startY, dx, dy, mDuration); 30 | } 31 | 32 | public void setDuration(int time) { 33 | mDuration = time; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/listener/OnBannerClickListener.java: -------------------------------------------------------------------------------- 1 | package com.youth.banner.listener; 2 | 3 | 4 | /** 5 | * 旧版接口,由于返回的下标是从1开始,下标越界而废弃(因为有人使用所以不能直接删除) 6 | */ 7 | @Deprecated 8 | public interface OnBannerClickListener { 9 | public void OnBannerClick(int position); 10 | } 11 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/listener/OnBannerListener.java: -------------------------------------------------------------------------------- 1 | package com.youth.banner.listener; 2 | 3 | public interface OnBannerListener { 4 | public void OnBannerClick(int position); 5 | } 6 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/loader/ImageLoader.java: -------------------------------------------------------------------------------- 1 | package com.youth.banner.loader; 2 | 3 | import android.content.Context; 4 | import android.widget.ImageView; 5 | 6 | 7 | public abstract class ImageLoader implements ImageLoaderInterface { 8 | 9 | @Override 10 | public ImageView createImageView(Context context) { 11 | ImageView imageView = new ImageView(context); 12 | return imageView; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/loader/ImageLoaderInterface.java: -------------------------------------------------------------------------------- 1 | package com.youth.banner.loader; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | 6 | import java.io.Serializable; 7 | 8 | 9 | public interface ImageLoaderInterface extends Serializable { 10 | 11 | void displayImage(Context context, Object path, T imageView); 12 | 13 | T createImageView(Context context); 14 | } 15 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/transformer/AccordionTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Toxic Bakery 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.youth.banner.transformer; 18 | 19 | import android.view.View; 20 | 21 | public class AccordionTransformer extends ABaseTransformer { 22 | 23 | @Override 24 | protected void onTransform(View view, float position) { 25 | view.setPivotX(position < 0 ? 0 : view.getWidth()); 26 | view.setScaleX(position < 0 ? 1f + position : 1f - position); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/transformer/BackgroundToForegroundTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Toxic Bakery 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.youth.banner.transformer; 18 | 19 | import android.view.View; 20 | 21 | public class BackgroundToForegroundTransformer extends ABaseTransformer { 22 | 23 | @Override 24 | protected void onTransform(View view, float position) { 25 | final float height = view.getHeight(); 26 | final float width = view.getWidth(); 27 | final float scale = min(position < 0 ? 1f : Math.abs(1f - position), 0.5f); 28 | 29 | view.setScaleX(scale); 30 | view.setScaleY(scale); 31 | view.setPivotX(width * 0.5f); 32 | view.setPivotY(height * 0.5f); 33 | view.setTranslationX(position < 0 ? width * position : -width * position * 0.25f); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/transformer/CubeInTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Toxic Bakery 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.youth.banner.transformer; 18 | 19 | import android.view.View; 20 | 21 | public class CubeInTransformer extends ABaseTransformer { 22 | 23 | @Override 24 | protected void onTransform(View view, float position) { 25 | // Rotate the fragment on the left or right edge 26 | view.setPivotX(position > 0 ? 0 : view.getWidth()); 27 | view.setPivotY(0); 28 | view.setRotationY(-90f * position); 29 | } 30 | 31 | @Override 32 | public boolean isPagingEnabled() { 33 | return true; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/transformer/CubeOutTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Toxic Bakery 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.youth.banner.transformer; 18 | 19 | import android.view.View; 20 | 21 | public class CubeOutTransformer extends ABaseTransformer { 22 | 23 | @Override 24 | protected void onTransform(View view, float position) { 25 | view.setPivotX(position < 0f ? view.getWidth() : 0f); 26 | view.setPivotY(view.getHeight() * 0.5f); 27 | view.setRotationY(90f * position); 28 | } 29 | 30 | @Override 31 | public boolean isPagingEnabled() { 32 | return true; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/transformer/DefaultTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Toxic Bakery 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.youth.banner.transformer; 18 | 19 | import android.view.View; 20 | 21 | public class DefaultTransformer extends ABaseTransformer { 22 | 23 | @Override 24 | protected void onTransform(View view, float position) { 25 | } 26 | 27 | @Override 28 | public boolean isPagingEnabled() { 29 | return true; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/transformer/DepthPageTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Toxic Bakery 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.youth.banner.transformer; 18 | 19 | import android.view.View; 20 | 21 | public class DepthPageTransformer extends ABaseTransformer { 22 | 23 | private static final float MIN_SCALE = 0.75f; 24 | 25 | @Override 26 | protected void onTransform(View view, float position) { 27 | if (position <= 0f) { 28 | view.setTranslationX(0f); 29 | view.setScaleX(1f); 30 | view.setScaleY(1f); 31 | } else if (position <= 1f) { 32 | final float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position)); 33 | view.setAlpha(1 - position); 34 | view.setPivotY(0.5f * view.getHeight()); 35 | view.setTranslationX(view.getWidth() * -position); 36 | view.setScaleX(scaleFactor); 37 | view.setScaleY(scaleFactor); 38 | } 39 | } 40 | 41 | @Override 42 | protected boolean isPagingEnabled() { 43 | return true; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/transformer/FlipHorizontalTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Toxic Bakery 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.youth.banner.transformer; 18 | 19 | import android.view.View; 20 | 21 | public class FlipHorizontalTransformer extends ABaseTransformer { 22 | 23 | @Override 24 | protected void onTransform(View view, float position) { 25 | final float rotation = 180f * position; 26 | 27 | view.setAlpha(rotation > 90f || rotation < -90f ? 0 : 1); 28 | view.setPivotX(view.getWidth() * 0.5f); 29 | view.setPivotY(view.getHeight() * 0.5f); 30 | view.setRotationY(rotation); 31 | } 32 | 33 | @Override 34 | protected void onPostTransform(View page, float position) { 35 | super.onPostTransform(page, position); 36 | 37 | //resolve problem: new page can't handle click event! 38 | if (position > -0.5f && position < 0.5f) { 39 | page.setVisibility(View.VISIBLE); 40 | } else { 41 | page.setVisibility(View.INVISIBLE); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/transformer/FlipVerticalTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Toxic Bakery 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.youth.banner.transformer; 18 | 19 | import android.view.View; 20 | 21 | public class FlipVerticalTransformer extends ABaseTransformer { 22 | 23 | @Override 24 | protected void onTransform(View view, float position) { 25 | final float rotation = -180f * position; 26 | 27 | view.setAlpha(rotation > 90f || rotation < -90f ? 0f : 1f); 28 | view.setPivotX(view.getWidth() * 0.5f); 29 | view.setPivotY(view.getHeight() * 0.5f); 30 | view.setRotationX(rotation); 31 | } 32 | 33 | @Override 34 | protected void onPostTransform(View page, float position) { 35 | super.onPostTransform(page, position); 36 | 37 | if (position > -0.5f && position < 0.5f) { 38 | page.setVisibility(View.VISIBLE); 39 | } else { 40 | page.setVisibility(View.INVISIBLE); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/transformer/ForegroundToBackgroundTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Toxic Bakery 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.youth.banner.transformer; 18 | 19 | import android.view.View; 20 | 21 | public class ForegroundToBackgroundTransformer extends ABaseTransformer { 22 | 23 | @Override 24 | protected void onTransform(View view, float position) { 25 | final float height = view.getHeight(); 26 | final float width = view.getWidth(); 27 | final float scale = min(position > 0 ? 1f : Math.abs(1f + position), 0.5f); 28 | 29 | view.setScaleX(scale); 30 | view.setScaleY(scale); 31 | view.setPivotX(width * 0.5f); 32 | view.setPivotY(height * 0.5f); 33 | view.setTranslationX(position > 0 ? width * position : -width * position * 0.25f); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/transformer/RotateDownTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Toxic Bakery 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.youth.banner.transformer; 18 | 19 | import android.view.View; 20 | 21 | public class RotateDownTransformer extends ABaseTransformer { 22 | 23 | private static final float ROT_MOD = -15f; 24 | 25 | @Override 26 | protected void onTransform(View view, float position) { 27 | final float width = view.getWidth(); 28 | final float height = view.getHeight(); 29 | final float rotation = ROT_MOD * position * -1.25f; 30 | 31 | view.setPivotX(width * 0.5f); 32 | view.setPivotY(height); 33 | view.setRotation(rotation); 34 | } 35 | 36 | @Override 37 | protected boolean isPagingEnabled() { 38 | return true; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/transformer/RotateUpTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Toxic Bakery 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.youth.banner.transformer; 18 | 19 | import android.view.View; 20 | 21 | public class RotateUpTransformer extends ABaseTransformer { 22 | 23 | private static final float ROT_MOD = -15f; 24 | 25 | @Override 26 | protected void onTransform(View view, float position) { 27 | final float width = view.getWidth(); 28 | final float rotation = ROT_MOD * position; 29 | 30 | view.setPivotX(width * 0.5f); 31 | view.setPivotY(0f); 32 | view.setTranslationX(0f); 33 | view.setRotation(rotation); 34 | } 35 | 36 | @Override 37 | protected boolean isPagingEnabled() { 38 | return true; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/transformer/ScaleInOutTransformer.java: -------------------------------------------------------------------------------- 1 | package com.youth.banner.transformer; 2 | 3 | import android.view.View; 4 | 5 | public class ScaleInOutTransformer extends ABaseTransformer { 6 | 7 | @Override 8 | protected void onTransform(View view, float position) { 9 | view.setPivotX(position < 0 ? 0 : view.getWidth()); 10 | view.setPivotY(view.getHeight() / 2f); 11 | float scale = position < 0 ? 1f + position : 1f - position; 12 | view.setScaleX(scale); 13 | view.setScaleY(scale); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/transformer/StackTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Toxic Bakery 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.youth.banner.transformer; 18 | 19 | import android.view.View; 20 | 21 | public class StackTransformer extends ABaseTransformer { 22 | 23 | @Override 24 | protected void onTransform(View view, float position) { 25 | view.setTranslationX(position < 0 ? 0f : -view.getWidth() * position); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/transformer/TabletTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Toxic Bakery 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.youth.banner.transformer; 18 | 19 | import android.graphics.Camera; 20 | import android.graphics.Matrix; 21 | import android.view.View; 22 | 23 | public class TabletTransformer extends ABaseTransformer { 24 | 25 | private static final Matrix OFFSET_MATRIX = new Matrix(); 26 | private static final Camera OFFSET_CAMERA = new Camera(); 27 | private static final float[] OFFSET_TEMP_FLOAT = new float[2]; 28 | 29 | @Override 30 | protected void onTransform(View view, float position) { 31 | final float rotation = (position < 0 ? 30f : -30f) * Math.abs(position); 32 | 33 | view.setTranslationX(getOffsetXForRotation(rotation, view.getWidth(), view.getHeight())); 34 | view.setPivotX(view.getWidth() * 0.5f); 35 | view.setPivotY(0); 36 | view.setRotationY(rotation); 37 | } 38 | 39 | protected static final float getOffsetXForRotation(float degrees, int width, int height) { 40 | OFFSET_MATRIX.reset(); 41 | OFFSET_CAMERA.save(); 42 | OFFSET_CAMERA.rotateY(Math.abs(degrees)); 43 | OFFSET_CAMERA.getMatrix(OFFSET_MATRIX); 44 | OFFSET_CAMERA.restore(); 45 | 46 | OFFSET_MATRIX.preTranslate(-width * 0.5f, -height * 0.5f); 47 | OFFSET_MATRIX.postTranslate(width * 0.5f, height * 0.5f); 48 | OFFSET_TEMP_FLOAT[0] = width; 49 | OFFSET_TEMP_FLOAT[1] = height; 50 | OFFSET_MATRIX.mapPoints(OFFSET_TEMP_FLOAT); 51 | return (width - OFFSET_TEMP_FLOAT[0]) * (degrees > 0.0f ? 1.0f : -1.0f); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/transformer/ZoomInTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Toxic Bakery 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.youth.banner.transformer; 18 | 19 | import android.view.View; 20 | 21 | public class ZoomInTransformer extends ABaseTransformer { 22 | 23 | @Override 24 | protected void onTransform(View view, float position) { 25 | final float scale = position < 0 ? position + 1f : Math.abs(1f - position); 26 | view.setScaleX(scale); 27 | view.setScaleY(scale); 28 | view.setPivotX(view.getWidth() * 0.5f); 29 | view.setPivotY(view.getHeight() * 0.5f); 30 | view.setAlpha(position < -1f || position > 1f ? 0f : 1f - (scale - 1f)); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/transformer/ZoomOutSlideTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Toxic Bakery 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.youth.banner.transformer; 18 | 19 | import android.view.View; 20 | 21 | public class ZoomOutSlideTransformer extends ABaseTransformer { 22 | 23 | private static final float MIN_SCALE = 0.85f; 24 | private static final float MIN_ALPHA = 0.5f; 25 | 26 | @Override 27 | protected void onTransform(View view, float position) { 28 | if (position >= -1 || position <= 1) { 29 | // Modify the default slide transition to shrink the page as well 30 | final float height = view.getHeight(); 31 | final float width = view.getWidth(); 32 | final float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position)); 33 | final float vertMargin = height * (1 - scaleFactor) / 2; 34 | final float horzMargin = width * (1 - scaleFactor) / 2; 35 | 36 | // Center vertically 37 | view.setPivotY(0.5f * height); 38 | view.setPivotX(0.5f * width); 39 | 40 | if (position < 0) { 41 | view.setTranslationX(horzMargin - vertMargin / 2); 42 | } else { 43 | view.setTranslationX(-horzMargin + vertMargin / 2); 44 | } 45 | 46 | // Scale the page down (between MIN_SCALE and 1) 47 | view.setScaleX(scaleFactor); 48 | view.setScaleY(scaleFactor); 49 | 50 | // Fade the page relative to its size. 51 | view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA)); 52 | } 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/transformer/ZoomOutTranformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Toxic Bakery 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.youth.banner.transformer; 18 | 19 | import android.view.View; 20 | 21 | public class ZoomOutTranformer extends ABaseTransformer { 22 | 23 | @Override 24 | protected void onTransform(View view, float position) { 25 | final float scale = 1f + Math.abs(position); 26 | view.setScaleX(scale); 27 | view.setScaleY(scale); 28 | view.setPivotX(view.getWidth() * 0.5f); 29 | view.setPivotY(view.getHeight() * 0.5f); 30 | view.setAlpha(position < -1f || position > 1f ? 0f : 1f - (scale - 1f)); 31 | if(position == -1){ 32 | view.setTranslationX(view.getWidth() * -1); 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /banner/src/main/java/com/youth/banner/view/BannerViewPager.java: -------------------------------------------------------------------------------- 1 | package com.youth.banner.view; 2 | 3 | import android.content.Context; 4 | import android.support.v4.view.ViewPager; 5 | import android.util.AttributeSet; 6 | import android.view.MotionEvent; 7 | 8 | 9 | public class BannerViewPager extends ViewPager { 10 | private boolean scrollable = true; 11 | 12 | public BannerViewPager(Context context) { 13 | super(context); 14 | } 15 | 16 | public BannerViewPager(Context context, AttributeSet attrs) { 17 | super(context, attrs); 18 | setClipChildren(false); 19 | } 20 | 21 | @Override 22 | public boolean onTouchEvent(MotionEvent ev) { 23 | if(this.scrollable) { 24 | if (getCurrentItem() == 0 && getChildCount() == 0) { 25 | return false; 26 | } 27 | return super.onTouchEvent(ev); 28 | } else { 29 | return false; 30 | } 31 | } 32 | 33 | @Override 34 | public boolean onInterceptTouchEvent(MotionEvent ev) { 35 | if(this.scrollable) { 36 | if (getCurrentItem() == 0 && getChildCount() == 0) { 37 | return false; 38 | } 39 | return super.onInterceptTouchEvent(ev); 40 | } else { 41 | return false; 42 | } 43 | } 44 | 45 | public void setScrollable(boolean scrollable) { 46 | this.scrollable = scrollable; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /banner/src/main/res/animator/scale_with_alpha.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /banner/src/main/res/drawable/black_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | -------------------------------------------------------------------------------- /banner/src/main/res/drawable/gray_radius.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /banner/src/main/res/drawable/no_banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/banner/src/main/res/drawable/no_banner.png -------------------------------------------------------------------------------- /banner/src/main/res/drawable/white_radius.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /banner/src/main/res/values/attr.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /banner/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Oct 18 14:59:29 CST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip 7 | -------------------------------------------------------------------------------- /json/plugin_list.json: -------------------------------------------------------------------------------- 1 | { 2 | "errorCode": 0, 3 | "errorMsg": "", 4 | "data": [ 5 | { 6 | "thumb": "https://raw.githubusercontent.com/xujiaji/xujiaji.github.io/pictures/wanandroid/plugin-thumb/SolarProgresView.gif", 7 | "name":"SolarProgresView", 8 | "description":"类似于太阳花形状的自定义进度条,主要根据光线传感器展示光线强度", 9 | "pkg":"com.mqt.solarprogressview", 10 | "start_class":"com.mqt.solarprogressview.SampleActy", 11 | "version_code":1, 12 | "url":"https://github.com/miqt/SolarProgressView" 13 | }, 14 | { 15 | "thumb": "https://raw.githubusercontent.com/xujiaji/xujiaji.github.io/pictures/wanandroid/plugin-thumb/RippleCheckBox.png", 16 | "name": "RippleCheckBox", 17 | "description": "简洁,舒服,波纹动画,勾选动画,高度可控的波纹CheckBox", 18 | "pkg": "com.xujiaji.ripplecheckbox", 19 | "start_class": "com.xujiaji.ripplecheckbox.MainActivity", 20 | "version_code": 2, 21 | "url": "https://github.com/xujiaji/RippleCheckBox" 22 | }, 23 | { 24 | "thumb": "https://raw.githubusercontent.com/xujiaji/xujiaji.github.io/pictures/wanandroid/plugin-thumb/stepview.png", 25 | "name": "自定义签到的步骤View", 26 | "description": "以七天为周天,执行当天签到需要一个动画效果;签到前灰色,签到后变为绿色;每天加的分数不一定,第三天和第七天加的比较多,分数签到完成为橙色,有up标签。", 27 | "pkg": "com.sorgs.stepview", 28 | "start_class": "com.sorgs.stepview.ui.activity.MainActivity", 29 | "version_code": 1, 30 | "url": "https://github.com/sorgs/StepView" 31 | }, 32 | { 33 | "thumb": "https://raw.githubusercontent.com/xujiaji/xujiaji.github.io/pictures/wanandroid/plugin-thumb/happy-bubble.png", 34 | "name": "HappyBubble", 35 | "description": "BubbleLayout随意变化的气泡布局,BubbleDialog根据点击View的位置定位它的位置,BubbleDialog可定制方向等!", 36 | "pkg": "com.xujiaji.happybubbletest", 37 | "start_class": "com.xujiaji.happybubbletest.MainActivity", 38 | "version_code": 2, 39 | "url": "https://github.com/xujiaji/HappyBubble" 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /json/version.json: -------------------------------------------------------------------------------- 1 | { 2 | "errorCode":0, 3 | "errorMsg":"", 4 | "data":{ 5 | "version_name":"1.0.5", 6 | "version_code":6, 7 | "update_info":"1.删除首页右下角清单入口图标;\n2.清单将作为单独的项目运作;", 8 | "file_size":"9.05M", 9 | "constraint":false, 10 | "apk_url":"https://github.com/xujiaji/WanAndroid/releases/download/v1.0.5/app-release.apk" 11 | } 12 | } -------------------------------------------------------------------------------- /pybridge/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /pybridge/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion rootProject.compileSdk 5 | 6 | defaultConfig { 7 | minSdkVersion rootProject.minSdk 8 | targetSdkVersion rootProject.targetSdk 9 | versionCode 1 10 | versionName "1.0" 11 | } 12 | buildTypes { 13 | release { 14 | minifyEnabled false 15 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 16 | } 17 | } 18 | sourceSets.main { 19 | jni.srcDirs = [] 20 | jniLibs.srcDir 'src/main/libs' 21 | } 22 | } 23 | 24 | dependencies { 25 | api fileTree(dir: 'libs', include: ['*.jar']) 26 | implementation "com.android.support:appcompat-v7:$support" 27 | } 28 | -------------------------------------------------------------------------------- /pybridge/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/jventura/Library/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 | -------------------------------------------------------------------------------- /pybridge/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /pybridge/src/main/assets/python/bootstrap.py: -------------------------------------------------------------------------------- 1 | """ 2 | This file is executed when the Python interpreter is started. 3 | Use this file to configure all your necessary python code. 4 | 5 | """ 6 | 7 | import json 8 | import html_to_json 9 | import parser_links 10 | 11 | 12 | def router(args): 13 | """ 14 | Defines the router function that routes by function name. 15 | 16 | :param args: JSON arguments 17 | :return: JSON response 18 | """ 19 | values = json.loads(args) 20 | 21 | try: 22 | function = routes[values.get('function')] 23 | 24 | status = 'ok' 25 | res = function(values) 26 | except KeyError: 27 | status = 'fail' 28 | res = None 29 | 30 | return json.dumps({ 31 | 'status': status, 32 | 'result': res, 33 | }) 34 | 35 | 36 | def greet(args): 37 | """Simple function that greets someone.""" 38 | return 'Hello %s' % args['name'] 39 | 40 | 41 | def add(args): 42 | """Simple function to add two numbers.""" 43 | return args['a'] + args['b'] 44 | 45 | 46 | def mul(args): 47 | """Simple function to multiply two numbers.""" 48 | return args['a'] * args['b'] 49 | 50 | def parserAPISPage(args): 51 | return html_to_json.parserAPISPage(args['data']) 52 | 53 | def parserLinks(args): 54 | return parser_links.parserFriendLinks(args['data']) 55 | 56 | routes = { 57 | 'greet': greet, 58 | 'add': add, 59 | 'mul': mul, 60 | 'parserAPISPage': parserAPISPage, 61 | 'parserLinks': parserLinks 62 | } 63 | -------------------------------------------------------------------------------- /pybridge/src/main/assets/python/html_test.py: -------------------------------------------------------------------------------- 1 | from html.parser import HTMLParser 2 | 3 | 4 | class MyHTMLParser(HTMLParser): 5 | 6 | def __init__(self): 7 | HTMLParser.__init__(self) 8 | self.resultValue = [] 9 | 10 | def handle_starttag(self, tag, attrs): 11 | self.resultValue.append(tag) 12 | print('<%s>' % tag) 13 | print('attr:', attrs) 14 | for attr in attrs: 15 | if attr == ('class', 'list_navi listNavi'): 16 | print(True) 17 | print(attr) 18 | 19 | def handle_endtag(self, tag): 20 | print('' % tag) 21 | 22 | def handle_startendtag(self, tag, attrs): 23 | print('<%s/>' % tag) 24 | 25 | def handle_data(self, data): 26 | print(data) 27 | 28 | def handle_comment(self, data): 29 | print('') 30 | 31 | def handle_entityref(self, name): 32 | print('&%s;' % name) 33 | 34 | def handle_charref(self, name): 35 | print('&#%s;' % name) 36 | 37 | def runParser(): 38 | parser = MyHTMLParser() 39 | parser.feed(''' 40 | 41 | 42 |
    d11111
43 | 44 |

Some html HTML tutorial...
END

45 | ''') 46 | return parser.resultValue 47 | 48 | -------------------------------------------------------------------------------- /pybridge/src/main/assets/python/stdlib.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/pybridge/src/main/assets/python/stdlib.zip -------------------------------------------------------------------------------- /pybridge/src/main/java/com/jventura/pybridge/PyBridge.java: -------------------------------------------------------------------------------- 1 | package com.jventura.pybridge; 2 | 3 | import org.json.JSONObject; 4 | import org.json.JSONException; 5 | 6 | 7 | public class PyBridge { 8 | 9 | /** 10 | * Initializes the Python interpreter. 11 | * 12 | * @param datapath the location of the extracted python files 13 | * @return error code 14 | */ 15 | public static native int start(String datapath); 16 | 17 | /** 18 | * Stops the Python interpreter. 19 | * 20 | * @return error code 21 | */ 22 | public static native int stop(); 23 | 24 | /** 25 | * Sends a string payload to the Python interpreter. 26 | * 27 | * @param payload the payload string 28 | * @return a string with the result 29 | */ 30 | public static native String call(String payload); 31 | 32 | /** 33 | * Sends a JSON payload to the Python interpreter. 34 | * 35 | * @param payload JSON payload 36 | * @return JSON response 37 | */ 38 | public static JSONObject call(JSONObject payload) { 39 | String result = call(payload.toString()); 40 | try { 41 | return new JSONObject(result); 42 | } catch (JSONException e) { 43 | e.printStackTrace(); 44 | return null; 45 | } 46 | } 47 | 48 | // Load library 49 | static { 50 | System.loadLibrary("pybridge"); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /pybridge/src/main/java/com/jventura/pybridge/PyManager.java: -------------------------------------------------------------------------------- 1 | package com.jventura.pybridge; 2 | 3 | import android.content.Context; 4 | import android.widget.Toast; 5 | 6 | import org.json.JSONException; 7 | import org.json.JSONObject; 8 | 9 | 10 | public class PyManager { 11 | 12 | private static PyManager instance; 13 | private String pythonPath; 14 | 15 | private PyManager(Context context) { 16 | // Extract python files from assets 17 | AssetExtractor assetExtractor = new AssetExtractor(context); 18 | assetExtractor.removeAssets("python"); 19 | assetExtractor.copyAssets("python"); 20 | // Get the extracted assets directory 21 | pythonPath = assetExtractor.getAssetsDataDir() + "python"; 22 | } 23 | 24 | public static PyManager getInstance(Context context) { 25 | if (instance == null) { 26 | synchronized (PyManager.class) { 27 | instance = new PyManager(context); 28 | } 29 | } 30 | return instance; 31 | } 32 | 33 | private String handle(String data, String funName) { 34 | // Start the Python interpreter 35 | PyBridge.start(pythonPath); 36 | 37 | // Call a Python function 38 | try { 39 | JSONObject json = new JSONObject(); 40 | json.put("function", funName); 41 | json.put("data", data); 42 | 43 | JSONObject result = PyBridge.call(json); 44 | return result.getString("result"); 45 | 46 | // TextView textView = (TextView) findViewById(R.id.textView); 47 | // textView.setText(answer); 48 | 49 | } catch (JSONException e) { 50 | e.printStackTrace(); 51 | return ""; 52 | } finally { 53 | // Stop the interpreter 54 | PyBridge.stop(); 55 | } 56 | } 57 | 58 | public String parserOPENAPISHtml(String data) { 59 | return handle(data, "parserAPISPage"); 60 | } 61 | 62 | public String parserFriendLinks(String data) { 63 | return handle(data, "parserLinks"); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /pybridge/src/main/jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | CRYSTAX_PATH := D:\Android\crystax-ndk-10.3.2 3 | 4 | 5 | # Build libpybridge.so 6 | 7 | include $(CLEAR_VARS) 8 | LOCAL_MODULE := pybridge 9 | LOCAL_SRC_FILES := pybridge.c 10 | LOCAL_LDLIBS := -llog 11 | LOCAL_SHARED_LIBRARIES := python3.5m 12 | include $(BUILD_SHARED_LIBRARY) 13 | 14 | 15 | # Include libpython3.5m.so 16 | 17 | include $(CLEAR_VARS) 18 | LOCAL_MODULE := python3.5m 19 | LOCAL_SRC_FILES := $(CRYSTAX_PATH)/sources/python/3.5/libs/$(TARGET_ARCH_ABI)/libpython3.5m.so 20 | LOCAL_EXPORT_CFLAGS := -I $(CRYSTAX_PATH)/sources/python/3.5/include/python/ 21 | include $(PREBUILT_SHARED_LIBRARY) 22 | -------------------------------------------------------------------------------- /pybridge/src/main/jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_PLATFORM := android-19 2 | APP_ABI := armeabi-v7a x86 3 | -------------------------------------------------------------------------------- /pybridge/src/main/libs/armeabi-v7a/libcrystax.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/pybridge/src/main/libs/armeabi-v7a/libcrystax.so -------------------------------------------------------------------------------- /pybridge/src/main/libs/armeabi-v7a/libpybridge.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/pybridge/src/main/libs/armeabi-v7a/libpybridge.so -------------------------------------------------------------------------------- /pybridge/src/main/libs/armeabi-v7a/libpython3.5m.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/pybridge/src/main/libs/armeabi-v7a/libpython3.5m.so -------------------------------------------------------------------------------- /pybridge/src/main/libs/x86/libcrystax.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/pybridge/src/main/libs/x86/libcrystax.so -------------------------------------------------------------------------------- /pybridge/src/main/libs/x86/libpybridge.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/pybridge/src/main/libs/x86/libpybridge.so -------------------------------------------------------------------------------- /pybridge/src/main/libs/x86/libpython3.5m.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/pybridge/src/main/libs/x86/libpython3.5m.so -------------------------------------------------------------------------------- /pybridge/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /pybridge/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /pybridge/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | PyApp 3 | 4 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ":banner", ":pybridge" 2 | -------------------------------------------------------------------------------- /xu.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujiaji/WanAndroid/dd3cebc670a769e73dcf9a163100358e24f3d211/xu.jks --------------------------------------------------------------------------------