├── .gitignore
├── PhotoPicker
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── me
│ │ └── iwf
│ │ └── photopicker
│ │ ├── PhotoPagerActivity.java
│ │ ├── PhotoPicker.java
│ │ ├── PhotoPickerActivity.java
│ │ ├── PhotoPreview.java
│ │ ├── adapter
│ │ ├── PhotoGridAdapter.java
│ │ ├── PhotoPagerAdapter.java
│ │ ├── PopupDirectoryListAdapter.java
│ │ └── SelectableAdapter.java
│ │ ├── entity
│ │ ├── Photo.java
│ │ └── PhotoDirectory.java
│ │ ├── event
│ │ ├── OnItemCheckListener.java
│ │ ├── OnPhotoClickListener.java
│ │ └── Selectable.java
│ │ ├── fragment
│ │ ├── ImagePagerFragment.java
│ │ └── PhotoPickerFragment.java
│ │ ├── utils
│ │ ├── AndroidLifecycleUtils.java
│ │ ├── FileUtils.java
│ │ ├── ImageCaptureManager.java
│ │ ├── MediaStoreHelper.java
│ │ ├── PermissionsConstant.java
│ │ ├── PermissionsUtils.java
│ │ ├── PhotoDirectoryLoader.java
│ │ └── PhotoFileProvider.java
│ │ └── widget
│ │ ├── SquareItemLayout.java
│ │ └── TouchImageView.java
│ └── res
│ ├── drawable-v21
│ └── __picker_bg_material_item.xml
│ ├── drawable-xxhdpi
│ ├── __picker_checkbox_marked.png
│ ├── __picker_checkbox_n.png
│ ├── __picker_ic_broken_image_black_48dp.png
│ ├── __picker_ic_camera_n.png
│ ├── __picker_ic_camera_p.png
│ ├── __picker_ic_delete_black_24dp.png
│ ├── __picker_ic_delete_n.png
│ ├── __picker_ic_delete_p.png
│ └── __picker_ic_photo_black_48dp.png
│ ├── drawable
│ ├── __picker_bg_material_item.xml
│ ├── __picker_camera.xml
│ ├── __picker_checkbox_bg.xml
│ ├── __picker_delete.xml
│ └── __picker_photo_bg.xml
│ ├── layout
│ ├── __picker_activity_photo_pager.xml
│ ├── __picker_activity_photo_picker.xml
│ ├── __picker_fragment_photo_picker.xml
│ ├── __picker_item_directory.xml
│ ├── __picker_item_photo.xml
│ ├── __picker_picker_fragment_image_pager.xml
│ ├── __picker_picker_item_pager.xml
│ └── __picker_toolbar.xml
│ ├── menu
│ ├── __picker_menu_picker.xml
│ └── __picker_menu_preview.xml
│ ├── values-v21
│ └── colors.xml
│ ├── values-zh
│ └── strings.xml
│ ├── values
│ ├── colors.xml
│ ├── dimen.xml
│ ├── strings.xml
│ └── styles.xml
│ └── xml
│ └── __picker_provider_paths.xml
├── README.md
├── app
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── assets
│ ├── about.html
│ └── icon_photo_add.png
│ ├── java
│ └── me
│ │ └── cl
│ │ └── lingxi
│ │ ├── adapter
│ │ ├── EvaluateAdapter.java
│ │ ├── FeedAdapter.java
│ │ ├── FeedPhotoAdapter.java
│ │ ├── FutureAdapter.java
│ │ ├── PhotoSelAdapter.java
│ │ ├── PublicLicenseAdapter.java
│ │ ├── RelevantAdapter.java
│ │ ├── ReplyAdapter.java
│ │ ├── TopicEitAdapter.java
│ │ ├── UserInfoAdapter.java
│ │ └── ViewPagerAdapter.java
│ │ ├── common
│ │ ├── config
│ │ │ ├── Api.java
│ │ │ └── Constants.java
│ │ ├── glide
│ │ │ ├── CustomGlideExtension.java
│ │ │ ├── CustomGlideModule.java
│ │ │ └── OkHttpLibraryGlideModule.java
│ │ ├── okhttp
│ │ │ ├── GetRequest.java
│ │ │ ├── HttpLoggerInterceptor.java
│ │ │ ├── OkUtil.java
│ │ │ ├── PostRequest.java
│ │ │ └── ResultCallback.java
│ │ ├── result
│ │ │ ├── Result.java
│ │ │ └── ResultConstant.java
│ │ ├── util
│ │ │ ├── ContentUtil.java
│ │ │ ├── DateUtil.java
│ │ │ ├── FeedContentUtil.java
│ │ │ ├── GsonUtil.java
│ │ │ ├── ImageUtil.java
│ │ │ ├── MD5Util.java
│ │ │ ├── NetworkUtil.java
│ │ │ ├── SPUtil.java
│ │ │ └── Utils.java
│ │ └── widget
│ │ │ ├── AppBarStateChangeListener.java
│ │ │ └── GridItemDecoration.java
│ │ ├── dialog
│ │ ├── EditTextDialog.java
│ │ ├── FutureDialog.java
│ │ └── LogoutDialog.java
│ │ ├── entity
│ │ ├── AppVersion.java
│ │ ├── Comment.java
│ │ ├── Feed.java
│ │ ├── Future.java
│ │ ├── Like.java
│ │ ├── PageInfo.java
│ │ ├── PublicLicense.java
│ │ ├── Relevant.java
│ │ ├── Reply.java
│ │ ├── Topic.java
│ │ ├── User.java
│ │ ├── UserInfo.java
│ │ └── UserToken.java
│ │ ├── module
│ │ ├── LxApplication.java
│ │ ├── feed
│ │ │ ├── FeedActivity.java
│ │ │ ├── PublishActivity.java
│ │ │ ├── ShareFeedActivity.java
│ │ │ └── TopicEitActivity.java
│ │ ├── future
│ │ │ └── FutureActivity.java
│ │ ├── main
│ │ │ ├── FeedFragment.java
│ │ │ ├── FutureFragment.java
│ │ │ ├── HomeFragment.java
│ │ │ ├── MainActivity.java
│ │ │ ├── MessageChildFragment.java
│ │ │ ├── MessageFragment.java
│ │ │ └── MineFragment.java
│ │ ├── member
│ │ │ ├── LoginActivity.java
│ │ │ ├── RegisterActivity.java
│ │ │ ├── ResetPwdActivity.java
│ │ │ └── UserActivity.java
│ │ ├── mine
│ │ │ ├── PersonalInfoActivity.java
│ │ │ └── RelevantActivity.java
│ │ ├── search
│ │ │ └── SearchActivity.java
│ │ ├── setting
│ │ │ ├── AboutActivity.java
│ │ │ ├── PublicLicenseActivity.java
│ │ │ └── SettingsActivity.java
│ │ ├── splash
│ │ │ └── SplashActivity.java
│ │ └── webview
│ │ │ └── WebActivity.java
│ │ ├── view
│ │ ├── FlowRadioGroup.java
│ │ ├── JellyScrollView.java
│ │ ├── textview
│ │ │ ├── ClickableImageSpan.java
│ │ │ ├── ClickableMovementMethod.java
│ │ │ └── NoLineClickableSpan.java
│ │ └── webview
│ │ │ ├── MoeChromeClient.java
│ │ │ ├── MoeWebClient.java
│ │ │ └── MoeWebView.java
│ │ └── viewmodel
│ │ ├── FeedViewModel.java
│ │ ├── FutureViewModel.java
│ │ ├── TopicViewModel.java
│ │ ├── UploadViewModel.java
│ │ └── UserViewModel.java
│ └── res
│ ├── color
│ ├── bottom_navigation_selector.xml
│ ├── future_selector.xml
│ ├── inc_episode_selector.xml
│ └── selector_text.xml
│ ├── drawable
│ ├── btn_publish_selector.xml
│ ├── future_selector.xml
│ ├── home_card_shape.xml
│ ├── ic_accessory.xml
│ ├── ic_browse.xml
│ ├── ic_camera.xml
│ ├── ic_camera_add.xml
│ ├── ic_camera_fill.xml
│ ├── ic_camera_selector.xml
│ ├── ic_comment.xml
│ ├── ic_delete.xml
│ ├── ic_delete_fill.xml
│ ├── ic_eit.xml
│ ├── ic_favorite.xml
│ ├── ic_home.xml
│ ├── ic_homepage.xml
│ ├── ic_homepage_fill.xml
│ ├── ic_homepage_selector.xml
│ ├── ic_interactive.xml
│ ├── ic_interactive_fill.xml
│ ├── ic_interactive_selector.xml
│ ├── ic_like.xml
│ ├── ic_like_fill.xml
│ ├── ic_like_selector.xml
│ ├── ic_message.xml
│ ├── ic_mine.xml
│ ├── ic_mine_fill.xml
│ ├── ic_mine_selector.xml
│ ├── ic_more.xml
│ ├── ic_more_badge.xml
│ ├── ic_ok.xml
│ ├── ic_password.xml
│ ├── ic_people.xml
│ ├── ic_photo.xml
│ ├── ic_postbox.png
│ ├── ic_search.xml
│ ├── ic_search_t.xml
│ ├── ic_send.xml
│ ├── ic_setup.xml
│ ├── ic_skip.xml
│ ├── ic_topic.xml
│ ├── ic_user.xml
│ ├── img_future_bg.9.png
│ ├── img_lingxi.png
│ ├── img_login.jpg
│ ├── img_miaozi.png
│ ├── img_mine_bc.9.png
│ ├── img_user.png
│ ├── inc_episode_selector.xml
│ ├── more_entry_selector.xml
│ ├── nav_bg.xml
│ ├── nav_item_bg.xml
│ ├── nav_item_bg_selector.xml
│ ├── shape_badge.xml
│ ├── shape_edit.xml
│ └── shape_search.xml
│ ├── layout
│ ├── about_activity.xml
│ ├── edit_dialog.xml
│ ├── feed_action_include.xml
│ ├── feed_activity.xml
│ ├── feed_detail_recycle_item.xml
│ ├── feed_evaluate_recycle_item.xml
│ ├── feed_fragment.xml
│ ├── feed_info_include.xml
│ ├── feed_like_include.xml
│ ├── feed_reply_recycle_item.xml
│ ├── future_activity.xml
│ ├── future_dialog.xml
│ ├── future_fragment.xml
│ ├── future_recycle_item.xml
│ ├── home_fragment.xml
│ ├── include_bottom_navigation.xml
│ ├── include_recycler_view.xml
│ ├── include_tab_layout.xml
│ ├── include_toolbar.xml
│ ├── login_activity.xml
│ ├── main_menu_badge.xml
│ ├── message_child_fragment.xml
│ ├── message_fragment.xml
│ ├── mian_activity.xml
│ ├── mine_fragment.xml
│ ├── mine_logout_dialog.xml
│ ├── personal_info_activity.xml
│ ├── public_license_activity.xml
│ ├── public_license_recycle_item.xml
│ ├── publish_activity.xml
│ ├── publish_photo_recycle_item.xml
│ ├── registe_activity.xml
│ ├── relevant_activity.xml
│ ├── relevant_recycle_item.xml
│ ├── resetpwd_activity.xml
│ ├── search_activity.xml
│ ├── settings_activity.xml
│ ├── splash_activity.xml
│ ├── topic_eit_activity.xml
│ ├── topic_eit_recycle_item.xml
│ ├── user_activity.xml
│ └── web_activity.xml
│ ├── menu
│ ├── future_menu.xml
│ ├── navigation_menu.xml
│ ├── publish_menu.xml
│ ├── search_menu.xml
│ ├── search_view_menu.xml
│ └── send_menu.xml
│ ├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-nodpi
│ └── ic_launcher_background.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── values-en
│ └── strings.xml
│ ├── values-v21
│ ├── colors.xml
│ └── styles.xml
│ ├── values-v23
│ └── colors.xml
│ ├── values-w820dp
│ └── dimens.xml
│ ├── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
│ └── xml
│ ├── network_security_config.xml
│ ├── preference_setting.xml
│ └── provider_paths.xml
├── build.gradle
├── gradle.properties
├── gradle
├── libs.versions.toml
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── library
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ ├── com
│ │ ├── bm
│ │ │ └── library
│ │ │ │ ├── Info.java
│ │ │ │ ├── PhotoView.java
│ │ │ │ └── RotateGestureDetector.java
│ │ └── library
│ │ │ └── flowlayout
│ │ │ ├── FlowLayoutManager.java
│ │ │ └── SpaceItemDecoration.java
│ └── me
│ │ └── cl
│ │ └── library
│ │ ├── base
│ │ ├── BaseActivity.java
│ │ └── BaseFragment.java
│ │ ├── loadmore
│ │ ├── LoadMord.java
│ │ ├── LoadMoreAdapter.java
│ │ ├── LoadMoreViewHolder.java
│ │ └── OnLoadMoreListener.java
│ │ ├── model
│ │ └── TipMessage.java
│ │ ├── photo
│ │ ├── PhotoActivity.java
│ │ ├── PhotoAdapter.java
│ │ ├── PhotoBrowser.java
│ │ ├── PhotoDownloadService.java
│ │ ├── PhotoListener.java
│ │ └── PhotoViewPager.java
│ │ ├── recycle
│ │ ├── ItemAnimator.java
│ │ └── ItemDecoration.java
│ │ ├── util
│ │ ├── ColorPhrase.java
│ │ ├── ToastUtil.java
│ │ └── ToolbarUtil.java
│ │ └── view
│ │ ├── LoadingDialog.java
│ │ └── MoeToast.java
│ └── res
│ ├── drawable
│ ├── ic_navigate.xml
│ ├── img_toast_bc.9.png
│ ├── loading_frame.xml
│ ├── loading_icon_1.png
│ ├── loading_icon_2.png
│ ├── loading_icon_3.png
│ ├── loading_icon_4.png
│ └── photo_text_shape.xml
│ ├── layout
│ ├── lib_dialog_progress.xml
│ ├── lib_load_more.xml
│ ├── photo_activity.xml
│ └── photo_adapter_item.xml
│ └── values
│ └── value.xml
├── screenshot
├── Screenshot_about.jpg
├── Screenshot_feed.jpg
├── Screenshot_home.jpg
├── Screenshot_login.jpg
├── Screenshot_message.jpg
├── Screenshot_mine.jpg
├── Screenshot_publish.jpg
├── Screenshot_relevant.jpg
├── Screenshot_user.jpg
└── Screenshot_welcome.jpg
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | /.gradle
2 | /.idea
3 | /alpha
4 | /app/build
5 | /app/app.iml
6 | /build
7 | /captures
8 | /library/build
9 | /library/library.iml
10 | /online
11 | /PhotoPicker/build
12 | /PhotoPicker/PhotoPicker.iml
13 | /lingcikey.jks
14 | /lingxi-android.iml
15 | /local.properties
--------------------------------------------------------------------------------
/PhotoPicker/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 |
5 | compileSdkVersion libs.versions.compileSdk.get()
6 |
7 | resourcePrefix "__picker_"
8 |
9 | dexOptions {
10 | javaMaxHeapSize "4g"
11 | }
12 |
13 | defaultConfig {
14 | minSdkVersion libs.versions.minSdk.get()
15 | targetSdkVersion libs.versions.targetSdk.get()
16 | }
17 |
18 | lintOptions {
19 | abortOnError false
20 | }
21 |
22 | }
23 |
24 | dependencies {
25 | api fileTree(dir: 'libs', include: ['*.jar'])
26 | api project(":library")
27 | }
--------------------------------------------------------------------------------
/PhotoPicker/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
15 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/java/me/iwf/photopicker/entity/Photo.java:
--------------------------------------------------------------------------------
1 | package me.iwf.photopicker.entity;
2 |
3 | /**
4 | * Created by donglua on 15/6/30.
5 | */
6 | public class Photo {
7 |
8 | private int id;
9 | private String path;
10 |
11 | public Photo(int id, String path) {
12 | this.id = id;
13 | this.path = path;
14 | }
15 |
16 | public Photo() {
17 | }
18 |
19 | @Override public boolean equals(Object o) {
20 | if (this == o) return true;
21 | if (!(o instanceof Photo)) return false;
22 |
23 | Photo photo = (Photo) o;
24 |
25 | return id == photo.id;
26 | }
27 |
28 | @Override public int hashCode() {
29 | return id;
30 | }
31 |
32 | public String getPath() {
33 | return path;
34 | }
35 |
36 | public void setPath(String path) {
37 | this.path = path;
38 | }
39 |
40 | public int getId() {
41 | return id;
42 | }
43 |
44 | public void setId(int id) {
45 | this.id = id;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/java/me/iwf/photopicker/event/OnItemCheckListener.java:
--------------------------------------------------------------------------------
1 | package me.iwf.photopicker.event;
2 |
3 | import me.iwf.photopicker.entity.Photo;
4 |
5 | /**
6 | * Created by donglua on 15/6/20.
7 | */
8 | public interface OnItemCheckListener {
9 |
10 | /***
11 | *
12 | * @param position 所选图片的位置
13 | * @param path 所选的图片
14 | * @param selectedItemCount 已选数量
15 | * @return enable check
16 | */
17 | boolean onItemCheck(int position, Photo path, int selectedItemCount);
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/java/me/iwf/photopicker/event/OnPhotoClickListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
6 | * Vestibulum commodo. Ut rhoncus gravida arcu.
7 | */
8 |
9 | package me.iwf.photopicker.event;
10 |
11 | import android.view.View;
12 |
13 | /**
14 | * Created by donglua on 15/6/20.
15 | */
16 | public interface OnPhotoClickListener {
17 |
18 | void onClick(View v, int position, boolean showCamera);
19 | }
20 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/java/me/iwf/photopicker/event/Selectable.java:
--------------------------------------------------------------------------------
1 | package me.iwf.photopicker.event;
2 |
3 | import me.iwf.photopicker.entity.Photo;
4 |
5 | /**
6 | * Created by donglua on 15/6/30.
7 | */
8 | public interface Selectable {
9 |
10 |
11 | /**
12 | * Indicates if the item at position position is selected
13 | *
14 | * @param photo Photo of the item to check
15 | * @return true if the item is selected, false otherwise
16 | */
17 | boolean isSelected(Photo photo);
18 |
19 | /**
20 | * Toggle the selection status of the item at a given position
21 | *
22 | * @param photo Photo of the item to toggle the selection status for
23 | */
24 | void toggleSelection(Photo photo);
25 |
26 | /**
27 | * Clear the selection status for all items
28 | */
29 | void clearSelection();
30 |
31 | /**
32 | * Count the selected items
33 | *
34 | * @return Selected items count
35 | */
36 | int getSelectedItemCount();
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/java/me/iwf/photopicker/utils/AndroidLifecycleUtils.java:
--------------------------------------------------------------------------------
1 | package me.iwf.photopicker.utils;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 |
6 | import androidx.fragment.app.Fragment;
7 | import androidx.fragment.app.FragmentActivity;
8 |
9 | public class AndroidLifecycleUtils {
10 | public static boolean canLoadImage(Fragment fragment) {
11 | if (fragment == null) {
12 | return true;
13 | }
14 |
15 | FragmentActivity activity = fragment.getActivity();
16 |
17 | return canLoadImage(activity);
18 | }
19 |
20 | public static boolean canLoadImage(Context context) {
21 | if (context == null) {
22 | return true;
23 | }
24 |
25 | if (!(context instanceof Activity)) {
26 | return true;
27 | }
28 |
29 | Activity activity = (Activity) context;
30 | return canLoadImage(activity);
31 | }
32 |
33 | public static boolean canLoadImage(Activity activity) {
34 | if (activity == null) {
35 | return true;
36 | }
37 |
38 | boolean destroyed = activity.isDestroyed();
39 |
40 | return !destroyed && !activity.isFinishing();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/java/me/iwf/photopicker/utils/FileUtils.java:
--------------------------------------------------------------------------------
1 | package me.iwf.photopicker.utils;
2 |
3 | import java.io.File;
4 |
5 | /**
6 | * Created by myc on 2016/12/14.
7 | * More Code on 1101255053@qq.com
8 | * Description:
9 | */
10 | public class FileUtils {
11 | public static boolean fileIsExists(String path) {
12 | if (path == null || path.trim().length() <= 0) {
13 | return false;
14 | }
15 | try {
16 | File f = new File(path);
17 | if (!f.exists()) {
18 | return false;
19 | }
20 | } catch (Exception e) {
21 | return false;
22 | }
23 | return true;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/java/me/iwf/photopicker/utils/PermissionsConstant.java:
--------------------------------------------------------------------------------
1 | package me.iwf.photopicker.utils;
2 |
3 | import android.Manifest;
4 |
5 | /**
6 | * Created by donglua on 2016/10/19.
7 | */
8 |
9 | public class PermissionsConstant {
10 |
11 | public static final int REQUEST_CAMERA = 1;
12 | public static final int REQUEST_EXTERNAL_READ = 2;
13 | public static final int REQUEST_EXTERNAL_WRITE = 3;
14 |
15 | public static final String[] PERMISSIONS_CAMERA = {
16 | Manifest.permission.CAMERA,
17 | Manifest.permission.WRITE_EXTERNAL_STORAGE
18 | };
19 | public static final String[] PERMISSIONS_EXTERNAL_WRITE = {
20 | Manifest.permission.WRITE_EXTERNAL_STORAGE
21 | };
22 |
23 | public static final String[] PERMISSIONS_EXTERNAL_READ = {
24 | Manifest.permission.READ_EXTERNAL_STORAGE
25 | };
26 | }
27 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/java/me/iwf/photopicker/utils/PermissionsUtils.java:
--------------------------------------------------------------------------------
1 | package me.iwf.photopicker.utils;
2 |
3 | import android.app.Activity;
4 | import android.content.pm.PackageManager;
5 |
6 | import androidx.core.app.ActivityCompat;
7 | import androidx.core.content.ContextCompat;
8 | import androidx.fragment.app.Fragment;
9 |
10 | import static android.Manifest.permission.CAMERA;
11 | import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
12 | import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
13 |
14 | /**
15 | * Created by donglua on 2016/10/19.
16 | */
17 |
18 | public class PermissionsUtils {
19 |
20 | public static boolean checkReadStoragePermission(Activity activity) {
21 | if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) {
22 | return true;
23 | }
24 | int readStoragePermissionState =
25 | ContextCompat.checkSelfPermission(activity, READ_EXTERNAL_STORAGE);
26 |
27 | boolean readStoragePermissionGranted = readStoragePermissionState == PackageManager.PERMISSION_GRANTED;
28 |
29 | if (!readStoragePermissionGranted) {
30 | ActivityCompat.requestPermissions(activity,
31 | PermissionsConstant.PERMISSIONS_EXTERNAL_READ,
32 | PermissionsConstant.REQUEST_EXTERNAL_READ);
33 | }
34 | return readStoragePermissionGranted;
35 | }
36 |
37 | public static boolean checkWriteStoragePermission(Fragment fragment) {
38 |
39 | int writeStoragePermissionState =
40 | ContextCompat.checkSelfPermission(fragment.getContext(), WRITE_EXTERNAL_STORAGE);
41 |
42 | boolean writeStoragePermissionGranted = writeStoragePermissionState == PackageManager.PERMISSION_GRANTED;
43 |
44 | if (!writeStoragePermissionGranted) {
45 | fragment.requestPermissions(PermissionsConstant.PERMISSIONS_EXTERNAL_WRITE,
46 | PermissionsConstant.REQUEST_EXTERNAL_WRITE);
47 | }
48 | return writeStoragePermissionGranted;
49 | }
50 |
51 | public static boolean checkCameraPermission(Fragment fragment) {
52 | int cameraPermissionState = ContextCompat.checkSelfPermission(fragment.getContext(), CAMERA);
53 |
54 | boolean cameraPermissionGranted = cameraPermissionState == PackageManager.PERMISSION_GRANTED;
55 |
56 | if (!cameraPermissionGranted) {
57 | fragment.requestPermissions(PermissionsConstant.PERMISSIONS_CAMERA,
58 | PermissionsConstant.REQUEST_CAMERA);
59 | }
60 | return cameraPermissionGranted;
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/java/me/iwf/photopicker/utils/PhotoDirectoryLoader.java:
--------------------------------------------------------------------------------
1 | package me.iwf.photopicker.utils;
2 |
3 | import android.content.Context;
4 | import android.net.Uri;
5 | import android.provider.MediaStore.Images.Media;
6 |
7 | import androidx.loader.content.CursorLoader;
8 |
9 | import static android.provider.MediaStore.MediaColumns.MIME_TYPE;
10 |
11 | /**
12 | * Created by 黄东鲁 on 15/6/28.
13 | */
14 | public class PhotoDirectoryLoader extends CursorLoader {
15 |
16 | final String[] IMAGE_PROJECTION = {
17 | Media._ID,
18 | Media.DATA,
19 | Media.BUCKET_ID,
20 | Media.BUCKET_DISPLAY_NAME,
21 | Media.DATE_ADDED,
22 | Media.SIZE
23 | };
24 |
25 | public PhotoDirectoryLoader(Context context, boolean showGif) {
26 | super(context);
27 |
28 | setProjection(IMAGE_PROJECTION);
29 | setUri(Media.EXTERNAL_CONTENT_URI);
30 | setSortOrder(Media.DATE_ADDED + " DESC");
31 |
32 | setSelection(
33 | MIME_TYPE + "=? or " + MIME_TYPE + "=? or "+ MIME_TYPE + "=? " + (showGif ? ("or " + MIME_TYPE + "=?") : ""));
34 | String[] selectionArgs;
35 | if (showGif) {
36 | selectionArgs = new String[] { "image/jpeg", "image/png", "image/jpg","image/gif" };
37 | } else {
38 | selectionArgs = new String[] { "image/jpeg", "image/png", "image/jpg" };
39 | }
40 | setSelectionArgs(selectionArgs);
41 | }
42 |
43 | private PhotoDirectoryLoader(Context context, Uri uri, String[] projection, String selection,
44 | String[] selectionArgs, String sortOrder) {
45 | super(context, uri, projection, selection, selectionArgs, sortOrder);
46 | }
47 |
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/java/me/iwf/photopicker/utils/PhotoFileProvider.java:
--------------------------------------------------------------------------------
1 | package me.iwf.photopicker.utils;
2 |
3 | import androidx.core.content.FileProvider;
4 |
5 | /**
6 | * Created by Donglu on 2017/6/7.
7 | */
8 |
9 | public class PhotoFileProvider extends FileProvider {
10 | }
11 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/java/me/iwf/photopicker/widget/SquareItemLayout.java:
--------------------------------------------------------------------------------
1 | package me.iwf.photopicker.widget;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.widget.RelativeLayout;
6 |
7 | /**
8 | * Created by donglua on 15/6/21.
9 | */
10 | public class SquareItemLayout extends RelativeLayout {
11 | public SquareItemLayout(Context context, AttributeSet attrs, int defStyle) {
12 | super(context, attrs, defStyle);
13 | }
14 |
15 | public SquareItemLayout(Context context, AttributeSet attrs) {
16 | super(context, attrs);
17 | }
18 |
19 | public SquareItemLayout(Context context) {
20 | super(context);
21 | }
22 |
23 | @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
24 | setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec));
25 | int childWidthSize = getMeasuredWidth();
26 | heightMeasureSpec =
27 | widthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY);
28 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/drawable-v21/__picker_bg_material_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/drawable-xxhdpi/__picker_checkbox_marked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/PhotoPicker/src/main/res/drawable-xxhdpi/__picker_checkbox_marked.png
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/drawable-xxhdpi/__picker_checkbox_n.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/PhotoPicker/src/main/res/drawable-xxhdpi/__picker_checkbox_n.png
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/drawable-xxhdpi/__picker_ic_broken_image_black_48dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/PhotoPicker/src/main/res/drawable-xxhdpi/__picker_ic_broken_image_black_48dp.png
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/drawable-xxhdpi/__picker_ic_camera_n.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/PhotoPicker/src/main/res/drawable-xxhdpi/__picker_ic_camera_n.png
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/drawable-xxhdpi/__picker_ic_camera_p.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/PhotoPicker/src/main/res/drawable-xxhdpi/__picker_ic_camera_p.png
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/drawable-xxhdpi/__picker_ic_delete_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/PhotoPicker/src/main/res/drawable-xxhdpi/__picker_ic_delete_black_24dp.png
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/drawable-xxhdpi/__picker_ic_delete_n.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/PhotoPicker/src/main/res/drawable-xxhdpi/__picker_ic_delete_n.png
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/drawable-xxhdpi/__picker_ic_delete_p.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/PhotoPicker/src/main/res/drawable-xxhdpi/__picker_ic_delete_p.png
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/drawable-xxhdpi/__picker_ic_photo_black_48dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/PhotoPicker/src/main/res/drawable-xxhdpi/__picker_ic_photo_black_48dp.png
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/drawable/__picker_bg_material_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/drawable/__picker_camera.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/drawable/__picker_checkbox_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
-
7 |
8 |
9 |
13 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | -
22 |
23 |
-
24 |
25 |
26 |
30 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/drawable/__picker_delete.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/drawable/__picker_photo_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
8 |
9 |
10 |
11 | -
12 |
13 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/layout/__picker_activity_photo_pager.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
16 |
17 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/layout/__picker_activity_photo_picker.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/layout/__picker_fragment_photo_picker.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
16 |
17 |
22 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/layout/__picker_item_directory.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
24 |
25 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/layout/__picker_item_photo.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
16 |
17 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/layout/__picker_picker_fragment_image_pager.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/layout/__picker_picker_item_pager.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/layout/__picker_toolbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/menu/__picker_menu_picker.xml:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/menu/__picker_menu_preview.xml:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/values-v21/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #e1e1e1
4 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/values-zh/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 图片
5 | 删除
6 | 完成
7 | 完成(%1$d/%2$d)
8 | %1$d/%2$d
9 | 撤消
10 | 删除了一张图片
11 | 确认删除?
12 | 确定
13 | 取消
14 | 所有图片
15 | 你最多可以选择%1$d张图片
16 | %1$d张
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #CA000000
5 | #44000000
6 | #282828
7 | #f3f3f3
8 |
9 | #282828
10 | #505050
11 | #787878
12 | #ff99cc00
13 | #33ffffff
14 |
15 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/values/dimen.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 48dip
5 | 80dip
6 | 80dip
7 | 80dp
8 |
9 |
10 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Images
4 | Delete
5 | Done
6 | Done(%1$d/%2$d)
7 | %1$d/%2$d
8 | Undo
9 | Deleted a photo
10 | Confirm to delete?
11 | Yes
12 | Cancel
13 | All Images
14 | %1$d
15 | You can only select %1$d images
16 |
17 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/PhotoPicker/src/main/res/xml/__picker_provider_paths.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## 关于灵悉
2 |
3 | 个人兴趣项目,此代码为app端代码
4 | 当前版本包含一图一言,用户注册登录,修改头像,写给未来,动态发布,评论回复,查看我的回复、与我相关等
5 | 项目一直在无规律更新,坚持全凭兴趣,服务端查看[灵悉-server](https://github.com/happycao/lingxi-server)
6 | 网络为OkHttp,只做了简单的get及post请求封装,如有更多需求请选择更好的轮子
7 | Glide版本4.1.1,与之对应PhotoPicker版本0.9.12、glide-transformations版本3.0.1
8 | 调试请使用alpha版本,local版本为本人本地使用,online版本为发布打包版本
9 | 体验请直接点击下载打包版本[点击下载测试版](https://api.ihappyc.eu.org:10514/download/lingxi-test.apk),非安全证书,同意即可,不放心可以不下载
10 | 如果不是用于测试,欢迎来正式版一起玩耍[点击下载正式版](https://api.ihappyc.eu.org:10514/download/lingxi.apk)
11 |
12 | **[2024/11/06]**
13 | 1、提升gradle版本至7.5.1
14 |
15 | **[2021/05/30]**
16 | 1、采用viewmodel剥离网络请求,轻量化Activity/Fragment
17 |
18 | **[2021/05/09]**
19 | 1、此版本升级不可逆,建议悉知所有变更项,如果只是服务不可以,可升级到2021/03/15版本
20 | 2、废弃ButterKnife,采用viewBinding,因此涉及代码较多,升级不可逆
21 | 3、升级Gradle版本到6.6.1,升级gradle build tools到4.0.1,以支持viewBinding
22 | 4、将PhotoPicker只作为本地模块依赖,解决远程包无法下载,同时依赖androidx的包
23 | 5、升级recyclerview版本到1.2.0,获得ConcatAdapter的支持
24 | 6、再次建议测试使用`alpha`版本打包
25 |
26 | **[2021/03/15]**
27 | 1、迁移服务器,旧版本将无法使用,请尽快升级
28 | 2、发布动态时支持查询添加话题和@人
29 |
30 | **[19/10/18]**
31 | 1、移除历史提交,移除了exoPlayer,仅保留灵悉本体功能
32 | 2、迁移至androidx,minSdkVersion变更为21
33 | 3、首页一图一言支持两个图源,可在设置变更为图鉴源
34 | 4、全局白色主题
35 | 5、~~写给未来app内暂时无法查看~~,20/05/17获得支持
36 |
37 | ### 灵悉相关
38 |
39 | - 生无彩凤双飞翼,心有灵犀一点通
40 | - 依托于社交群组,好友向社交圈,供用户吐槽交流
41 | - [x] 用户注册登陆
42 | - [x] 首页一图一言
43 | - [x] 动态发布点赞评论
44 | - [x] 写给未来的信
45 | - [x] 分享链接到灵悉
46 | - [x] app更新跳转浏览器下载更新
47 | - [x] Toast彩蛋
48 | - [ ] 个人信息修改
49 | - [x] 动态发布支持话题
50 | - [x] 动态支持@用户
51 | - [ ] 支持用户动态删除
52 | - [ ] 支持话题分组
53 |
54 | ### 截图展示
55 | 
56 | 
57 | 
58 | 
59 | 
60 | 
61 | 
62 | 
63 | 
64 |
65 | ## 反馈与建议
66 | - QQ:986417980
67 | - 交流群:387355490
68 |
69 |
70 | 欢迎star,感谢阅读这份文档。
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 |
5 | compileSdk 28
6 |
7 | defaultConfig {
8 | applicationId "me.cl.lingxi"
9 | minSdkVersion libs.versions.minSdk.get()
10 | targetSdkVersion libs.versions.targetSdk.get()
11 | versionCode 300
12 | versionName "1.3.0"
13 |
14 | vectorDrawables.useSupportLibrary = true
15 | flavorDimensions "versionCode"
16 | }
17 |
18 | // https://developer.android.google.cn/topic/libraries/view-binding
19 | buildFeatures {
20 | viewBinding = true
21 | }
22 |
23 | productFlavors {
24 | alpha {
25 | applicationId "me.cl.lingxi.alpha"
26 | manifestPlaceholders = [
27 | 'APP_ID' : "me.cl.lingxi.alpha",
28 | 'APP_NAME': "@string/app_name_alpha"
29 | ]
30 | }
31 | local {
32 | applicationId "me.cl.lingxi.local"
33 | manifestPlaceholders = [
34 | 'APP_ID' : "me.cl.lingxi.local",
35 | 'APP_NAME': "@string/app_name_local"
36 | ]
37 | }
38 | online {
39 | applicationId "me.cl.lingxi"
40 | manifestPlaceholders = [
41 | 'APP_ID' : "me.cl.lingxi",
42 | 'APP_NAME': "@string/app_name"
43 | ]
44 | }
45 | }
46 |
47 | buildTypes {
48 | release {
49 | minifyEnabled false
50 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
51 | }
52 | }
53 |
54 | lintOptions {
55 | abortOnError false
56 | disable 'GoogleAppIndexingWarning'
57 | }
58 |
59 | compileOptions {
60 | targetCompatibility JavaVersion.VERSION_1_8
61 | sourceCompatibility JavaVersion.VERSION_1_8
62 | }
63 |
64 | }
65 |
66 | dependencies {
67 | implementation fileTree(include: ['*.jar'], dir: 'libs')
68 | implementation project(":PhotoPicker")
69 | implementation libs.androidx.recyclerview
70 | implementation libs.androidx.constraintlayout
71 | implementation libs.okhttp
72 | implementation libs.gson
73 | implementation libs.bundles.glide
74 | annotationProcessor libs.glide.compiler
75 | implementation libs.compressor
76 | // 解决Glide找不到Android声明库问题
77 | //annotationProcessor libs.androidx.annotation
78 |
79 | // 权限申请
80 | implementation libs.rxjava
81 | implementation libs.rxpermissions
82 | }
83 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\Android Studio\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/main/assets/icon_photo_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/app/src/main/assets/icon_photo_add.png
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/adapter/ReplyAdapter.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.adapter;
2 |
3 | import android.view.LayoutInflater;
4 | import android.view.View;
5 | import android.view.ViewGroup;
6 |
7 | import androidx.annotation.NonNull;
8 | import androidx.appcompat.widget.AppCompatTextView;
9 | import androidx.recyclerview.widget.RecyclerView;
10 |
11 | import java.util.List;
12 |
13 | import me.cl.lingxi.common.util.Utils;
14 | import me.cl.lingxi.databinding.FeedReplyRecycleItemBinding;
15 | import me.cl.lingxi.entity.Reply;
16 |
17 | /**
18 | * Reply Adapter
19 | */
20 | public class ReplyAdapter extends RecyclerView.Adapter {
21 |
22 | private final List mList;
23 |
24 | private OnItemListener mOnItemListener;
25 |
26 | public interface OnItemListener {
27 | void onItemClick(View view, Reply reply);
28 | }
29 |
30 | public void setOnItemListener(OnItemListener onItemListener) {
31 | this.mOnItemListener = onItemListener;
32 | }
33 |
34 | public ReplyAdapter(List list) {
35 | this.mList = list;
36 | }
37 |
38 | @NonNull
39 | @Override
40 | public ReplyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
41 | FeedReplyRecycleItemBinding binding = FeedReplyRecycleItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
42 | return new ReplyViewHolder(binding);
43 | }
44 |
45 | @Override
46 | public void onBindViewHolder(@NonNull ReplyViewHolder holder, int position) {
47 | holder.bindItem(mList.get(position));
48 | }
49 |
50 | @Override
51 | public int getItemCount() {
52 | return mList.size();
53 | }
54 |
55 | class ReplyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
56 |
57 | private final AppCompatTextView mReplyInfo;
58 | private Reply mReply;
59 |
60 | public ReplyViewHolder(FeedReplyRecycleItemBinding binding) {
61 | super(binding.getRoot());
62 |
63 | mReplyInfo = binding.replyInfo;
64 |
65 | mReplyInfo.setOnClickListener(this);
66 | }
67 |
68 | public void bindItem(Reply reply) {
69 | mReply = reply;
70 | String replyStr = "{" + reply.getUser().getUsername() + "}回复{" + reply.getToUser().getUsername() + "}:" + reply.getCommentInfo();
71 | mReplyInfo.setText(Utils.colorFormat(replyStr));
72 | }
73 |
74 | @Override
75 | public void onClick(View view){
76 | if (mOnItemListener != null) mOnItemListener.onItemClick(view, mReply);
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/adapter/ViewPagerAdapter.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.adapter;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.fragment.app.Fragment;
5 | import androidx.fragment.app.FragmentManager;
6 | import androidx.fragment.app.FragmentPagerAdapter;
7 |
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | /**
12 | * ViewPagerAdapter
13 | */
14 | public class ViewPagerAdapter extends FragmentPagerAdapter {
15 |
16 | private final List mFragments = new ArrayList<>();
17 | private final List mTitles = new ArrayList<>();
18 |
19 | public ViewPagerAdapter(FragmentManager fm) {
20 | super(fm);
21 | }
22 |
23 | public void addFragment(Fragment fragment, String title) {
24 | mFragments.add(fragment);
25 | mTitles.add(title);
26 | }
27 |
28 | @NonNull
29 | @Override
30 | public Fragment getItem(int position) {
31 | return mFragments.get(position);
32 | }
33 |
34 | @Override
35 | public CharSequence getPageTitle(int position) {
36 | return mTitles.get(position);
37 | }
38 |
39 | @Override
40 | public int getCount() {
41 | return mTitles.size();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/common/config/Constants.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.common.config;
2 |
3 | /**
4 | * 常量
5 | */
6 | public class Constants {
7 |
8 | // 回复已读
9 | public static boolean isRead = true;
10 |
11 | // action
12 | public static final String UPDATE_USER_INFO = "me.cl.update.info";
13 |
14 | // 与我相关&我的回复
15 | public static final String REPLY_TYPE = "reply_type";
16 | public static final String REPLY_MY = "reply_my";
17 | public static final String REPLY_RELEVANT = "reply_relevant";
18 |
19 | // 本地缓存key
20 | public static final String SP_USER_ID = "user_id";
21 | public static final String SP_USER_NAME = "user_name";
22 | public static final String SP_BEEN_LOGIN = "been_login";
23 | public static final String SP_UPDATE_FLAG = "update_flag";
24 | public static final String SP_FUTURE_INFO = "sp_future_info";
25 |
26 | // 参数传递
27 | public static final String PASSED_UNREAD_NUM = "unread_num";
28 | public static final String PASSED_USER_NAME = "user_name";
29 | public static final String PASSED_USER_INFO = "user_info";
30 |
31 | // 页面标识
32 | public static final int ACTIVITY_MAIN = 10001;
33 | public static final int ACTIVITY_PUBLISH = 10002;
34 | public static final int ACTIVITY_MOOD = 10003;
35 | public static final int ACTIVITY_PERSONAL = 10004;
36 |
37 | // 回退标识
38 | public static final String GO_INDEX = "go_index";
39 |
40 | // 服务器rss图片
41 | public static final String IMG_URL = Api.rssUrl;
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/common/glide/CustomGlideExtension.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.common.glide;
2 |
3 | import android.annotation.SuppressLint;
4 |
5 | import com.bumptech.glide.annotation.GlideExtension;
6 | import com.bumptech.glide.annotation.GlideOption;
7 | import com.bumptech.glide.request.RequestOptions;
8 |
9 | /**
10 | * @author : happyc
11 | * e-mail : bafs.jy@live.com
12 | * time : 2018/05/31
13 | * desc : GlideOption
14 | * version: 1.0
15 | */
16 | @GlideExtension
17 | public class CustomGlideExtension {
18 |
19 | // 缩略图的最小尺寸,单位:px
20 | private static final int MINI_THUMB_SIZE = 100;
21 |
22 | /**
23 | * 将构造方法设为私有,作为工具类使用
24 | */
25 | private CustomGlideExtension() {
26 | }
27 |
28 | /**
29 | * 1.自己新增的方法的第一个参数必须是RequestOptions options
30 | * 2.方法必须是静态的
31 | */
32 | @SuppressLint("CheckResult")
33 | @GlideOption
34 | public static void miniThumb(RequestOptions options) {
35 | options.fitCenter().override(MINI_THUMB_SIZE);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/common/glide/CustomGlideModule.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.common.glide;
2 |
3 | import android.content.Context;
4 | import android.util.Log;
5 |
6 | import androidx.annotation.NonNull;
7 |
8 | import com.bumptech.glide.GlideBuilder;
9 | import com.bumptech.glide.annotation.GlideModule;
10 | import com.bumptech.glide.load.DecodeFormat;
11 | import com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPool;
12 | import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory;
13 | import com.bumptech.glide.load.engine.cache.LruResourceCache;
14 | import com.bumptech.glide.module.AppGlideModule;
15 | import com.bumptech.glide.request.RequestOptions;
16 |
17 | /**
18 | * @author : happyc
19 | * e-mail : bafs.jy@live.com
20 | * time : 2018/05/31
21 | * desc : 实现AppGlideModule,GlideV4
22 | * version: 1.0
23 | */
24 | @GlideModule
25 | public class CustomGlideModule extends AppGlideModule {
26 |
27 | // 无需实现任何方法即可使用
28 | // 官方文档 https://muyangmin.github.io/glide-docs-cn/doc/configuration.html#applications
29 |
30 | /**
31 | * 相关配置
32 | */
33 | @Override
34 | public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
35 | // 内存缓存
36 | int memoryCacheSizeBytes = 1024 * 1024 * 20; // 20mb
37 | builder.setMemoryCache(new LruResourceCache(memoryCacheSizeBytes));
38 | // Bitmap 池
39 | int bitmapPoolSizeBytes = 1024 * 1024 * 30; // 30mb
40 | builder.setBitmapPool(new LruBitmapPool(bitmapPoolSizeBytes));
41 | // 磁盘缓存
42 | int diskCacheSizeBytes = 1024 * 1024 * 100; // 100 MB
43 | builder.setDiskCache(new InternalCacheDiskCacheFactory(context, diskCacheSizeBytes));
44 | // 请求选项
45 | builder.setDefaultRequestOptions(
46 | new RequestOptions()
47 | .format(DecodeFormat.PREFER_RGB_565)
48 | .disallowHardwareConfig());
49 | // 日志级别
50 | builder.setLogLevel(Log.ERROR);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/common/glide/OkHttpLibraryGlideModule.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.common.glide;
2 |
3 | import android.content.Context;
4 | import androidx.annotation.NonNull;
5 |
6 | import com.bumptech.glide.Glide;
7 | import com.bumptech.glide.Registry;
8 | import com.bumptech.glide.annotation.GlideModule;
9 | import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader;
10 | import com.bumptech.glide.load.model.GlideUrl;
11 | import com.bumptech.glide.module.LibraryGlideModule;
12 |
13 | import java.io.InputStream;
14 |
15 | import me.cl.lingxi.common.okhttp.OkUtil;
16 |
17 | /**
18 | * @author : happyc
19 | * e-mail : bafs.jy@live.com
20 | * time : 2018/05/31
21 | * desc : 实现LibraryGlideModule
22 | * version: 1.0
23 | */
24 | @GlideModule
25 | public class OkHttpLibraryGlideModule extends LibraryGlideModule {
26 |
27 | @Override
28 | public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
29 | registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(OkUtil.newInstance().getOkHttpClient()));
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/common/okhttp/ResultCallback.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.common.okhttp;
2 |
3 | import com.google.gson.internal.$Gson$Types;
4 |
5 | import java.lang.reflect.ParameterizedType;
6 | import java.lang.reflect.Type;
7 |
8 | import okhttp3.Call;
9 |
10 | public abstract class ResultCallback {
11 |
12 | public abstract void onSuccess(T response);
13 |
14 | public abstract void onError(Call call, Exception e);
15 |
16 | Type getType() {
17 | Type superclass = getClass().getGenericSuperclass();
18 | if (superclass instanceof Class) {
19 | throw new RuntimeException("Missing type parameter.");
20 | }
21 | ParameterizedType parameterize = (ParameterizedType) superclass;
22 | return $Gson$Types.canonicalize(parameterize.getActualTypeArguments()[0]);
23 | }
24 | }
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/common/result/Result.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.common.result;
2 |
3 | /**
4 | * 返回结果
5 | * @param data
6 | */
7 | public class Result {
8 |
9 | private String code;
10 | private String msg;
11 | private T data;
12 |
13 | public String getCode() {
14 | return code;
15 | }
16 |
17 | public void setCode(String code) {
18 | this.code = code;
19 | }
20 |
21 | public String getMsg() {
22 | return msg;
23 | }
24 |
25 | public void setMsg(String msg) {
26 | this.msg = msg;
27 | }
28 |
29 | public T getData() {
30 | return data;
31 | }
32 |
33 | public void setData(T data) {
34 | this.data = data;
35 | }
36 | }
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/common/result/ResultConstant.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.common.result;
2 |
3 | /**
4 | * author : Bafs
5 | * e-mail : bafs.jy@live.com
6 | * time : 2018/07/24
7 | * desc : 结果常量
8 | * version: 1.0
9 | */
10 | public class ResultConstant {
11 |
12 | /**
13 | * 成功code
14 | */
15 | public static final String CODE_SUCCESS = "00000";
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/common/util/DateUtil.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.common.util;
2 |
3 | import java.text.ParseException;
4 | import java.text.SimpleDateFormat;
5 | import java.util.Date;
6 | import java.util.Locale;
7 |
8 | /**
9 | * 时间换算类
10 | */
11 | public class DateUtil {
12 |
13 | /**
14 | * 显示时间,如果与当前时间差别小于一天,则自动用**秒(分,小时)前,
15 | * 如果大于一天则用format规定的格式显示
16 | *
17 | * @param date 时间
18 | * @return 处理得到的时间字符串
19 | */
20 | public static String showTime(String date) {
21 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.SIMPLIFIED_CHINESE);
22 | Date cTime = null;
23 | try {
24 | cTime = sdf.parse(date);
25 | } catch (ParseException e) {
26 | e.printStackTrace();
27 | }
28 | return showTime(cTime);
29 | }
30 |
31 | public static String showTime(Date data) {
32 | if (data == null) return "未知";
33 | long nowTimeLong = System.currentTimeMillis();
34 | long cTimeLong = data.getTime();
35 | long result = Math.abs(nowTimeLong - cTimeLong);
36 |
37 | if (result < 60000) {
38 | long seconds = result / 1000;
39 | if (seconds == 0) {
40 | return "刚刚";
41 | } else {
42 | return seconds + "秒前";
43 | }
44 | }
45 | if (result < 3600000) {
46 | long seconds = result / 60000;
47 | return seconds + "分钟前";
48 | }
49 | if (result < 86400000) {
50 | long seconds = result / 3600000;
51 | return seconds + "小时前";
52 | }
53 | if (result < 1702967296) {
54 | long seconds = result / 86400000;
55 | return seconds + "天前";
56 | }
57 |
58 | // 跨年
59 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy", Locale.SIMPLIFIED_CHINESE);
60 | long nowYearLong = 0;
61 | try {
62 | nowYearLong = sdf.parse(sdf.format(new Date())).getTime();
63 | } catch (ParseException e) {
64 | e.printStackTrace();
65 | }
66 | sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.SIMPLIFIED_CHINESE);
67 | if (nowYearLong < cTimeLong){
68 | sdf = new SimpleDateFormat("MM-dd hh:mm", Locale.SIMPLIFIED_CHINESE);
69 | }
70 | return sdf.format(data);
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/common/util/GsonUtil.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.common.util;
2 |
3 | import com.google.gson.Gson;
4 | import java.lang.reflect.Type;
5 |
6 | import java.util.Arrays;
7 | import java.util.List;
8 |
9 | /**
10 | * Gson工具类
11 | * Created by bafsj on 17/3/31.
12 | */
13 | public class GsonUtil {
14 |
15 | private static Gson gson = new Gson();
16 |
17 | /**
18 | * 解析json
19 | * @param json json字符串
20 | * @param clazz class
21 | * @return 对象
22 | */
23 | public static T toObject(String json, Class clazz) {
24 | return gson.fromJson(json, clazz);
25 | }
26 |
27 | /**
28 | *
29 | * @param json json字符串
30 | * @param type Type
31 | * @return 对象
32 | */
33 | public static T toObject(String json, Type type) {
34 | return gson.fromJson(json, type);
35 | }
36 |
37 | /**
38 | * 解析json数组
39 | * @param json json字符串
40 | * @param clazz 示例 T[].class
41 | * @return 集合
42 | */
43 | public static List toList(String json, Class clazz) {
44 | T[] array = gson.fromJson(json, clazz);
45 | return Arrays.asList(array);
46 | }
47 |
48 | /**
49 | * 将Object转为json
50 | * @param src Object
51 | * @return json字符串
52 | */
53 | public static String toJson(Object src) {
54 | return gson.toJson(src);
55 | }
56 | }
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/common/util/MD5Util.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.common.util;
2 |
3 | import java.security.MessageDigest;
4 |
5 | public class MD5Util {
6 | /**
7 | * 描述:MD5加密.
8 | *
9 | * @param str 要加密的字符串
10 | * @return String 加密的字符串
11 | */
12 | public final static String MD5(String str) {
13 | char hexDigits[] = { // 用来将字节转换成 16 进制表示的字符
14 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
15 | 'e', 'f' };
16 | try {
17 | byte[] strTemp = str.getBytes();
18 | MessageDigest mdTemp = MessageDigest.getInstance("MD5");
19 | mdTemp.update(strTemp);
20 | byte tmp[] = mdTemp.digest(); // MD5 的计算结果是一个 128 位的长整数,
21 | // 用字节表示就是 16 个字节
22 | char strs[] = new char[16 * 2]; // 每个字节用 16 进制表示的话,使用两个字符,
23 | // 所以表示成 16 进制需要 32 个字符
24 | int k = 0; // 表示转换结果中对应的字符位置
25 | for (int i = 0; i < 16; i++) { // 从第一个字节开始,对 MD5 的每一个字节
26 | // 转换成 16 进制字符的转换
27 | byte byte0 = tmp[i]; // 取第 i 个字节
28 | strs[k++] = hexDigits[byte0 >>> 4 & 0xf]; // 取字节中高 4 位的数字转换,
29 | // >>> 为逻辑右移,将符号位一起右移
30 | strs[k++] = hexDigits[byte0 & 0xf]; // 取字节中低 4 位的数字转换
31 | }
32 | return new String(strs).toUpperCase(); // 换后的结果转换为字符串
33 | } catch (Exception e) {
34 | return null;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/common/util/NetworkUtil.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.common.util;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.net.ConnectivityManager;
6 | import android.net.NetworkInfo;
7 | import android.telephony.TelephonyManager;
8 |
9 | /**
10 | * 网络工具
11 | * 需添加权限 {@code }
12 | */
13 | public class NetworkUtil {
14 |
15 | // 打开网络设置
16 | public static void openWirelessSettings(Context context) {
17 | context.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS));
18 | }
19 |
20 | // 获取活动网络信息
21 | private static NetworkInfo getActiveNetworkInfo(Context context) {
22 | ConnectivityManager cm = (ConnectivityManager) context
23 | .getSystemService(Context.CONNECTIVITY_SERVICE);
24 | return cm.getActiveNetworkInfo();
25 | }
26 |
27 | // 判断网络是否可用
28 | public static boolean isAvailable(Context context) {
29 | NetworkInfo info = getActiveNetworkInfo(context);
30 | return info != null && info.isAvailable();
31 | }
32 |
33 | // 判断网络是否连接
34 | public static boolean isConnected(Context context) {
35 | NetworkInfo info = getActiveNetworkInfo(context);
36 | return info != null && info.isConnected();
37 | }
38 |
39 | // 判断网络是否是4G
40 | public static boolean is4G(Context context) {
41 | NetworkInfo info = getActiveNetworkInfo(context);
42 | return info != null && info.isAvailable() && info.getSubtype() == TelephonyManager.NETWORK_TYPE_LTE;
43 | }
44 |
45 | // 判断wifi是否连接状态
46 | public static boolean isWifiConnected(Context context) {
47 | ConnectivityManager cm = (ConnectivityManager) context
48 | .getSystemService(Context.CONNECTIVITY_SERVICE);
49 | return cm != null && cm.getActiveNetworkInfo() != null
50 | && cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI;
51 | }
52 |
53 | // 获取移动网络运营商名称
54 | public static String getNetworkOperatorName(Context context) {
55 | TelephonyManager tm = (TelephonyManager) context
56 | .getSystemService(Context.TELEPHONY_SERVICE);
57 | return tm != null ? tm.getNetworkOperatorName() : null;
58 | }
59 |
60 | }
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/common/widget/AppBarStateChangeListener.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.common.widget;
2 |
3 | import com.google.android.material.appbar.AppBarLayout;
4 |
5 | /**
6 | * @author : happyc
7 | * e-mail : bafs.jy@live.com
8 | * time : 2017/09/17
9 | * desc :
10 | * version : 1.0
11 | */
12 | public abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChangedListener {
13 |
14 | public enum State {
15 | EXPANDED, // 展开状态
16 | COLLAPSED, // 折叠状态
17 | IDLE // 中间状态
18 | }
19 |
20 | private State mCurrentState = State.IDLE;
21 |
22 | @Override
23 | public final void onOffsetChanged(AppBarLayout appBarLayout, int i) {
24 | if (i == 0) {
25 | if (mCurrentState != State.EXPANDED) {
26 | onStateChanged(appBarLayout, State.EXPANDED);
27 | }
28 | mCurrentState = State.EXPANDED;
29 | } else if (Math.abs(i) >= appBarLayout.getTotalScrollRange()) {
30 | if (mCurrentState != State.COLLAPSED) {
31 | onStateChanged(appBarLayout, State.COLLAPSED);
32 | }
33 | mCurrentState = State.COLLAPSED;
34 | } else {
35 | if (mCurrentState != State.IDLE) {
36 | onStateChanged(appBarLayout, State.IDLE);
37 | }
38 | mCurrentState = State.IDLE;
39 | }
40 | }
41 |
42 | public abstract void onStateChanged(AppBarLayout appBarLayout, State state);
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/entity/AppVersion.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.entity;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | * App版本
7 | */
8 | public class AppVersion implements Serializable {
9 |
10 | private String versionName;
11 | private Integer versionCode;
12 | private Integer updateFlag;
13 | private String updateInfo;
14 | private String apkName;
15 | private String apkUrl;
16 |
17 | public String getVersionName() {
18 | return versionName;
19 | }
20 |
21 | public void setVersionName(String versionName) {
22 | this.versionName = versionName;
23 | }
24 |
25 | public Integer getVersionCode() {
26 | return versionCode;
27 | }
28 |
29 | public void setVersionCode(Integer versionCode) {
30 | this.versionCode = versionCode;
31 | }
32 |
33 | public Integer getUpdateFlag() {
34 | return updateFlag;
35 | }
36 |
37 | public void setUpdateFlag(Integer updateFlag) {
38 | this.updateFlag = updateFlag;
39 | }
40 |
41 | public String getUpdateInfo() {
42 | return updateInfo;
43 | }
44 |
45 | public void setUpdateInfo(String updateInfo) {
46 | this.updateInfo = updateInfo;
47 | }
48 |
49 | public String getApkName() {
50 | return apkName;
51 | }
52 |
53 | public void setApkName(String apkName) {
54 | this.apkName = apkName;
55 | }
56 |
57 | public String getApkUrl() {
58 | return apkUrl;
59 | }
60 |
61 | public void setApkUrl(String apkUrl) {
62 | this.apkUrl = apkUrl;
63 | }
64 | }
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/entity/Comment.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.entity;
2 |
3 | import java.io.Serializable;
4 | import java.util.List;
5 |
6 | // 评论
7 | public class Comment implements Serializable {
8 |
9 | private String id;
10 | private String feedId;
11 | private User user;
12 | private User toUser;
13 | private String commentInfo;
14 | private String createTime;
15 | private String updateTime;
16 | private Integer replyNum;
17 | private List replyList;
18 |
19 | public String getId() {
20 | return id;
21 | }
22 |
23 | public void setId(String id) {
24 | this.id = id;
25 | }
26 |
27 | public String getFeedId() {
28 | return feedId;
29 | }
30 |
31 | public void setFeedId(String feedId) {
32 | this.feedId = feedId;
33 | }
34 |
35 | public User getUser() {
36 | return user;
37 | }
38 |
39 | public void setUser(User user) {
40 | this.user = user;
41 | }
42 |
43 | public User getToUser() {
44 | return toUser;
45 | }
46 |
47 | public void setToUser(User toUser) {
48 | this.toUser = toUser;
49 | }
50 |
51 | public String getCommentInfo() {
52 | return commentInfo;
53 | }
54 |
55 | public void setCommentInfo(String commentInfo) {
56 | this.commentInfo = commentInfo;
57 | }
58 |
59 | public String getCreateTime() {
60 | return createTime;
61 | }
62 |
63 | public void setCreateTime(String createTime) {
64 | this.createTime = createTime;
65 | }
66 |
67 | public String getUpdateTime() {
68 | return updateTime;
69 | }
70 |
71 | public void setUpdateTime(String updateTime) {
72 | this.updateTime = updateTime;
73 | }
74 |
75 | public Integer getReplyNum() {
76 | return replyNum;
77 | }
78 |
79 | public void setReplyNum(Integer replyNum) {
80 | this.replyNum = replyNum;
81 | }
82 |
83 | public List getReplyList() {
84 | return replyList;
85 | }
86 |
87 | public void setReplyList(List replyList) {
88 | this.replyList = replyList;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/entity/Future.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.entity;
2 |
3 | import java.io.Serializable;
4 | import java.util.Date;
5 |
6 | /**
7 | * @author : happyc
8 | * e-mail : bafs.jy@live.com
9 | * time : 2020/05/14
10 | * desc : 写给未来
11 | * version: 1.0
12 | */
13 | public class Future implements Serializable {
14 |
15 | private String id;
16 | private String userId;
17 | private String toMail;
18 | private String username;
19 | private String futureInfo;
20 | private Integer days;
21 | private Date createTime;
22 | private Date showTime;
23 |
24 | public String getId() {
25 | return id;
26 | }
27 |
28 | public void setId(String id) {
29 | this.id = id;
30 | }
31 |
32 | public String getUserId() {
33 | return userId;
34 | }
35 |
36 | public void setUserId(String userId) {
37 | this.userId = userId;
38 | }
39 |
40 | public String getToMail() {
41 | return toMail;
42 | }
43 |
44 | public void setToMail(String toMail) {
45 | this.toMail = toMail;
46 | }
47 |
48 | public String getUsername() {
49 | return username;
50 | }
51 |
52 | public void setUsername(String username) {
53 | this.username = username;
54 | }
55 |
56 | public String getFutureInfo() {
57 | return futureInfo;
58 | }
59 |
60 | public void setFutureInfo(String futureInfo) {
61 | this.futureInfo = futureInfo;
62 | }
63 |
64 | public Integer getDays() {
65 | return days;
66 | }
67 |
68 | public void setDays(Integer days) {
69 | this.days = days;
70 | }
71 |
72 | public Date getCreateTime() {
73 | return createTime;
74 | }
75 |
76 | public void setCreateTime(Date createTime) {
77 | this.createTime = createTime;
78 | }
79 |
80 | public Date getShowTime() {
81 | return showTime;
82 | }
83 |
84 | public void setShowTime(Date showTime) {
85 | this.showTime = showTime;
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/entity/Like.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.entity;
2 |
3 | import java.io.Serializable;
4 |
5 | // 点赞
6 | public class Like implements Serializable {
7 |
8 | private String userId;
9 | private String username;
10 |
11 | public String getUserId() {
12 | return userId;
13 | }
14 |
15 | public void setUserId(String userId) {
16 | this.userId = userId;
17 | }
18 |
19 | public String getUsername() {
20 | return username;
21 | }
22 |
23 | public void setUsername(String username) {
24 | this.username = username;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/entity/PageInfo.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.entity;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * author : Bafs
7 | * e-mail : bafs.jy@live.com
8 | * time : 2018/04/22
9 | * desc : 分页信息
10 | * version: 1.0
11 | */
12 | public class PageInfo {
13 |
14 | private Integer pageNum;
15 | private Integer pageSize;
16 | private Integer total;
17 | private List list;
18 | private Integer size;
19 |
20 | public Integer getPageNum() {
21 | return pageNum;
22 | }
23 |
24 | public void setPageNum(Integer pageNum) {
25 | this.pageNum = pageNum;
26 | }
27 |
28 | public Integer getPageSize() {
29 | return pageSize;
30 | }
31 |
32 | public void setPageSize(Integer pageSize) {
33 | this.pageSize = pageSize;
34 | }
35 |
36 | public Integer getTotal() {
37 | return total;
38 | }
39 |
40 | public void setTotal(Integer total) {
41 | this.total = total;
42 | }
43 |
44 | public List getList() {
45 | return list;
46 | }
47 |
48 | public void setList(List list) {
49 | this.list = list;
50 | }
51 |
52 | public Integer getSize() {
53 | return size;
54 | }
55 |
56 | public void setSize(Integer size) {
57 | this.size = size;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/entity/PublicLicense.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.entity;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | * author : Bafs
7 | * e-mail : bafs.jy@live.com
8 | * time : 2017/09/07
9 | * desc : 开源相关
10 | * version: 1.0
11 | */
12 | public class PublicLicense implements Serializable{
13 |
14 | private String name;
15 | private String author;
16 | private String desc;
17 | private String url;
18 |
19 | public PublicLicense(String name, String author, String desc, String url) {
20 | this.name = name;
21 | this.author = author;
22 | this.desc = desc;
23 | this.url = url;
24 | }
25 |
26 | public String getName() {
27 | return name;
28 | }
29 |
30 | public void setName(String name) {
31 | this.name = name;
32 | }
33 |
34 | public String getAuthor() {
35 | return author;
36 | }
37 |
38 | public void setAuthor(String author) {
39 | this.author = author;
40 | }
41 |
42 | public String getDesc() {
43 | return desc;
44 | }
45 |
46 | public void setDesc(String desc) {
47 | this.desc = desc;
48 | }
49 |
50 | public String getUrl() {
51 | return url;
52 | }
53 |
54 | public void setUrl(String url) {
55 | this.url = url;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/entity/Relevant.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.entity;
2 |
3 | import java.io.Serializable;
4 | import java.util.List;
5 |
6 | // 与我相关
7 | public class Relevant implements Serializable {
8 |
9 | private Feed feed;
10 | private Comment comment;
11 | private Integer replyNum;
12 | private List replyList;
13 |
14 | public Comment getComment() {
15 | return comment;
16 | }
17 |
18 | public void setComment(Comment comment) {
19 | this.comment = comment;
20 | }
21 |
22 | public Feed getFeed() {
23 | return feed;
24 | }
25 |
26 | public void setFeed(Feed feed) {
27 | this.feed = feed;
28 | }
29 |
30 | public Integer getReplyNum() {
31 | return replyNum;
32 | }
33 |
34 | public void setReplyNum(Integer replyNum) {
35 | this.replyNum = replyNum;
36 | }
37 |
38 | public List getReplyList() {
39 | return replyList;
40 | }
41 |
42 | public void setReplyList(List replyList) {
43 | this.replyList = replyList;
44 | }
45 | }
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/entity/Reply.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.entity;
2 |
3 | import java.io.Serializable;
4 |
5 | // 回复
6 | public class Reply implements Serializable {
7 |
8 | private String id;
9 | private String feedId;
10 | private String commentId;
11 | private User user;
12 | private User toUser;
13 | private String commentInfo;
14 | private String createTime;
15 | private String updateTime;
16 |
17 | public String getId() {
18 | return id;
19 | }
20 |
21 | public void setId(String id) {
22 | this.id = id;
23 | }
24 |
25 | public String getFeedId() {
26 | return feedId;
27 | }
28 |
29 | public void setFeedId(String feedId) {
30 | this.feedId = feedId;
31 | }
32 |
33 | public String getCommentId() {
34 | return commentId;
35 | }
36 |
37 | public void setCommentId(String commentId) {
38 | this.commentId = commentId;
39 | }
40 |
41 | public User getUser() {
42 | return user;
43 | }
44 |
45 | public void setUser(User user) {
46 | this.user = user;
47 | }
48 |
49 | public User getToUser() {
50 | return toUser;
51 | }
52 |
53 | public void setToUser(User toUser) {
54 | this.toUser = toUser;
55 | }
56 |
57 | public String getCommentInfo() {
58 | return commentInfo;
59 | }
60 |
61 | public void setCommentInfo(String commentInfo) {
62 | this.commentInfo = commentInfo;
63 | }
64 |
65 | public String getCreateTime() {
66 | return createTime;
67 | }
68 |
69 | public void setCreateTime(String createTime) {
70 | this.createTime = createTime;
71 | }
72 |
73 | public String getUpdateTime() {
74 | return updateTime;
75 | }
76 |
77 | public void setUpdateTime(String updateTime) {
78 | this.updateTime = updateTime;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/entity/Topic.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.entity;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | * @author : happyc
7 | * time : 2020/11/09
8 | * desc :
9 | * version : 1.0
10 | */
11 | public class Topic implements Serializable {
12 |
13 | private String id;
14 | private String topicName;
15 | private String avatar;
16 | private boolean selected;
17 |
18 | public String getId() {
19 | return id;
20 | }
21 |
22 | public void setId(String id) {
23 | this.id = id;
24 | }
25 |
26 | public String getTopicName() {
27 | return topicName;
28 | }
29 |
30 | public void setTopicName(String topicName) {
31 | this.topicName = topicName;
32 | }
33 |
34 | public String getAvatar() {
35 | return avatar;
36 | }
37 |
38 | public void setAvatar(String avatar) {
39 | this.avatar = avatar;
40 | }
41 |
42 | public boolean isSelected() {
43 | return selected;
44 | }
45 |
46 | public void setSelected(boolean selected) {
47 | this.selected = selected;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/entity/User.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.entity;
2 |
3 | import java.io.Serializable;
4 |
5 | // 用户
6 | public class User implements Serializable {
7 |
8 | private String id;
9 | private String username;
10 | private String avatar;
11 | private String imToken;
12 |
13 | public String getId() {
14 | return id;
15 | }
16 |
17 | public void setId(String id) {
18 | this.id = id;
19 | }
20 |
21 | public String getUsername() {
22 | return username;
23 | }
24 |
25 | public void setUsername(String username) {
26 | this.username = username;
27 | }
28 |
29 | public String getAvatar() {
30 | return avatar;
31 | }
32 |
33 | public void setAvatar(String avatar) {
34 | this.avatar = avatar;
35 | }
36 |
37 | public String getImToken() {
38 | return imToken;
39 | }
40 |
41 | public void setImToken(String imToken) {
42 | this.imToken = imToken;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/entity/UserToken.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.entity;
2 |
3 | /**
4 | * @author Bafs
5 | * 用户token
6 | */
7 | public class UserToken {
8 |
9 | private String id;
10 | private String username;
11 | private String token;
12 |
13 | public String getId() {
14 | return id;
15 | }
16 |
17 | public void setId(String id) {
18 | this.id = id;
19 | }
20 |
21 | public String getUsername() {
22 | return username;
23 | }
24 |
25 | public void setUsername(String username) {
26 | this.username = username;
27 | }
28 |
29 | public String getToken() {
30 | return token;
31 | }
32 |
33 | public void setToken(String token) {
34 | this.token = token;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/module/LxApplication.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.module;
2 |
3 | import android.app.Application;
4 |
5 | import java.util.HashMap;
6 | import java.util.Map;
7 |
8 | import me.cl.lingxi.common.config.Api;
9 | import me.cl.lingxi.common.okhttp.OkUtil;
10 | import me.cl.lingxi.common.util.SPUtil;
11 |
12 | public class LxApplication extends Application {
13 |
14 | @Override
15 | public void onCreate() {
16 | super.onCreate();
17 |
18 | // 一定要注册
19 | SPUtil.newInstance().init(this);
20 | // 根据需求使用
21 | initOkUtil();
22 | }
23 |
24 | /**
25 | * 初始化OkUtil
26 | */
27 | private void initOkUtil() {
28 | // 公共请求头
29 | Map headers = new HashMap<>(1);
30 | String token = SPUtil.build().getString(Api.X_APP_TOKEN);
31 | headers.put(Api.X_APP_TOKEN, token);
32 | // 注册添加公共请求头
33 | OkUtil.newInstance().init(this)
34 | .addCommonHeaders(headers);
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/module/main/MessageFragment.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.module.main;
2 |
3 | import android.os.Bundle;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 |
8 | import androidx.annotation.NonNull;
9 | import androidx.fragment.app.Fragment;
10 |
11 | import me.cl.lingxi.adapter.ViewPagerAdapter;
12 | import me.cl.lingxi.databinding.MessageFragmentBinding;
13 |
14 | public class MessageFragment extends Fragment{
15 |
16 | private MessageFragmentBinding mBinding;
17 |
18 | private final String[] tabNamArray = {"未来日记", "飞鸽传书"};
19 |
20 | @Override
21 | public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
22 | mBinding = MessageFragmentBinding.inflate(inflater, container, false);
23 | init();
24 | return mBinding.getRoot();
25 | }
26 |
27 |
28 | private void init() {
29 | final ViewPagerAdapter mPagerAdapter = new ViewPagerAdapter(getChildFragmentManager());
30 | addFragment(mPagerAdapter);
31 | mBinding.viewPager.post(() -> {
32 | mBinding.viewPager.setAdapter(mPagerAdapter);
33 | mBinding.includeTab.tabLayout.setupWithViewPager(mBinding.viewPager);
34 | });
35 | }
36 |
37 | private void addFragment(ViewPagerAdapter mPagerAdapter) {
38 | FutureFragment futureFragment = FutureFragment.newInstance("new");
39 | MessageChildFragment newsFragment = MessageChildFragment.newInstance("飞鸽传书功能准备当中\n" +
40 | "有好的建议可点击下方按钮↓");
41 | mPagerAdapter.addFragment(futureFragment, tabNamArray[0]);
42 | mPagerAdapter.addFragment(newsFragment, tabNamArray[1]);
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/module/setting/SettingsActivity.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.module.setting;
2 |
3 | import android.os.Bundle;
4 | import android.preference.Preference;
5 | import android.preference.PreferenceFragment;
6 |
7 | import me.cl.library.base.BaseActivity;
8 | import me.cl.library.util.ToolbarUtil;
9 | import me.cl.lingxi.R;
10 | import me.cl.lingxi.common.util.SPUtil;
11 | import me.cl.lingxi.databinding.SettingsActivityBinding;
12 |
13 | /**
14 | * 设置
15 | * https://github.com/shellhub/blog/issues/29
16 | */
17 | public class SettingsActivity extends BaseActivity {
18 |
19 | private SettingsActivityBinding mBinding;
20 |
21 | @Override
22 | protected void onCreate(Bundle savedInstanceState) {
23 | super.onCreate(savedInstanceState);
24 | mBinding = SettingsActivityBinding.inflate(getLayoutInflater());
25 | setContentView(mBinding.getRoot());
26 | init();
27 | }
28 |
29 | private void init() {
30 | ToolbarUtil.init(mBinding.includeTb.toolbar, this)
31 | .setTitle(R.string.action_settings)
32 | .setBack()
33 | .setTitleCenter(R.style.AppTheme_Toolbar_TextAppearance)
34 | .build();
35 |
36 | getFragmentManager()
37 | .beginTransaction()
38 | .replace(R.id.fragment_container, new SettingsFragment())
39 | .commit();
40 | }
41 |
42 | public static class SettingsFragment extends PreferenceFragment {
43 |
44 | private static final String OPEN_TU_PICS = "open_tu_pics";
45 |
46 | @Override
47 | public void onCreate(Bundle savedInstanceState) {
48 | super.onCreate(savedInstanceState);
49 | addPreferencesFromResource(R.xml.preference_setting);
50 | initPreferences();
51 | }
52 |
53 | private void initPreferences() {
54 | Preference openTuPics = findPreference(OPEN_TU_PICS);
55 | openTuPics.setOnPreferenceChangeListener((preference, newValue) -> {
56 | SPUtil.build().putBoolean(OPEN_TU_PICS, (Boolean) newValue);
57 | return true;
58 | });
59 | }
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/view/textview/ClickableImageSpan.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.view.textview;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 | import android.graphics.drawable.Drawable;
6 | import android.text.style.ImageSpan;
7 | import android.view.View;
8 | /**
9 | * author : Bafs
10 | * e-mail : bafs.jy@live.com
11 | * time : 2018/05/27
12 | * desc : 可点击ImageSpan
13 | * version: 1.0
14 | */
15 | public abstract class ClickableImageSpan extends ImageSpan {
16 |
17 | public ClickableImageSpan(Drawable b, int verticalAlignment) {
18 | super(b, verticalAlignment);
19 | }
20 |
21 | public abstract void onClick(View view);
22 |
23 | @Override
24 | public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
25 | Drawable b = getDrawable();
26 | canvas.save();
27 | int transY = bottom - b.getBounds().bottom;
28 | transY -= paint.getFontMetricsInt().descent / 2;
29 | canvas.translate(x, transY);
30 | b.draw(canvas);
31 | canvas.restore();
32 | }
33 | }
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/view/textview/NoLineClickableSpan.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.view.textview;
2 |
3 | import android.content.Context;
4 | import android.text.TextPaint;
5 | import android.text.style.ClickableSpan;
6 | import android.view.View;
7 |
8 | import me.cl.lingxi.R;
9 |
10 | /**
11 | * author : Bafs
12 | * e-mail : bafs.jy@live.com
13 | * time : 2018/05/27
14 | * desc : ClickableSpan去下划线
15 | * version: 1.0
16 | */
17 | public class NoLineClickableSpan extends ClickableSpan {
18 |
19 | private Context mContext;
20 |
21 | public NoLineClickableSpan(Context context) {
22 | mContext = context;
23 | }
24 |
25 | @Override
26 | public void onClick(View widget) {
27 | }
28 |
29 | @Override
30 | public void updateDrawState(TextPaint ds) {
31 | super.updateDrawState(ds);
32 | // 文本颜色
33 | ds.setColor(mContext.getResources().getColor(R.color.blue));
34 | // 去掉超链接下划线
35 | ds.setUnderlineText(false);
36 | }
37 | }
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/view/webview/MoeChromeClient.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.view.webview;
2 |
3 | import android.media.MediaPlayer;
4 | import android.view.View;
5 | import android.webkit.WebChromeClient;
6 | import android.widget.FrameLayout;
7 |
8 | /**
9 | * author : Bafs
10 | * e-mail : bafs.jy@live.com
11 | * time : 2018/05/13
12 | * desc : ChromeClient
13 | * version: 1.0
14 | */
15 | public class MoeChromeClient extends WebChromeClient implements MediaPlayer.OnCompletionListener {
16 |
17 | private static final String TAG = "MoeChromeClient";
18 |
19 | private FrameLayout mVideoView;
20 | private View mCustomView;
21 | private CustomViewCallback mCallback;
22 |
23 | private onChangedListener mOnChangedListener;
24 |
25 | public interface onChangedListener {
26 | void onFullscreen(boolean fullscreen);
27 | }
28 |
29 | public View getCustomView() {
30 | return mCustomView;
31 | }
32 |
33 | public MoeChromeClient(FrameLayout videoView, onChangedListener listener) {
34 | this.mVideoView = videoView;
35 | this.mOnChangedListener = listener;
36 | }
37 |
38 | @Override
39 | public void onCompletion(MediaPlayer mp) {
40 | if (mp != null) {
41 | if (mp.isPlaying()) {
42 | mp.stop();
43 | }
44 | mp.reset();
45 | mp.release();
46 | }
47 | }
48 |
49 | // 播放网络视频时全屏会被调用的方法
50 | @Override
51 | public void onShowCustomView(View view, CustomViewCallback callback) {
52 | if (mCustomView != null) {
53 | callback.onCustomViewHidden();
54 | return;
55 | }
56 | if (mOnChangedListener != null) {
57 | mOnChangedListener.onFullscreen(true);
58 | }
59 | mCustomView = view;
60 | mVideoView.addView(view);
61 | mVideoView.setVisibility(View.VISIBLE);
62 | mCallback = callback;
63 | }
64 |
65 | // 视频播放退出全屏会被调用的
66 | @Override
67 | public void onHideCustomView() {
68 | if (mCustomView == null) {
69 | return;
70 | }
71 | if (mOnChangedListener != null) {
72 | mOnChangedListener.onFullscreen(false);
73 | }
74 | mCustomView.setVisibility(View.GONE);
75 | mVideoView.removeView(mCustomView);
76 | mCustomView = null;
77 | mVideoView.setVisibility(View.GONE);
78 | mCallback.onCustomViewHidden();
79 | }
80 | }
--------------------------------------------------------------------------------
/app/src/main/java/me/cl/lingxi/viewmodel/TopicViewModel.java:
--------------------------------------------------------------------------------
1 | package me.cl.lingxi.viewmodel;
2 |
3 | import androidx.lifecycle.MutableLiveData;
4 | import androidx.lifecycle.ViewModel;
5 |
6 | import me.cl.lingxi.R;
7 | import me.cl.lingxi.common.config.Api;
8 | import me.cl.library.model.TipMessage;
9 | import me.cl.lingxi.common.okhttp.OkUtil;
10 | import me.cl.lingxi.common.okhttp.ResultCallback;
11 | import me.cl.lingxi.common.result.Result;
12 | import me.cl.lingxi.common.result.ResultConstant;
13 | import me.cl.lingxi.entity.PageInfo;
14 | import me.cl.lingxi.entity.Topic;
15 | import okhttp3.Call;
16 |
17 | /**
18 | * @author : happyc
19 | * time : 2021/05/10
20 | * desc :
21 | * version : 1.0
22 | */
23 | public class TopicViewModel extends ViewModel {
24 |
25 | public final MutableLiveData mTipMessage;
26 | public final MutableLiveData> mTopics;
27 |
28 | public TopicViewModel() {
29 | mTipMessage = new MutableLiveData<>();
30 | mTopics = new MutableLiveData<>();
31 | }
32 |
33 | /**
34 | * 查询话题
35 | * @param queryName 搜索话题
36 | * @param pageNum 页码
37 | * @param pageSize 页容量
38 | */
39 | public void queryTopic(String queryName, int pageNum, int pageSize) {
40 | OkUtil.post()
41 | .url(Api.queryTopic)
42 | .addParam("name", queryName)
43 | .addParam("pageNum", pageNum)
44 | .addParam("pageSize", pageSize)
45 | .execute(new ResultCallback>>() {
46 | @Override
47 | public void onSuccess(Result> response) {
48 | String code = response.getCode();
49 | if (ResultConstant.CODE_SUCCESS.equals(code)) {
50 | mTopics.postValue(response.getData());
51 | } else {
52 | mTipMessage.postValue(TipMessage.resId(R.string.toast_get_topic_error));
53 | }
54 | }
55 |
56 | @Override
57 | public void onError(Call call, Exception e) {
58 | mTipMessage.postValue(TipMessage.resId(R.string.toast_get_topic_error));
59 | }
60 | });
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/app/src/main/res/color/bottom_navigation_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/color/future_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/color/inc_episode_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/color/selector_text.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_publish_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 | -
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/future_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | -
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/home_card_shape.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_accessory.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_browse.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_camera.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_camera_add.xml:
--------------------------------------------------------------------------------
1 |
7 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_camera_fill.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_camera_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_comment.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_delete.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_delete_fill.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_eit.xml:
--------------------------------------------------------------------------------
1 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_favorite.xml:
--------------------------------------------------------------------------------
1 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_home.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_homepage.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_homepage_fill.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_homepage_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_interactive.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_interactive_fill.xml:
--------------------------------------------------------------------------------
1 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_interactive_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_like.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_like_fill.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_like_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_message.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_mine.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_mine_fill.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_mine_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_more.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_more_badge.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_ok.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_password.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_people.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_photo.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_postbox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/app/src/main/res/drawable/ic_postbox.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_search.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_search_t.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_send.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_setup.xml:
--------------------------------------------------------------------------------
1 |
7 |
11 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_skip.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_topic.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_user.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/img_future_bg.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/app/src/main/res/drawable/img_future_bg.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/img_lingxi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/app/src/main/res/drawable/img_lingxi.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/img_login.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/app/src/main/res/drawable/img_login.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/img_miaozi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/app/src/main/res/drawable/img_miaozi.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/img_mine_bc.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/app/src/main/res/drawable/img_mine_bc.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/img_user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/app/src/main/res/drawable/img_user.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/inc_episode_selector.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 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/more_entry_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/nav_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
8 |
9 |
10 |
14 |
15 |
18 |
19 |
20 |
21 |
22 | -
26 |
27 |
31 |
32 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/nav_item_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/nav_item_bg_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/shape_badge.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/shape_edit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/shape_search.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/edit_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/feed_detail_recycle_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
21 |
22 |
25 |
26 |
34 |
35 |
38 |
39 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/feed_fragment.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
12 |
13 |
17 |
18 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/feed_info_include.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
16 |
17 |
25 |
26 |
34 |
35 |
43 |
44 |
45 |
55 |
56 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/feed_like_include.xml:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
21 |
22 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/feed_reply_recycle_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/future_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
13 |
14 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/future_fragment.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
16 |
17 |
21 |
22 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/future_recycle_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
16 |
17 |
24 |
25 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/include_recycler_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/include_tab_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/include_toolbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/main_menu_badge.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/message_child_fragment.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
16 |
17 |
23 |
24 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/message_fragment.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
15 |
16 |
17 |
18 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/mian_activity.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
14 |
15 |
20 |
21 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/mine_logout_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
27 |
28 |
32 |
33 |
37 |
38 |
46 |
47 |
51 |
52 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/public_license_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
13 |
14 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/public_license_recycle_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
22 |
23 |
30 |
31 |
32 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/publish_photo_recycle_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
17 |
18 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/relevant_activity.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
11 |
12 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/search_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/settings_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
12 |
13 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/splash_activity.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
15 |
16 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/topic_eit_recycle_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
18 |
27 |
28 |
32 |
33 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/web_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
17 |
18 |
22 |
23 |
24 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/future_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/navigation_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/publish_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/search_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/search_view_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/send_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/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/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-nodpi/ic_launcher_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/app/src/main/res/mipmap-nodpi/ic_launcher_background.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | @color/grey
6 | @color/white
7 | @color/grapefruit
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v23/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | @color/white
6 | @color/white
7 | @color/grapefruit
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 | 120dp
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | @color/white
6 | @color/white
7 | @color/grapefruit
8 | @color/textColorBasic
9 |
10 | #333333
11 | #666666
12 | #7f7f7f
13 |
14 | #EAECEE
15 | #e6e6e6
16 | #E0E0E0
17 | #ffffff
18 |
19 | #ffffff
20 | #000000
21 | #212121
22 | #00ffffff
23 | #4fc1e9
24 | #25c6fc
25 | #646464
26 | #cccccc
27 | #ffdbe4e7
28 | #ED5565
29 | #fffcf7
30 | #ffeeeeee
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 16dp
6 |
7 |
8 | 3dp
9 | 4dp
10 | 6dp
11 | 8dp
12 | 10dp
13 | 12dp
14 | 14dp
15 | 16dp
16 | 20dp
17 | 24dp
18 | 28dp
19 | 32dp
20 | 36dp
21 | 40dp
22 | 44dp
23 | 48dp
24 | 52dp
25 | 56dp
26 | 60dp
27 | 68dp
28 | 200dp
29 |
30 |
31 | 12dp
32 | 13dp
33 | 14dp
34 | 15dp
35 | 16dp
36 | 17dp
37 | 18dp
38 |
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/network_security_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/preference_setting.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/provider_paths.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
9 |
12 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | maven { url 'https://maven.aliyun.com/repository/public/' }
4 | maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
5 | maven { url "https://jitpack.io" }
6 | google()
7 | mavenCentral()
8 | }
9 | dependencies {
10 | // https://developer.android.google.cn/studio/releases/gradle-plugin?hl=zh-cn
11 | // https://developer.android.google.cn/reference/tools/gradle-api
12 | classpath 'com.android.tools.build:gradle:7.4.2'
13 | }
14 | }
15 |
16 | allprojects {
17 | repositories {
18 | maven { url 'https://maven.aliyun.com/repository/public/' }
19 | maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
20 | maven { url "https://jitpack.io" }
21 | google()
22 | mavenCentral()
23 | }
24 | }
25 |
26 | tasks.register('clean', Delete) {
27 | delete rootProject.buildDir
28 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 | android.enableJetifier=true
20 | android.useAndroidX=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Nov 25 11:34:50 CST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https://mirrors.cloud.tencent.com/gradle/gradle-7.5.1-bin.zip
7 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/library/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 |
5 | compileSdkVersion libs.versions.compileSdk.get()
6 |
7 | defaultConfig {
8 | minSdkVersion libs.versions.minSdk.get()
9 | targetSdkVersion libs.versions.targetSdk.get()
10 | versionCode 1
11 | versionName "1.0"
12 |
13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
14 | }
15 |
16 | buildTypes {
17 | release {
18 | minifyEnabled false
19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
20 | }
21 | }
22 | }
23 |
24 | dependencies {
25 | api fileTree(dir: 'libs', include: ['*.jar'])
26 | api libs.android.material
27 | api libs.androidx.appcompat
28 | api libs.androidx.recyclerview
29 | api libs.glide
30 | }
31 |
--------------------------------------------------------------------------------
/library/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/library/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/library/src/main/java/com/bm/library/Info.java:
--------------------------------------------------------------------------------
1 | package com.bm.library;
2 |
3 | import android.graphics.PointF;
4 | import android.graphics.RectF;
5 | import android.widget.ImageView;
6 |
7 | /**
8 | * Created by liuheng on 2015/8/19.
9 | */
10 | public class Info {
11 |
12 | // 内部图片在整个手机界面的位置
13 | RectF mRect = new RectF();
14 |
15 | // 控件在窗口的位置
16 | RectF mImgRect = new RectF();
17 |
18 | RectF mWidgetRect = new RectF();
19 |
20 | RectF mBaseRect = new RectF();
21 |
22 | PointF mScreenCenter = new PointF();
23 |
24 | float mScale;
25 |
26 | float mDegrees;
27 |
28 | ImageView.ScaleType mScaleType;
29 |
30 | public Info(RectF rect, RectF img, RectF widget, RectF base, PointF screenCenter, float scale, float degrees, ImageView.ScaleType scaleType) {
31 | mRect.set(rect);
32 | mImgRect.set(img);
33 | mWidgetRect.set(widget);
34 | mScale = scale;
35 | mScaleType = scaleType;
36 | mDegrees = degrees;
37 | mBaseRect.set(base);
38 | mScreenCenter.set(screenCenter);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/library/src/main/java/com/bm/library/RotateGestureDetector.java:
--------------------------------------------------------------------------------
1 | package com.bm.library;
2 |
3 | import android.view.MotionEvent;
4 |
5 | /**
6 | * Created by q2366 on 2015/10/12.
7 | */
8 | public class RotateGestureDetector {
9 |
10 | private static final int MAX_DEGREES_STEP = 120;
11 |
12 | private OnRotateListener mListener;
13 |
14 | private float mPrevSlope;
15 | private float mCurrSlope;
16 |
17 | private float x1;
18 | private float y1;
19 | private float x2;
20 | private float y2;
21 |
22 | public RotateGestureDetector(OnRotateListener l) {
23 | mListener = l;
24 | }
25 |
26 | public void onTouchEvent(MotionEvent event) {
27 |
28 | final int Action = event.getActionMasked();
29 |
30 | switch (Action) {
31 | case MotionEvent.ACTION_POINTER_DOWN:
32 | case MotionEvent.ACTION_POINTER_UP:
33 | if (event.getPointerCount() == 2) mPrevSlope = caculateSlope(event);
34 | break;
35 | case MotionEvent.ACTION_MOVE:
36 | if (event.getPointerCount() > 1) {
37 | mCurrSlope = caculateSlope(event);
38 |
39 | double currDegrees = Math.toDegrees(Math.atan(mCurrSlope));
40 | double prevDegrees = Math.toDegrees(Math.atan(mPrevSlope));
41 |
42 | double deltaSlope = currDegrees - prevDegrees;
43 |
44 | if (Math.abs(deltaSlope) <= MAX_DEGREES_STEP) {
45 | mListener.onRotate((float) deltaSlope, (x2 + x1) / 2, (y2 + y1) / 2);
46 | }
47 | mPrevSlope = mCurrSlope;
48 | }
49 | break;
50 | default:
51 | break;
52 | }
53 | }
54 |
55 | private float caculateSlope(MotionEvent event) {
56 | x1 = event.getX(0);
57 | y1 = event.getY(0);
58 | x2 = event.getX(1);
59 | y2 = event.getY(1);
60 | return (y2 - y1) / (x2 - x1);
61 | }
62 | }
63 |
64 | interface OnRotateListener {
65 | void onRotate(float degrees, float focusX, float focusY);
66 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/library/flowlayout/SpaceItemDecoration.java:
--------------------------------------------------------------------------------
1 | package com.library.flowlayout;
2 |
3 | import android.graphics.Rect;
4 | import android.view.View;
5 |
6 | import androidx.annotation.NonNull;
7 | import androidx.recyclerview.widget.RecyclerView;
8 |
9 | /**
10 | * Created by xiangcheng on 17/8/22.
11 | */
12 | public class SpaceItemDecoration extends RecyclerView.ItemDecoration {
13 |
14 | private int space;
15 |
16 | public SpaceItemDecoration(int space) {
17 | this.space = space;
18 | }
19 |
20 | @Override
21 | public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
22 | outRect.top = space;
23 | outRect.left = space;
24 | outRect.right = space;
25 | outRect.bottom = space;
26 | }
27 | }
--------------------------------------------------------------------------------
/library/src/main/java/me/cl/library/base/BaseFragment.java:
--------------------------------------------------------------------------------
1 | package me.cl.library.base;
2 |
3 | import androidx.annotation.StringRes;
4 | import androidx.fragment.app.Fragment;
5 |
6 | import me.cl.library.util.ToastUtil;
7 | import me.cl.library.view.MoeToast;
8 |
9 | public class BaseFragment extends Fragment {
10 |
11 | public void showToast(@StringRes int msgId) {
12 | ToastUtil.showToast(getContext(), msgId);
13 | }
14 |
15 | public void showToast(String msg) {
16 | ToastUtil.showToast(getContext(), msg);
17 | }
18 |
19 | public void showMoeToast(@StringRes int msgId) {
20 | MoeToast.makeText(getContext(), msgId);
21 | }
22 |
23 | public void showMoeToast(String msg) {
24 | MoeToast.makeText(getContext(), msg);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/library/src/main/java/me/cl/library/loadmore/LoadMord.java:
--------------------------------------------------------------------------------
1 | package me.cl.library.loadmore;
2 |
3 | /**
4 | * author : Bafs
5 | * e-mail : bafs.jy@live.com
6 | * time : 2018/04/21
7 | * desc : 加载更多模式
8 | * version: 1.0
9 | */
10 | public class LoadMord {
11 |
12 | /** 正在加载 */
13 | public static final int LOAD_MORE = 0;
14 | /** 上拉加载 */
15 | public static final int LOAD_PULL_TO = 1;
16 | /** 没有更多 */
17 | public static final int LOAD_NONE = 2;
18 | /** 加载完成 */
19 | public static final int LOAD_END = 3;
20 | }
21 |
--------------------------------------------------------------------------------
/library/src/main/java/me/cl/library/loadmore/LoadMoreAdapter.java:
--------------------------------------------------------------------------------
1 | package me.cl.library.loadmore;
2 |
3 | import android.view.View;
4 | import android.view.ViewGroup;
5 |
6 | import androidx.annotation.NonNull;
7 | import androidx.recyclerview.widget.RecyclerView;
8 |
9 | import me.cl.library.R;
10 |
11 | /**
12 | * @author : happyc
13 | * time : 2021/05/09
14 | * desc :
15 | * version : 1.0
16 | */
17 | public class LoadMoreAdapter extends RecyclerView.Adapter {
18 |
19 | private int status = LoadMord.LOAD_END;
20 |
21 | @NonNull
22 | @Override
23 | public LoadMoreViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
24 | View view = View.inflate(parent.getContext(), R.layout.lib_load_more, null);
25 | return new LoadMoreViewHolder(view);
26 | }
27 |
28 | @Override
29 | public void onBindViewHolder(@NonNull LoadMoreViewHolder holder, int position) {
30 | holder.bindItem(status);
31 | }
32 |
33 | @Override
34 | public int getItemCount() {
35 | return 1;
36 | }
37 |
38 | public void pullTo() {
39 | status = LoadMord.LOAD_PULL_TO;
40 | notifyDataSetChanged();
41 | }
42 |
43 | public void loading() {
44 | status = LoadMord.LOAD_MORE;
45 | notifyDataSetChanged();
46 | }
47 |
48 | public void loadNone() {
49 | status = LoadMord.LOAD_NONE;
50 | notifyDataSetChanged();
51 | }
52 |
53 | public void loadEnd() {
54 | status = LoadMord.LOAD_END;
55 | notifyDataSetChanged();
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/library/src/main/java/me/cl/library/loadmore/LoadMoreViewHolder.java:
--------------------------------------------------------------------------------
1 | package me.cl.library.loadmore;
2 |
3 | import android.view.View;
4 | import android.view.ViewGroup;
5 | import android.widget.ProgressBar;
6 | import android.widget.TextView;
7 |
8 | import androidx.appcompat.widget.LinearLayoutCompat;
9 | import androidx.recyclerview.widget.RecyclerView;
10 |
11 | import me.cl.library.R;
12 |
13 |
14 | /**
15 | * author : Bafs
16 | * e-mail : bafs.jy@live.com
17 | * time : 2018/04/21
18 | * desc : 加载更多ViewHolder
19 | * version: 1.0
20 | */
21 | public class LoadMoreViewHolder extends RecyclerView.ViewHolder {
22 |
23 | private ProgressBar mProgress;
24 | private TextView mLoadPrompt;
25 |
26 | public LoadMoreViewHolder(View itemView) {
27 | super(itemView);
28 | initView(itemView);
29 | }
30 |
31 | private void initView(View itemView) {
32 | mProgress = itemView.findViewById(R.id.lib_progress);
33 | mLoadPrompt = itemView.findViewById(R.id.lib_load_prompt);
34 |
35 | LinearLayoutCompat.LayoutParams params = new LinearLayoutCompat.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
36 | itemView.setLayoutParams(params);
37 | itemView.setVisibility(View.GONE);
38 | }
39 |
40 | public void bindItem(int status) {
41 | switch (status) {
42 | case LoadMord.LOAD_MORE:
43 | mProgress.setVisibility(View.VISIBLE);
44 | mLoadPrompt.setText(R.string.lib_load_more);
45 | itemView.setVisibility(View.VISIBLE);
46 | break;
47 | case LoadMord.LOAD_PULL_TO:
48 | mProgress.setVisibility(View.GONE);
49 | mLoadPrompt.setText(R.string.lib_load_pull_to);
50 | itemView.setVisibility(View.VISIBLE);
51 | break;
52 | case LoadMord.LOAD_NONE:
53 | mProgress.setVisibility(View.GONE);
54 | mLoadPrompt.setText(R.string.lib_load_none);
55 | break;
56 | case LoadMord.LOAD_END:
57 | default:
58 | itemView.setVisibility(View.INVISIBLE);
59 | break;
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/library/src/main/java/me/cl/library/loadmore/OnLoadMoreListener.java:
--------------------------------------------------------------------------------
1 | package me.cl.library.loadmore;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.recyclerview.widget.LinearLayoutManager;
5 | import androidx.recyclerview.widget.RecyclerView;
6 | import androidx.recyclerview.widget.StaggeredGridLayoutManager;
7 |
8 | /**
9 | * RecyclerView加载更多
10 | * Created by Bafsj on 2016/12/20.
11 | */
12 |
13 | public abstract class OnLoadMoreListener extends RecyclerView.OnScrollListener {
14 |
15 | private int itemCount, lastPosition;
16 |
17 | public abstract void onLoadMore();
18 |
19 | @Override
20 | public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
21 | RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
22 | if (layoutManager instanceof LinearLayoutManager) {
23 | LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
24 | itemCount = linearLayoutManager.getItemCount();
25 | lastPosition = linearLayoutManager.findLastCompletelyVisibleItemPosition();
26 | } else if (layoutManager instanceof StaggeredGridLayoutManager) {
27 | StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager;
28 | itemCount = staggeredGridLayoutManager.getItemCount();
29 | int spanCount = staggeredGridLayoutManager.getSpanCount();
30 | int[] itemPositions = staggeredGridLayoutManager.findLastCompletelyVisibleItemPositions(new int[spanCount]);
31 | lastPosition = findLast(itemPositions);
32 | }
33 | }
34 |
35 | @Override
36 | public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
37 | super.onScrollStateChanged(recyclerView, newState);
38 | // 判断RecyclerView的状态是空闲时,同时,是最后一个可见的ITEM时才加载
39 | if (newState == RecyclerView.SCROLL_STATE_IDLE && lastPosition == itemCount - 1) {
40 | this.onLoadMore();
41 | }
42 | }
43 |
44 | /**
45 | * 找到最后一个item
46 | */
47 | private int findLast(int[] items) {
48 | int last = items[0];
49 | for (int item : items) {
50 | if (item > last) {
51 | last = item;
52 | }
53 | }
54 | return last;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/library/src/main/java/me/cl/library/model/TipMessage.java:
--------------------------------------------------------------------------------
1 | package me.cl.library.model;
2 |
3 | import androidx.annotation.StringRes;
4 |
5 | /**
6 | * @author : happyc
7 | * time : 2021/05/10
8 | * desc :
9 | * version : 1.0
10 | */
11 | public class TipMessage {
12 |
13 | private int msgId;
14 | private String msgStr;
15 | private boolean res;
16 |
17 | public TipMessage() {
18 | }
19 |
20 | public TipMessage(int msgId) {
21 | this.msgId = msgId;
22 | this.res = true;
23 | }
24 |
25 | public TipMessage(String msgStr) {
26 | this.msgStr = msgStr;
27 | this.res = false;
28 | }
29 |
30 | public int getMsgId() {
31 | return msgId;
32 | }
33 |
34 | public void setMsgId(int msgId) {
35 | this.msgId = msgId;
36 | }
37 |
38 | public String getMsgStr() {
39 | return msgStr;
40 | }
41 |
42 | public void setMsgStr(String msgStr) {
43 | this.msgStr = msgStr;
44 | }
45 |
46 | public boolean isRes() {
47 | return res;
48 | }
49 |
50 | public void setRes(boolean res) {
51 | this.res = res;
52 | }
53 |
54 | public static TipMessage resId(@StringRes int msgId) {
55 | return new TipMessage(msgId);
56 | }
57 |
58 | public static TipMessage str(String msgStr) {
59 | return new TipMessage(msgStr);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/library/src/main/java/me/cl/library/photo/PhotoBrowser.java:
--------------------------------------------------------------------------------
1 | package me.cl.library.photo;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import androidx.annotation.NonNull;
8 |
9 | import java.util.ArrayList;
10 |
11 | /**
12 | * author : happyc
13 | * e-mail : bafs.jy@live.com
14 | * time : 2019/04/26
15 | * desc :
16 | * version: 1.0
17 | */
18 | public class PhotoBrowser {
19 |
20 | public static final int REQUEST_CODE = 666;
21 | public static final String EXTRA_CURRENT_ITEM = "current_item";
22 | public static final String EXTRA_PHOTOS = "photos";
23 | public static final String EXTRA_DOWNLOAD_PATH = "download_path";
24 |
25 | public PhotoBrowser() {
26 |
27 | }
28 |
29 | public static PhotoBrowser.Builder builder() {
30 | return new PhotoBrowser.Builder();
31 | }
32 |
33 | public static class Builder {
34 |
35 | private Bundle mBrowserOptionsBundle = new Bundle();
36 | private Intent mBrowserIntent = new Intent();
37 |
38 | public Builder() {
39 |
40 | }
41 |
42 | public void start(@NonNull Activity activity) {
43 | activity.startActivity(this.getIntent(activity));
44 | }
45 |
46 | private Intent getIntent(@NonNull Context context) {
47 | this.mBrowserIntent.setClass(context, PhotoActivity.class);
48 | this.mBrowserIntent.putExtras(this.mBrowserOptionsBundle);
49 | return this.mBrowserIntent;
50 | }
51 |
52 | public PhotoBrowser.Builder setPhotos(ArrayList photoPaths) {
53 | this.mBrowserOptionsBundle.putStringArrayList(EXTRA_PHOTOS, photoPaths);
54 | return this;
55 | }
56 |
57 | public PhotoBrowser.Builder setCurrentItem(int currentItem) {
58 | this.mBrowserOptionsBundle.putInt(EXTRA_CURRENT_ITEM, currentItem);
59 | return this;
60 | }
61 |
62 | public PhotoBrowser.Builder setDownloadPath(String downloadPath) {
63 | this.mBrowserOptionsBundle.putString(EXTRA_DOWNLOAD_PATH, downloadPath);
64 | return this;
65 | }
66 |
67 |
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/library/src/main/java/me/cl/library/photo/PhotoListener.java:
--------------------------------------------------------------------------------
1 | package me.cl.library.photo;
2 |
3 | import android.net.Uri;
4 | import androidx.annotation.StringRes;
5 | import androidx.fragment.app.FragmentActivity;
6 | import android.view.View;
7 | import android.widget.ImageView;
8 |
9 | /**
10 | * author : happyc
11 | * e-mail : bafs.jy@live.com
12 | * time : 2019/04/26
13 | * desc : 图片相关事件
14 | * version: 1.0
15 | */
16 | public interface PhotoListener {
17 |
18 | interface OnPhotoClickListener {
19 | void onClick(FragmentActivity activity, ImageView view, int position, String url);
20 | }
21 |
22 | interface OnPhotoLongClickListener {
23 | void onLongClick(FragmentActivity activity, ImageView view, int position, String url);
24 | }
25 |
26 | interface OnClickListener {
27 | void onClick(View view, int position, String url);
28 | }
29 |
30 | interface OnLongClickListener {
31 | void onLongClick(View view, int position, String url);
32 | }
33 |
34 | interface OnMoveOutListener {
35 | void onMoveOut();
36 | }
37 |
38 | interface OnPageChangeListener {
39 | void onPageSelected(int position);
40 | }
41 |
42 | interface OnDownLoadListener {
43 | void onSuccess(Uri uri);
44 | void onFailed(@StringRes int message);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/library/src/main/java/me/cl/library/photo/PhotoViewPager.java:
--------------------------------------------------------------------------------
1 | package me.cl.library.photo;
2 |
3 | import android.content.Context;
4 | import androidx.annotation.NonNull;
5 | import androidx.annotation.Nullable;
6 | import androidx.viewpager.widget.ViewPager;
7 | import android.util.AttributeSet;
8 | import android.view.MotionEvent;
9 |
10 | /**
11 | * author : happyc
12 | * e-mail : bafs.jy@live.com
13 | * time : 2019/04/26
14 | * desc :
15 | * version: 1.0
16 | */
17 | public class PhotoViewPager extends ViewPager {
18 |
19 | public PhotoViewPager(@NonNull Context context) {
20 | super(context);
21 | }
22 |
23 | public PhotoViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
24 | super(context, attrs);
25 | }
26 |
27 | @Override
28 | public boolean onInterceptTouchEvent(MotionEvent ev) {
29 | try {
30 | return super.onInterceptTouchEvent(ev);
31 | } catch (IllegalArgumentException ex) {
32 | return false;
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/library/src/main/java/me/cl/library/util/ToastUtil.java:
--------------------------------------------------------------------------------
1 | package me.cl.library.util;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.os.Handler;
6 | import android.os.Looper;
7 | import android.widget.Toast;
8 |
9 | /**
10 | * author : Bafs
11 | * e-mail : bafs.jy@live.com
12 | * time : 2018/07/24
13 | * desc : Toast Util
14 | * version: 1.0
15 | */
16 | public class ToastUtil {
17 |
18 | private static Toast toast;
19 | private static Handler mHandler = new Handler(Looper.getMainLooper());
20 |
21 | public static void showToast(final Context context, final String info) {
22 | mHandler.post(new Runnable() {
23 | @Override
24 | public void run() {
25 | toastShow(context, info, Toast.LENGTH_SHORT);
26 | }
27 | });
28 | }
29 |
30 | public static void showToast(final Context context, final int infoId) {
31 | mHandler.post(new Runnable() {
32 | @Override
33 | public void run() {
34 | toastShow(context, context.getResources().getString(infoId), Toast.LENGTH_SHORT);
35 | }
36 | });
37 | }
38 |
39 | @SuppressLint("ShowToast")
40 | private static void toastShow(Context context, String info, int duration) {
41 | if (toast == null) {
42 | toast = Toast.makeText(context, info, duration);
43 | } else {
44 | toast.setText(info);
45 | }
46 | toast.show();
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/ic_navigate.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
10 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/img_toast_bc.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/library/src/main/res/drawable/img_toast_bc.9.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable/loading_frame.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
11 |
14 |
17 |
18 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/loading_icon_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/library/src/main/res/drawable/loading_icon_1.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable/loading_icon_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/library/src/main/res/drawable/loading_icon_2.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable/loading_icon_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/library/src/main/res/drawable/loading_icon_3.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable/loading_icon_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/library/src/main/res/drawable/loading_icon_4.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable/photo_text_shape.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/lib_dialog_progress.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
25 |
26 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/lib_load_more.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
18 |
23 |
24 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/photo_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
21 |
22 |
30 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/photo_adapter_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/library/src/main/res/values/value.xml:
--------------------------------------------------------------------------------
1 |
2 | library
3 | 请稍等…
4 | 正在加载…
5 | 上拉加载
6 | 没有更多
7 | 加载完成
8 |
9 | #00ddff
10 |
11 |
12 |
15 |
16 |
19 |
20 |
30 |
31 |
39 |
40 |
41 | %1$d/%2$ds
42 | 保存
43 | 图片保存成功
44 | 图片保存失败
45 | 图片已保存
46 |
47 |
48 |
--------------------------------------------------------------------------------
/screenshot/Screenshot_about.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/screenshot/Screenshot_about.jpg
--------------------------------------------------------------------------------
/screenshot/Screenshot_feed.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/screenshot/Screenshot_feed.jpg
--------------------------------------------------------------------------------
/screenshot/Screenshot_home.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/screenshot/Screenshot_home.jpg
--------------------------------------------------------------------------------
/screenshot/Screenshot_login.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/screenshot/Screenshot_login.jpg
--------------------------------------------------------------------------------
/screenshot/Screenshot_message.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/screenshot/Screenshot_message.jpg
--------------------------------------------------------------------------------
/screenshot/Screenshot_mine.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/screenshot/Screenshot_mine.jpg
--------------------------------------------------------------------------------
/screenshot/Screenshot_publish.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/screenshot/Screenshot_publish.jpg
--------------------------------------------------------------------------------
/screenshot/Screenshot_relevant.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/screenshot/Screenshot_relevant.jpg
--------------------------------------------------------------------------------
/screenshot/Screenshot_user.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/screenshot/Screenshot_user.jpg
--------------------------------------------------------------------------------
/screenshot/Screenshot_welcome.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happycao/lingxi-android/bc88d0074f1d97771f243e1dbf78bd03647ca141/screenshot/Screenshot_welcome.jpg
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':library'
2 | include ':PhotoPicker'
3 |
--------------------------------------------------------------------------------