├── app ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── drawable-xhdpi │ │ │ ├── ic_ask_64.png │ │ │ ├── ic_avatar.png │ │ │ ├── ic_fav_64.png │ │ │ ├── ic_follow.png │ │ │ ├── ic_like.png │ │ │ ├── ic_newt.jpg │ │ │ ├── ic_random.png │ │ │ ├── ic_rise.png │ │ │ ├── ic_search.png │ │ │ ├── ic_share.png │ │ │ ├── ic_tab_me.png │ │ │ ├── ic_trends.png │ │ │ ├── icon_zan.png │ │ │ ├── ic_about_us.png │ │ │ ├── ic_fans_64.png │ │ │ ├── ic_favorite.png │ │ │ ├── ic_feedback.png │ │ │ ├── ic_like_64.png │ │ │ ├── ic_post_64.png │ │ │ ├── ic_rise_64.png │ │ │ ├── ic_settings.png │ │ │ ├── ic_tab_bigv.png │ │ │ ├── icon_right.png │ │ │ ├── img_loading.jpg │ │ │ ├── shadow_left.png │ │ │ ├── ic_answer_64.png │ │ │ ├── ic_favor_fill.png │ │ │ ├── ic_good_grades.png │ │ │ ├── ic_logo_font.png │ │ │ ├── ic_rise_red_64.png │ │ │ ├── ic_tab_essence.png │ │ │ ├── ic_thanks_64.png │ │ │ ├── icon_copyright.png │ │ │ ├── shadow_bottom.png │ │ │ ├── shadow_right.png │ │ │ ├── ic_changed_theme.png │ │ │ ├── ic_rise_blue_64.png │ │ │ ├── ic_default_avatar.png │ │ │ ├── ic_favorite_light.png │ │ │ ├── ic_favorite_normal.png │ │ │ ├── ic_info_black_24dp.png │ │ │ ├── ic_sync_black_24dp.png │ │ │ └── ic_notifications_black_24dp.png │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── icon_launcher.png │ │ ├── drawable │ │ │ ├── bg_stroke.xml │ │ │ ├── side_nav_bar.xml │ │ │ ├── round_textview.xml │ │ │ ├── bg_dark_item_click.xml │ │ │ └── bg_btn_click_normal.xml │ │ ├── anim │ │ │ ├── alpha_0_1.xml │ │ │ └── touch_card.xml │ │ ├── layout │ │ │ ├── swipeback_layout.xml │ │ │ ├── toolbar_settings.xml │ │ │ ├── fragment_topic.xml │ │ │ ├── activity_random_look.xml │ │ │ ├── fragment_hot_user.xml │ │ │ ├── activity_home.xml │ │ │ ├── fragment_posts.xml │ │ │ ├── view_toolbar.xml │ │ │ ├── fragment_home.xml │ │ │ ├── fragment_top_user_list.xml │ │ │ ├── fragment_user_center.xml │ │ │ ├── view_scroll_toolbar.xml │ │ │ ├── activity_loading.xml │ │ │ ├── view_scroll_toolbar_with_tab.xml │ │ │ ├── activity_web_browser.xml │ │ │ ├── view_scroll_toolbar_with_scroll_tab.xml │ │ │ ├── content_post_answers.xml │ │ │ ├── layout_user_merge_page.xml │ │ │ ├── layout_user_page_info.xml │ │ │ ├── activity_post_answers.xml │ │ │ ├── view_overlap_scrolling.xml │ │ │ ├── view_collapsing_toolbar.xml │ │ │ ├── activity_user_search.xml │ │ │ ├── fragment_post.xml │ │ │ ├── fragment_top_user.xml │ │ │ ├── layout_topic_list_item.xml │ │ │ ├── layout_my_top_answer_list_item.xml │ │ │ ├── activity_top_user.xml │ │ │ ├── activity_user_profile.xml │ │ │ ├── view_collapsing_toolbar_with_layout.xml │ │ │ ├── layout_user_search_item.xml │ │ │ ├── activity_my_favorite.xml │ │ │ ├── layout_post_list_item.xml │ │ │ ├── layout_top_user_item.xml │ │ │ ├── activity_about_us.xml │ │ │ ├── layout_answer_list_item.xml │ │ │ └── activity_feedback.xml │ │ ├── values-w820dp │ │ │ └── dimens.xml │ │ ├── menu │ │ │ ├── menu_search.xml │ │ │ └── menu_home.xml │ │ ├── values │ │ │ ├── dimens.xml │ │ │ ├── drawables.xml │ │ │ ├── colors.xml │ │ │ ├── attrs.xml │ │ │ └── strings.xml │ │ ├── xml │ │ │ └── preferences.xml │ │ ├── values-v21 │ │ │ └── styles.xml │ │ └── layout-v21 │ │ │ ├── layout_topic_list_item.xml │ │ │ ├── layout_post_list_item.xml │ │ │ ├── layout_top_user_item.xml │ │ │ └── layout_answer_list_item.xml │ │ ├── java │ │ └── com │ │ │ └── ouwenjie │ │ │ └── zhizhihu │ │ │ ├── common │ │ │ ├── Constant.java │ │ │ ├── ModelErrorException.java │ │ │ ├── OttoBus.java │ │ │ └── ThemeManager.java │ │ │ ├── ui │ │ │ ├── viewInterface │ │ │ │ ├── MVPView.java │ │ │ │ ├── PostAnswerViewInterface.java │ │ │ │ ├── TopUserListViewInterface.java │ │ │ │ ├── UserCenterViewInterface.java │ │ │ │ └── PostListViewInterface.java │ │ │ ├── view │ │ │ │ ├── swipebacklayout │ │ │ │ │ ├── BuildConfig.java │ │ │ │ │ ├── app │ │ │ │ │ │ ├── SwipeBackActivityBase.java │ │ │ │ │ │ ├── SwipeBackPreferenceActivity.java │ │ │ │ │ │ ├── SwipeBackActivity.java │ │ │ │ │ │ └── SwipeBackActivityHelper.java │ │ │ │ │ └── Utils.java │ │ │ │ ├── ProgressHelper.java │ │ │ │ └── MultiSwipeRefreshLayout.java │ │ │ ├── fragment │ │ │ │ ├── BaseFragment.java │ │ │ │ ├── SwipeRefreshFragment.java │ │ │ │ └── PostListFragment.java │ │ │ ├── activity │ │ │ │ ├── AboutUsActivity.java │ │ │ │ ├── base │ │ │ │ │ ├── SwipeBackActivity.java │ │ │ │ │ └── BaseActivity.java │ │ │ │ ├── LoadingActivity.java │ │ │ │ ├── HomeActivity.java │ │ │ │ ├── AppCompatPreferenceActivity.java │ │ │ │ └── MyFavoriteActivity.java │ │ │ └── adapter │ │ │ │ ├── PostListAdapter.java │ │ │ │ └── PostAnswerAdapter.java │ │ │ ├── model │ │ │ ├── entity │ │ │ │ ├── BaseModel.java │ │ │ │ ├── CheckNewModel.java │ │ │ │ ├── PostsModel.java │ │ │ │ ├── AnswerModel.java │ │ │ │ ├── TopUserModel.java │ │ │ │ ├── SearchUserModel.java │ │ │ │ ├── TabData.java │ │ │ │ ├── Topic.java │ │ │ │ ├── SearchUser.java │ │ │ │ ├── Post.java │ │ │ │ └── Answer.java │ │ │ ├── api │ │ │ │ ├── ZhiHu.java │ │ │ │ ├── TopUserType.java │ │ │ │ └── ApiService.java │ │ │ ├── mInterface │ │ │ │ └── ApiInterface.java │ │ │ └── mImp │ │ │ │ └── ApiImp.java │ │ │ ├── AppConfig.java │ │ │ ├── App.java │ │ │ ├── utils │ │ │ ├── DimenUtil.java │ │ │ ├── Once.java │ │ │ └── DataCleanUtil.java │ │ │ └── presenter │ │ │ ├── PostAnswerPresenter.java │ │ │ ├── TopUserListPresenter.java │ │ │ ├── UserCenterPresenter.java │ │ │ ├── MVPPresenter.java │ │ │ └── PostListPresenter.java │ │ └── AndroidManifest.xml └── build.gradle ├── settings.gradle ├── screenshot ├── 1.png ├── 2.png ├── 3.png └── 4.png ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── README.md ├── gradle.properties └── gradlew.bat /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /screenshot/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/screenshot/1.png -------------------------------------------------------------------------------- /screenshot/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/screenshot/2.png -------------------------------------------------------------------------------- /screenshot/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/screenshot/3.png -------------------------------------------------------------------------------- /screenshot/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/screenshot/4.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_ask_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_ask_64.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_avatar.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_fav_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_fav_64.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_follow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_follow.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_like.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_like.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_newt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_newt.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_random.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_random.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_rise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_rise.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_search.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_share.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_tab_me.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_tab_me.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_trends.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_trends.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/icon_zan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/icon_zan.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_about_us.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_about_us.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_fans_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_fans_64.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_favorite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_favorite.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_feedback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_feedback.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_like_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_like_64.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_post_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_post_64.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_rise_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_rise_64.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_settings.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_tab_bigv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_tab_bigv.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/icon_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/icon_right.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/img_loading.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/img_loading.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/shadow_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/shadow_left.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/icon_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/mipmap-xhdpi/icon_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_answer_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_answer_64.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_favor_fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_favor_fill.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_good_grades.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_good_grades.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_logo_font.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_logo_font.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_rise_red_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_rise_red_64.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_tab_essence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_tab_essence.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_thanks_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_thanks_64.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/icon_copyright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/icon_copyright.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/shadow_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/shadow_bottom.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/shadow_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/shadow_right.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_changed_theme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_changed_theme.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_rise_blue_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_rise_blue_64.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_default_avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_default_avatar.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_favorite_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_favorite_light.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_favorite_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_favorite_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_info_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_info_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_sync_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_sync_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_notifications_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Null-Ouwenjie/zhizhihu/HEAD/app/src/main/res/drawable-xhdpi/ic_notifications_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_stroke.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/anim/alpha_0_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/common/Constant.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.common; 2 | 3 | /** 4 | * Created by Jack on 2016/2/3. 5 | */ 6 | public class Constant { 7 | 8 | public static final String KEY_BIND_USER = "UserCenterFragment_Bind_User"; 9 | 10 | } 11 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Mar 22 14:24:09 CST 2016 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/res/layout/swipeback_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/side_nav_bar.xml: -------------------------------------------------------------------------------- 1 | 3 | 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/common/ModelErrorException.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.common; 2 | 3 | /** 4 | * 当 model 不等于 1 时,触发这一个 Exception 5 | * Created by Jack on 2016/1/18. 6 | */ 7 | public class ModelErrorException extends RuntimeException { 8 | public ModelErrorException(String msg) { 9 | super(msg); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/ui/viewInterface/MVPView.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.ui.viewInterface; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * Created by Jack on 2015/11/18. 7 | */ 8 | public interface MVPView { 9 | 10 | Context getContext(); 11 | 12 | void showProgress(); 13 | void hideProgress(); 14 | 15 | void toast(String msg); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/ui/viewInterface/PostAnswerViewInterface.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.ui.viewInterface; 2 | 3 | import com.ouwenjie.zhizhihu.model.entity.Answer; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Created by 文杰 on 2015/10/27. 9 | */ 10 | public interface PostAnswerViewInterface extends MVPView { 11 | 12 | void initList(List answers); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/ui/viewInterface/TopUserListViewInterface.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.ui.viewInterface; 2 | 3 | import com.ouwenjie.zhizhihu.model.entity.TopUser; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Created by Jack on 2016/3/23. 9 | */ 10 | public interface TopUserListViewInterface extends MVPView { 11 | 12 | void createUserListView(List topUsers); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/ui/viewInterface/UserCenterViewInterface.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.ui.viewInterface; 2 | 3 | import com.ouwenjie.zhizhihu.model.entity.UserDetail; 4 | 5 | /** 6 | * Created by Administrator on 2016/4/9 0009. 7 | */ 8 | public interface UserCenterViewInterface extends MVPView { 9 | 10 | void initData(UserDetail userDetailInfo); 11 | 12 | void showDefaultInfo(); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/round_textview.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/common/OttoBus.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.common; 2 | 3 | import com.squareup.otto.Bus; 4 | 5 | /** 6 | * Created by Jack on 2015/11/17. 7 | */ 8 | public class OttoBus { 9 | 10 | private static final Bus sBUS = new Bus(); 11 | 12 | public static Bus getInstance() { 13 | return sBUS; 14 | } 15 | 16 | private OttoBus() { 17 | // No instances. 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_search.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/ui/viewInterface/PostListViewInterface.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.ui.viewInterface; 2 | 3 | import com.ouwenjie.zhizhihu.model.entity.Post; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Created by 文杰 on 2015/10/27. 9 | */ 10 | public interface PostListViewInterface extends MVPView { 11 | 12 | void initList(List posts); 13 | 14 | void refreshList(); 15 | 16 | void setSwipeRefreshing(boolean refreshing); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_dark_item_click.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 160dp 5 | 6 | 16dp 7 | 16dp 8 | 16dp 9 | 8dp 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/toolbar_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/model/entity/BaseModel.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.model.entity; 2 | 3 | /** 4 | * Created by Jack on 2016/2/3. 5 | */ 6 | public class BaseModel { 7 | 8 | String error; 9 | 10 | public String getError() { 11 | return error; 12 | } 13 | 14 | public void setError(String error) { 15 | this.error = error; 16 | } 17 | 18 | @Override 19 | public String toString() { 20 | return "BaseModel{" + 21 | "error='" + error + '\'' + 22 | '}'; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | 15 | # Ignore Gradle files 16 | .gradle/ 17 | build/ 18 | /*/build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | # Eclipse project files 30 | .classpath 31 | .project 32 | .settings/ 33 | 34 | # Intellij project files 35 | *.iml 36 | *.ipr 37 | *.iws 38 | .idea/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 知之乎 [deprecated] 2 | zhihu.com Unofficial Client for Android 3 | 4 | >基于 MVP 模式,使用 Retrofit 2 + RxJava 做网络请求,API 来自[看知乎](http://www.kanzhihu.com/api-document) 5 | >[看知乎](http://www.kanzhihu.com/api-document) 网站已下线,该项目已无法运行,看看代码就好了。 6 | >或许哪天我会维护一个《知之乎》的后台呢,有空再说吧 :) 7 | 8 | #截图 9 | 10 | ![](screenshot/1.png) 11 | ![](screenshot/2.png) 12 | ![](screenshot/3.png) 13 | ![](screenshot/4.png) 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | Apache License 22 | Version 2.0, January 2004 23 | http://www.apache.org/licenses/ 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/model/entity/CheckNewModel.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.model.entity; 2 | 3 | /** 4 | * Created by Jack on 2016/2/3. 5 | */ 6 | public class CheckNewModel extends BaseModel { 7 | 8 | boolean result; 9 | 10 | public boolean isResult() { 11 | return result; 12 | } 13 | 14 | public void setResult(boolean result) { 15 | this.result = result; 16 | } 17 | 18 | @Override 19 | public String toString() { 20 | return "CheckNewModel{" + 21 | "result=" + result + 22 | '}'; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/ui/view/swipebacklayout/BuildConfig.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.ui.view.swipebacklayout; 2 | 3 | /** 4 | * Created by 文杰 on 2015/11/5. 5 | */ 6 | public class BuildConfig { 7 | public static final boolean DEBUG = false; 8 | public static final String APPLICATION_ID = "me.imid.swipebacklayout.lib"; 9 | public static final String BUILD_TYPE = "release"; 10 | public static final String FLAVOR = ""; 11 | public static final int VERSION_CODE = 1; 12 | public static final String VERSION_NAME = "1.0.0"; 13 | 14 | public BuildConfig() { 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_topic.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/model/entity/PostsModel.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.model.entity; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by 文杰 on 2015/10/19. 7 | */ 8 | public class PostsModel extends BaseModel { 9 | 10 | int count; 11 | List posts; 12 | 13 | public int getCount() { 14 | return count; 15 | } 16 | 17 | public void setCount(int count) { 18 | this.count = count; 19 | } 20 | 21 | public List getPosts() { 22 | return posts; 23 | } 24 | 25 | public void setPosts(List posts) { 26 | this.posts = posts; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/res/values/drawables.xml: -------------------------------------------------------------------------------- 1 | 2 | @android:drawable/ic_menu_camera 3 | @android:drawable/ic_menu_gallery 4 | @android:drawable/ic_menu_slideshow 5 | @android:drawable/ic_menu_manage 6 | @android:drawable/ic_menu_share 7 | @android:drawable/ic_menu_send 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/model/entity/AnswerModel.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.model.entity; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by 文杰 on 2015/10/20. 7 | */ 8 | public class AnswerModel extends BaseModel { 9 | 10 | int count; 11 | List answers; 12 | 13 | public int getCount() { 14 | return count; 15 | } 16 | 17 | public void setCount(int count) { 18 | this.count = count; 19 | } 20 | 21 | public List getAnswers() { 22 | return answers; 23 | } 24 | 25 | public void setAnswers(List answers) { 26 | this.answers = answers; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_random_look.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/model/entity/TopUserModel.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.model.entity; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by 文杰 on 2015/10/23. 7 | */ 8 | public class TopUserModel extends BaseModel { 9 | 10 | int count; 11 | List topuser; 12 | 13 | public int getCount() { 14 | return count; 15 | } 16 | 17 | public void setCount(int count) { 18 | this.count = count; 19 | } 20 | 21 | public List getTopuser() { 22 | return topuser; 23 | } 24 | 25 | public void setTopuser(List topuser) { 26 | this.topuser = topuser; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/model/entity/SearchUserModel.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.model.entity; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by Jack on 2016/2/3. 7 | */ 8 | public class SearchUserModel extends BaseModel { 9 | 10 | int count; 11 | List users; 12 | 13 | public int getCount() { 14 | return count; 15 | } 16 | 17 | public void setCount(int count) { 18 | this.count = count; 19 | } 20 | 21 | public List getUsers() { 22 | return users; 23 | } 24 | 25 | public void setUsers(List users) { 26 | this.users = users; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_btn_click_normal.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_home.xml: -------------------------------------------------------------------------------- 1 | 4 | 8 | 12 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_hot_user.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/AppConfig.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu; 2 | 3 | /** 4 | * 定义系统级配置 5 | * Created by Jack on 2015/11/27. 6 | */ 7 | public class AppConfig { 8 | 9 | public static boolean isDebug = true; // todo Release 版本记得关掉 debug (设为 false) 10 | 11 | public static final int MAX_CACHE_AGE = 3600 * 12; // 60 * 60 = 1 小时 12 | 13 | public static final String KZH_BASE_URL = "http://api.kanzhihu.com/"; 14 | 15 | public static final long RESPONSE_CACHE_SIZE = 10240000; // 10MB 16 | public static final int CONNECTION_TIME_OUT = 30; 17 | public static final int READ_TIME_OUT = 30; 18 | public static final int WRITE_TIME_OUT = 30; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_home.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/ui/view/swipebacklayout/app/SwipeBackActivityBase.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.ui.view.swipebacklayout.app; 2 | 3 | import com.ouwenjie.zhizhihu.ui.view.swipebacklayout.SwipeBackLayout; 4 | 5 | /** 6 | * Created by 文杰 on 2015/11/5. 7 | */ 8 | public interface SwipeBackActivityBase { 9 | /** 10 | * @return the SwipeBackLayout associated with this activity. 11 | */ 12 | public abstract SwipeBackLayout getSwipeBackLayout(); 13 | 14 | public abstract void setSwipeBackEnable(boolean enable); 15 | 16 | /** 17 | * Scroll out contentView and finish the activity 18 | */ 19 | public abstract void scrollToFinishActivity(); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/res/anim/touch_card.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_posts.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/model/api/ZhiHu.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.model.api; 2 | 3 | /** 4 | * Created by 文杰 on 2015/10/19. 5 | */ 6 | public class ZhiHu { 7 | 8 | // 知乎 url 9 | public static final String ZHIHU_URL = "http://www.zhihu.com/"; 10 | 11 | // 问题 url:http://www.zhihu.com/question/questionid 12 | // 答案 url:http://www.zhihu.com/question/questionid/answer/answerid 13 | public static final String QUESTION_BASE_URL = "http://www.zhihu.com/question/"; 14 | 15 | // 用户主页 url:http://www.zhihu.com/people/authorhash 16 | public static final String PEOPLE_BASE_URL = "http://www.zhihu.com/people/"; 17 | 18 | // 知乎 Android 客户端包名 19 | public static final String PACKAGE_NAME = "com.zhihu.android"; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_toolbar.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_home.xml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_top_user_list.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_user_center.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/model/entity/TabData.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.model.entity; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by Jack on 2016/3/15. 7 | */ 8 | public class TabData { 9 | 10 | String tabTxt; 11 | List topics; 12 | 13 | public String getTabTxt() { 14 | return tabTxt; 15 | } 16 | 17 | public void setTabTxt(String tabTxt) { 18 | this.tabTxt = tabTxt; 19 | } 20 | 21 | public List getTopics() { 22 | return topics; 23 | } 24 | 25 | public void setTopics(List topics) { 26 | this.topics = topics; 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | return "TabData{" + 32 | "tabTxt='" + tabTxt + '\'' + 33 | ", topics=" + topics + 34 | '}'; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_scroll_toolbar.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_loading.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/model/mInterface/ApiInterface.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.model.mInterface; 2 | 3 | import com.ouwenjie.zhizhihu.model.entity.Answer; 4 | import com.ouwenjie.zhizhihu.model.entity.Post; 5 | import com.ouwenjie.zhizhihu.model.entity.SearchUser; 6 | import com.ouwenjie.zhizhihu.model.entity.TopUser; 7 | import com.ouwenjie.zhizhihu.model.entity.UserDetail; 8 | 9 | import java.util.List; 10 | 11 | import rx.Observable; 12 | 13 | /** 14 | * Created by Jack on 2016/3/23. 15 | */ 16 | public interface ApiInterface { 17 | 18 | Observable> getPosts(); 19 | 20 | Observable> getPosts(String publishTime); 21 | 22 | Observable> getAnswers(String date, String name); 23 | 24 | Observable> getTopUser(String type, int page, int item); 25 | 26 | Observable getUserDetail(String userHash); 27 | 28 | Observable> searchUser(String key); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #076dc0 4 | #076dc0 5 | @color/md_pink_300 6 | 7 | @color/md_pink_500 8 | @color/md_light_blue_500 9 | @color/md_light_green_500 10 | 11 | #666666 12 | 13 | #E91E63 14 | #E91E63 15 | #F8BBD0 16 | #E040FB 17 | #212121 18 | #727272 19 | #FFFFFF 20 | #B6B6B6 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_scroll_toolbar_with_tab.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 16 | 17 | 18 | 19 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_web_browser.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 18 | 19 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_scroll_toolbar_with_scroll_tab.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 20 | 21 | 22 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/ui/view/ProgressHelper.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.ui.view; 2 | 3 | import android.app.ProgressDialog; 4 | import android.content.Context; 5 | 6 | /** 7 | * Created by Jack on 2016/1/19. 8 | */ 9 | public class ProgressHelper { 10 | 11 | private Context context; 12 | 13 | protected ProgressDialog progressDialog; 14 | 15 | public ProgressHelper(Context context) { 16 | this.context = context; 17 | } 18 | 19 | public void showProgress(String msg) { 20 | if (progressDialog == null) { 21 | progressDialog = new ProgressDialog(context); 22 | progressDialog.setIndeterminate(true); 23 | } 24 | progressDialog.setMessage(msg); 25 | progressDialog.show(); 26 | } 27 | 28 | public void showProgress() { 29 | showProgress("正在加载..."); 30 | } 31 | 32 | public void hideProgress() { 33 | if (progressDialog == null) { 34 | return; 35 | } 36 | if (progressDialog.isShowing()) { 37 | progressDialog.hide(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/App.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | 6 | import com.facebook.stetho.Stetho; 7 | import com.orhanobut.logger.LogLevel; 8 | import com.orhanobut.logger.Logger; 9 | 10 | import io.realm.Realm; 11 | import io.realm.RealmConfiguration; 12 | 13 | /** 14 | * Created by 文杰 on 2015/10/28. 15 | */ 16 | public class App extends Application { 17 | 18 | private static Context sContext; 19 | 20 | @Override 21 | public void onCreate() { 22 | super.onCreate(); 23 | sContext = getApplicationContext(); 24 | 25 | Realm.setDefaultConfiguration(new RealmConfiguration.Builder(getApplicationContext()).build()); 26 | 27 | if (AppConfig.isDebug) { 28 | Stetho.initializeWithDefaults(this); // 开启 Stetho 调试模式 29 | Logger.init("=LingKu=").logLevel(LogLevel.FULL); 30 | } else { 31 | Logger.init().logLevel(LogLevel.NONE); 32 | } 33 | 34 | } 35 | 36 | public static Context getContext() { 37 | return sContext; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/model/entity/Topic.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.model.entity; 2 | 3 | /** 4 | * Created by Jack on 2016/3/15. 5 | */ 6 | public class Topic { 7 | 8 | String topicTxt; 9 | String topicImg; 10 | String targetUrl; 11 | 12 | public String getTopicTxt() { 13 | return topicTxt; 14 | } 15 | 16 | public void setTopicTxt(String topicTxt) { 17 | this.topicTxt = topicTxt; 18 | } 19 | 20 | public String getTopicImg() { 21 | return topicImg; 22 | } 23 | 24 | public void setTopicImg(String topicImg) { 25 | this.topicImg = topicImg; 26 | } 27 | 28 | public String getTargetUrl() { 29 | return targetUrl; 30 | } 31 | 32 | public void setTargetUrl(String targetUrl) { 33 | this.targetUrl = targetUrl; 34 | } 35 | 36 | @Override 37 | public String toString() { 38 | return "Topic{" + 39 | "topicTxt='" + topicTxt + '\'' + 40 | ", topicImg='" + topicImg + '\'' + 41 | ", targetUrl='" + targetUrl + '\'' + 42 | '}'; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/common/ThemeManager.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.common; 2 | 3 | import android.content.Context; 4 | 5 | import com.ouwenjie.zhizhihu.R; 6 | import com.ouwenjie.zhizhihu.utils.PreferencesUtil; 7 | 8 | /** 9 | * Created by Administrator on 2016/4/12 0012. 10 | */ 11 | public class ThemeManager { 12 | 13 | private static final String KEY_CUR_THEME = "cur_theme"; 14 | 15 | public static final int DEFAULT_THEME = R.style.AppTheme; 16 | 17 | public static final int PINK_THEME = R.style.PinkAppTheme; 18 | 19 | public static int getCurTheme(Context context) { 20 | return PreferencesUtil.getInt(context, KEY_CUR_THEME, DEFAULT_THEME); 21 | } 22 | 23 | public static void saveCurTheme(Context context, int theme) { 24 | PreferencesUtil.putInt(context, KEY_CUR_THEME, theme); 25 | } 26 | 27 | public static void changeTheme(Context context) { 28 | if (getCurTheme(context) == DEFAULT_THEME) { 29 | saveCurTheme(context, PINK_THEME); 30 | } else { 31 | saveCurTheme(context, DEFAULT_THEME); 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/ui/fragment/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.ui.fragment; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.widget.Toast; 5 | 6 | import com.ouwenjie.zhizhihu.App; 7 | import com.ouwenjie.zhizhihu.ui.view.ProgressHelper; 8 | 9 | /** 10 | * Created by Jack on 2015/11/17. 11 | */ 12 | public class BaseFragment extends Fragment { 13 | 14 | @Override 15 | public void onResume() { 16 | super.onResume(); 17 | } 18 | 19 | @Override 20 | public void onPause() { 21 | super.onPause(); 22 | } 23 | 24 | public void toast(String msg) { 25 | Toast.makeText(App.getContext(), msg, Toast.LENGTH_SHORT).show(); 26 | } 27 | 28 | private ProgressHelper progressHelper; 29 | 30 | public void showProgress() { 31 | showProgress(null); 32 | } 33 | 34 | public void showProgress(String msg) { 35 | if (progressHelper == null) { 36 | progressHelper = new ProgressHelper(getActivity()); 37 | } 38 | progressHelper.showProgress(msg); 39 | } 40 | 41 | public void hideProgress() { 42 | progressHelper.hideProgress(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/res/layout/content_post_answers.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 17 | 18 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_user_merge_page.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 23 | 24 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_user_page_info.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 15 | 16 | 19 | 20 | 21 | 22 | 27 | 28 | 31 | 32 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_post_answers.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_overlap_scrolling.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 19 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/xml/preferences.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 26 | 27 | 28 | 29 | 30 | 31 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 19 | 20 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_collapsing_toolbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 21 | 22 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_user_search.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 14 | 15 | 20 | 21 | 25 | 26 | 27 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/model/api/TopUserType.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.model.api; 2 | 3 | /** 4 | * Created by Jack on 2016/2/3. 5 | */ 6 | public enum TopUserType { 7 | 8 | ask, // 提问数 9 | answer, // 回答数 10 | post, // 专栏文章数 11 | agree, // 赞同数 12 | ratio, // 平均赞同(总赞同数/(回答+专栏)) 13 | followee, // 关注数 14 | follower, // 被关注数(粉丝) 15 | 16 | agreei, // 1日赞同数增加 17 | agreeiratio, // 1日赞同数增幅 18 | agreeiw, // 7日赞同数增加 19 | agreeiratiow, // 7日赞同数增幅 20 | 21 | followeri, // 1日被关注数增加 22 | followiratio, // 1日被关注数增幅 23 | followeriw, // 7日被关注数增加 24 | followiratiow, // 7日被关注数增幅 25 | 26 | thanks, // 感谢数 27 | tratio, // 感谢/赞同比 28 | fav, // 收藏数 29 | fratio, // 收藏/赞同比 30 | logs, // 公共编辑数 31 | 32 | mostvote, // 最高赞同 33 | mostvotepercent, // 最高赞同占比 34 | mostvote5, // 前5赞同 35 | mostvote5percent, // 前5赞同占比 36 | mostvote10, // 前10赞同 37 | mostvote10percent, // 前10赞同占比 38 | 39 | count10000, // 赞同≥10000答案数 40 | count5000, // 赞同≥5000答案数 41 | count2000, // 赞同≥2000答案数 42 | count1000, // 赞同≥1000答案数 43 | count500, // 赞同≥500答案数 44 | count200, // 赞同≥200答案数 45 | count100, // 赞同≥100答案数 46 | 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/ui/activity/AboutUsActivity.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.ui.activity; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.widget.Toolbar; 5 | import android.view.View; 6 | import android.widget.TextView; 7 | 8 | import com.ouwenjie.zhizhihu.R; 9 | import com.ouwenjie.zhizhihu.ui.activity.base.SwipeBackActivity; 10 | 11 | import butterknife.Bind; 12 | import butterknife.ButterKnife; 13 | 14 | public class AboutUsActivity extends SwipeBackActivity { 15 | 16 | @Bind(R.id.toolbar) 17 | Toolbar mToolbar; 18 | @Bind(R.id.version_name_txt) 19 | TextView mVersionNameTxt; 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_about_us); 25 | ButterKnife.bind(this); 26 | 27 | initTitleBar(); 28 | } 29 | 30 | private void initTitleBar() { 31 | setSupportActionBar(mToolbar); 32 | setTitle("关于我们"); 33 | getSupportActionBar().setHomeButtonEnabled(true); 34 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 35 | mToolbar.setNavigationOnClickListener( 36 | new View.OnClickListener() { 37 | @Override 38 | public void onClick(View v) { 39 | AboutUsActivity.this.onBackPressed(); 40 | } 41 | } 42 | ); 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 知之乎 3 | 4 | 精选 5 | 大 V 6 | 7 | 8 | Open navigation drawer 9 | Close navigation drawer 10 | 11 | Settings 12 | 知之乎 13 | PostAnswersActivity 14 | 15 | 16 | Hello blank fragment 17 | 网络不可用 18 | 操作失败 19 | left image 20 | right image 21 | UserProfileActivity 22 | Settings 23 | 24 | 25 | 26 | 27 | 知乎客户端 28 | 内置浏览器 29 | 外部浏览器 30 | 31 | 32 | 33 | 0 34 | 1 35 | 2 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_post.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 15 | 16 | 24 | 25 | 26 | 27 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_top_user.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 15 | 16 | 24 | 25 | 26 | 27 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/ui/view/swipebacklayout/app/SwipeBackPreferenceActivity.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.ui.view.swipebacklayout.app; 2 | 3 | import android.os.Bundle; 4 | import android.preference.PreferenceActivity; 5 | import android.view.View; 6 | 7 | import com.ouwenjie.zhizhihu.ui.view.swipebacklayout.SwipeBackLayout; 8 | 9 | /** 10 | * Created by 文杰 on 2015/11/5. 11 | */ 12 | public class SwipeBackPreferenceActivity extends PreferenceActivity implements SwipeBackActivityBase { 13 | private SwipeBackActivityHelper mHelper; 14 | 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | mHelper = new SwipeBackActivityHelper(this); 19 | mHelper.onActivityCreate(); 20 | } 21 | 22 | @Override 23 | protected void onPostCreate(Bundle savedInstanceState) { 24 | super.onPostCreate(savedInstanceState); 25 | mHelper.onPostCreate(); 26 | } 27 | 28 | @Override 29 | public View findViewById(int id) { 30 | View v = super.findViewById(id); 31 | if (v == null && mHelper != null) 32 | return mHelper.findViewById(id); 33 | return v; 34 | } 35 | 36 | @Override 37 | public SwipeBackLayout getSwipeBackLayout() { 38 | return mHelper.getSwipeBackLayout(); 39 | } 40 | 41 | @Override 42 | public void setSwipeBackEnable(boolean enable) { 43 | getSwipeBackLayout().setEnableGesture(enable); 44 | } 45 | 46 | @Override 47 | public void scrollToFinishActivity() { 48 | getSwipeBackLayout().scrollToFinishActivity(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/ui/view/swipebacklayout/app/SwipeBackActivity.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.ui.view.swipebacklayout.app; 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.app.FragmentActivity; 5 | import android.view.View; 6 | 7 | import com.ouwenjie.zhizhihu.ui.view.swipebacklayout.SwipeBackLayout; 8 | import com.ouwenjie.zhizhihu.ui.view.swipebacklayout.Utils; 9 | 10 | /** 11 | * Created by 文杰 on 2015/11/5. 12 | */ 13 | public class SwipeBackActivity extends FragmentActivity implements SwipeBackActivityBase { 14 | private SwipeBackActivityHelper mHelper; 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | mHelper = new SwipeBackActivityHelper(this); 20 | mHelper.onActivityCreate(); 21 | } 22 | 23 | @Override 24 | protected void onPostCreate(Bundle savedInstanceState) { 25 | super.onPostCreate(savedInstanceState); 26 | mHelper.onPostCreate(); 27 | } 28 | 29 | @Override 30 | public View findViewById(int id) { 31 | View v = super.findViewById(id); 32 | if (v == null && mHelper != null) 33 | return mHelper.findViewById(id); 34 | return v; 35 | } 36 | 37 | @Override 38 | public SwipeBackLayout getSwipeBackLayout() { 39 | return mHelper.getSwipeBackLayout(); 40 | } 41 | 42 | @Override 43 | public void setSwipeBackEnable(boolean enable) { 44 | getSwipeBackLayout().setEnableGesture(enable); 45 | } 46 | 47 | @Override 48 | public void scrollToFinishActivity() { 49 | Utils.convertActivityToTranslucent(this); 50 | getSwipeBackLayout().scrollToFinishActivity(); 51 | } 52 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_topic_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 19 | 20 | 27 | 28 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/utils/DimenUtil.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.utils; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * Created by Jack on 2015/11/14. 7 | */ 8 | public class DimenUtil { 9 | /** 10 | * 将px值转换为dip或dp值,保证尺寸大小不变 11 | * 12 | * @param pxValue 13 | * (DisplayMetrics类中属性density) 14 | * @return 15 | */ 16 | public static int px2dip(Context context, float pxValue) { 17 | final float scale = context.getResources().getDisplayMetrics().density; 18 | return (int) (pxValue / scale + 0.5f); 19 | } 20 | 21 | /** 22 | * 将dip或dp值转换为px值,保证尺寸大小不变 23 | * 24 | * @param dipValue 25 | * (DisplayMetrics类中属性density) 26 | * @return 27 | */ 28 | public static int dip2px(Context context, float dipValue) { 29 | final float scale = context.getResources().getDisplayMetrics().density; 30 | return (int) (dipValue * scale + 0.5f); 31 | } 32 | 33 | /** 34 | * 将px值转换为sp值,保证文字大小不变 35 | * 36 | * @param pxValue 37 | * (DisplayMetrics类中属性scaledDensity) 38 | * @return 39 | */ 40 | public static int px2sp(Context context, float pxValue) { 41 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 42 | return (int) (pxValue / fontScale + 0.5f); 43 | } 44 | 45 | /** 46 | * 将sp值转换为px值,保证文字大小不变 47 | * 48 | * @param spValue 49 | * (DisplayMetrics类中属性scaledDensity) 50 | * @return 51 | */ 52 | public static int sp2px(Context context, float spValue) { 53 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 54 | return (int) (spValue * fontScale + 0.5f); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/res/layout-v21/layout_topic_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 20 | 21 | 28 | 29 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/model/entity/SearchUser.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.model.entity; 2 | 3 | /** 4 | * Created by 文杰 on 2015/10/23. 5 | */ 6 | public class SearchUser { 7 | 8 | // 基本信息 9 | String id; 10 | String name; 11 | String hash; 12 | String avatar; 13 | String signature; 14 | 15 | String answer; // 回答数 16 | String agree; // 赞同数 17 | String follower; // 被关注数(粉丝) 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 getName() { 28 | return name; 29 | } 30 | 31 | public void setName(String name) { 32 | this.name = name; 33 | } 34 | 35 | public String getHash() { 36 | return hash; 37 | } 38 | 39 | public void setHash(String hash) { 40 | this.hash = hash; 41 | } 42 | 43 | public String getAvatar() { 44 | return avatar; 45 | } 46 | 47 | public void setAvatar(String avatar) { 48 | this.avatar = avatar; 49 | } 50 | 51 | public String getSignature() { 52 | return signature; 53 | } 54 | 55 | public void setSignature(String signature) { 56 | this.signature = signature; 57 | } 58 | 59 | public String getAnswer() { 60 | return answer; 61 | } 62 | 63 | public void setAnswer(String answer) { 64 | this.answer = answer; 65 | } 66 | 67 | public String getAgree() { 68 | return agree; 69 | } 70 | 71 | public void setAgree(String agree) { 72 | this.agree = agree; 73 | } 74 | 75 | public String getFollower() { 76 | return follower; 77 | } 78 | 79 | public void setFollower(String follower) { 80 | this.follower = follower; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/ui/activity/base/SwipeBackActivity.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.ui.activity.base; 2 | 3 | import android.os.Bundle; 4 | import android.view.View; 5 | 6 | import com.ouwenjie.zhizhihu.ui.view.swipebacklayout.SwipeBackLayout; 7 | import com.ouwenjie.zhizhihu.ui.view.swipebacklayout.Utils; 8 | import com.ouwenjie.zhizhihu.ui.view.swipebacklayout.app.SwipeBackActivityBase; 9 | import com.ouwenjie.zhizhihu.ui.view.swipebacklayout.app.SwipeBackActivityHelper; 10 | 11 | /** 12 | * Created by 文杰 on 2015/10/22. 13 | */ 14 | public class SwipeBackActivity extends BaseActivity implements SwipeBackActivityBase { 15 | 16 | private SwipeBackActivityHelper mHelper; 17 | 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | mHelper = new SwipeBackActivityHelper(this); 22 | mHelper.onActivityCreate(); 23 | } 24 | 25 | @Override 26 | protected void onPostCreate(Bundle savedInstanceState) { 27 | super.onPostCreate(savedInstanceState); 28 | mHelper.onPostCreate(); 29 | } 30 | 31 | @Override 32 | public View findViewById(int id) { 33 | View v = super.findViewById(id); 34 | if (v == null && mHelper != null) 35 | return mHelper.findViewById(id); 36 | return v; 37 | } 38 | 39 | @Override 40 | public SwipeBackLayout getSwipeBackLayout() { 41 | return mHelper.getSwipeBackLayout(); 42 | } 43 | 44 | @Override 45 | public void setSwipeBackEnable(boolean enable) { 46 | getSwipeBackLayout().setEnableGesture(enable); 47 | } 48 | 49 | @Override 50 | public void scrollToFinishActivity() { 51 | Utils.convertActivityToTranslucent(this); 52 | getSwipeBackLayout().scrollToFinishActivity(); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_my_top_answer_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 18 | 19 | 22 | 23 | 31 | 32 | 39 | 40 | 41 | 42 | 48 | 49 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_top_user.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 22 | 23 | 24 | 25 | 32 | 33 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_user_profile.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 21 | 22 | 23 | 24 | 30 | 31 | 34 | 35 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_collapsing_toolbar_with_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 23 | 24 | 32 | 33 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/utils/Once.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Drakeet 3 | * 4 | * This file is part of Meizhi 5 | * 6 | * Meizhi is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Meizhi is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with Meizhi. If not, see . 18 | */ 19 | 20 | package com.ouwenjie.zhizhihu.utils; 21 | 22 | import android.content.Context; 23 | import android.content.SharedPreferences; 24 | 25 | /** 26 | * Created by drakeet on 8/16/15. 27 | */ 28 | public class Once { 29 | 30 | SharedPreferences mSharedPreferences; 31 | Context mContext; 32 | 33 | 34 | public Once(Context context) { 35 | mSharedPreferences = context.getSharedPreferences("once", Context.MODE_PRIVATE); 36 | mContext = context; 37 | } 38 | 39 | 40 | public void show(String tagKey, OnceCallback callback) { 41 | boolean isSecondTime = mSharedPreferences.getBoolean(tagKey, false); 42 | if (!isSecondTime) { 43 | callback.onOnce(); 44 | SharedPreferences.Editor editor = mSharedPreferences.edit(); 45 | editor.putBoolean(tagKey, true); 46 | editor.apply(); 47 | } 48 | } 49 | 50 | 51 | public void show(int tagKeyResId, OnceCallback callback) { 52 | show(mContext.getString(tagKeyResId), callback); 53 | } 54 | 55 | 56 | public interface OnceCallback { 57 | void onOnce(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/presenter/PostAnswerPresenter.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.presenter; 2 | 3 | import com.ouwenjie.zhizhihu.model.entity.Answer; 4 | import com.ouwenjie.zhizhihu.model.mImp.ApiImp; 5 | import com.ouwenjie.zhizhihu.model.mInterface.ApiInterface; 6 | import com.ouwenjie.zhizhihu.ui.viewInterface.PostAnswerViewInterface; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | import rx.Subscriber; 12 | import rx.Subscription; 13 | 14 | /** 15 | * Created by 文杰 on 2015/10/27. 16 | */ 17 | public class PostAnswerPresenter extends MVPPresenter { 18 | 19 | private ApiInterface mApiInterface; 20 | 21 | private List mAnswers = new ArrayList<>(); 22 | 23 | public PostAnswerPresenter(PostAnswerViewInterface postAnswerViewInterface) { 24 | super(postAnswerViewInterface); 25 | mApiInterface = new ApiImp(); 26 | } 27 | 28 | @Override 29 | public void create() { 30 | 31 | } 32 | 33 | @Override 34 | public void destroy() { 35 | mCompositeSubscription.clear(); 36 | } 37 | 38 | /** 39 | * 初始化列表 40 | * 41 | * @param date 42 | * @param name 43 | */ 44 | public void initData(String date, String name) { 45 | Subscription sub = mApiInterface.getAnswers(date, name) 46 | .subscribe(new Subscriber>() { 47 | @Override 48 | public void onCompleted() { 49 | 50 | } 51 | 52 | @Override 53 | public void onError(Throwable e) { 54 | doRxError(e); 55 | } 56 | 57 | @Override 58 | public void onNext(List list) { 59 | mAnswers = list; 60 | mViewInterface.initList(mAnswers); 61 | } 62 | }); 63 | mCompositeSubscription.add(sub); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/presenter/TopUserListPresenter.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.presenter; 2 | 3 | import com.ouwenjie.zhizhihu.model.entity.TopUser; 4 | import com.ouwenjie.zhizhihu.model.mImp.ApiImp; 5 | import com.ouwenjie.zhizhihu.model.mInterface.ApiInterface; 6 | import com.ouwenjie.zhizhihu.ui.viewInterface.TopUserListViewInterface; 7 | 8 | import java.util.List; 9 | 10 | import rx.Subscriber; 11 | import rx.Subscription; 12 | 13 | /** 14 | * Created by Jack on 2016/3/23. 15 | */ 16 | public class TopUserListPresenter extends MVPPresenter { 17 | 18 | private int mPage = 1; 19 | private static final int sPageCount = 20; 20 | 21 | private ApiInterface mApiInterface; 22 | private String mTopType; 23 | private List mTopUsers; 24 | 25 | public TopUserListPresenter(TopUserListViewInterface viewInterface) { 26 | super(viewInterface); 27 | mApiInterface = new ApiImp(); 28 | } 29 | 30 | @Override 31 | public void create() { 32 | 33 | } 34 | 35 | @Override 36 | public void destroy() { 37 | mCompositeSubscription.clear(); 38 | } 39 | 40 | 41 | public void loadTopUserData(String topType) { 42 | mTopType = topType; 43 | Subscription sub = mApiInterface.getTopUser(topType, mPage, sPageCount) 44 | .subscribe(new Subscriber>() { 45 | @Override 46 | public void onCompleted() { 47 | 48 | } 49 | 50 | @Override 51 | public void onError(Throwable e) { 52 | doRxError(e); 53 | } 54 | 55 | @Override 56 | public void onNext(List topUsers) { 57 | mTopUsers = topUsers; 58 | mViewInterface.createUserListView(mTopUsers); 59 | } 60 | }); 61 | mCompositeSubscription.add(sub); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_user_search_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 20 | 21 | 32 | 33 | 44 | 45 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/model/entity/Post.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.model.entity; 2 | 3 | /** 4 | * 文章列表 5 | * Created by 文杰 on 2015/10/19. 6 | */ 7 | public class Post { 8 | 9 | String id; 10 | String date; // 发表日期 11 | String name; // 文章名称 (yesterday / recent / archive) 12 | String pic; // 抬头图 url 13 | String publishtime; // 发表时间戳 14 | int count; // 文章包含答案数量 15 | String excerpt; // 摘要文字 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 getDate() { 26 | return date; 27 | } 28 | 29 | public void setDate(String date) { 30 | this.date = date; 31 | } 32 | 33 | public String getName() { 34 | return name; 35 | } 36 | 37 | public void setName(String name) { 38 | this.name = name; 39 | } 40 | 41 | public String getPic() { 42 | return pic; 43 | } 44 | 45 | public void setPic(String pic) { 46 | this.pic = pic; 47 | } 48 | 49 | public String getPublishtime() { 50 | return publishtime; 51 | } 52 | 53 | public void setPublishtime(String publishtime) { 54 | this.publishtime = publishtime; 55 | } 56 | 57 | public int getCount() { 58 | return count; 59 | } 60 | 61 | public void setCount(int count) { 62 | this.count = count; 63 | } 64 | 65 | public String getExcerpt() { 66 | return excerpt; 67 | } 68 | 69 | public void setExcerpt(String excerpt) { 70 | this.excerpt = excerpt; 71 | } 72 | 73 | @Override 74 | public String toString() { 75 | return "Post{" + 76 | "id='" + id + '\'' + 77 | ", date='" + date + '\'' + 78 | ", name='" + name + '\'' + 79 | ", pic='" + pic + '\'' + 80 | ", publishtime='" + publishtime + '\'' + 81 | ", count=" + count + 82 | ", excerpt='" + excerpt + '\'' + 83 | '}'; 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/ui/view/swipebacklayout/app/SwipeBackActivityHelper.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.ui.view.swipebacklayout.app; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Color; 5 | import android.graphics.drawable.ColorDrawable; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | 9 | import com.ouwenjie.zhizhihu.R; 10 | import com.ouwenjie.zhizhihu.ui.view.swipebacklayout.SwipeBackLayout; 11 | import com.ouwenjie.zhizhihu.ui.view.swipebacklayout.Utils; 12 | 13 | /** 14 | * Created by 文杰 on 2015/11/5. 15 | */ 16 | public class SwipeBackActivityHelper { 17 | private Activity mActivity; 18 | 19 | private SwipeBackLayout mSwipeBackLayout; 20 | 21 | public SwipeBackActivityHelper(Activity activity) { 22 | mActivity = activity; 23 | } 24 | 25 | @SuppressWarnings("deprecation") 26 | public void onActivityCreate() { 27 | mActivity.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); 28 | mActivity.getWindow().getDecorView().setBackgroundDrawable(null); 29 | mSwipeBackLayout = (SwipeBackLayout) LayoutInflater.from(mActivity).inflate( 30 | R.layout.swipeback_layout, null); 31 | mSwipeBackLayout.addSwipeListener(new SwipeBackLayout.SwipeListener() { 32 | @Override 33 | public void onScrollStateChange(int state, float scrollPercent) { 34 | } 35 | 36 | @Override 37 | public void onEdgeTouch(int edgeFlag) { 38 | Utils.convertActivityToTranslucent(mActivity); 39 | } 40 | 41 | @Override 42 | public void onScrollOverThreshold() { 43 | 44 | } 45 | }); 46 | } 47 | 48 | public void onPostCreate() { 49 | mSwipeBackLayout.attachToActivity(mActivity); 50 | } 51 | 52 | public View findViewById(int id) { 53 | if (mSwipeBackLayout != null) { 54 | return mSwipeBackLayout.findViewById(id); 55 | } 56 | return null; 57 | } 58 | 59 | public SwipeBackLayout getSwipeBackLayout() { 60 | return mSwipeBackLayout; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_my_favorite.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 22 | 23 | 24 | 25 | 31 | 32 | 38 | 39 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_post_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 21 | 22 | 32 | 33 | 38 | 39 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/ui/activity/base/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.ui.activity.base; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.widget.Toast; 8 | 9 | import com.ouwenjie.zhizhihu.App; 10 | import com.ouwenjie.zhizhihu.common.ThemeManager; 11 | import com.ouwenjie.zhizhihu.ui.view.ProgressHelper; 12 | 13 | public class BaseActivity extends AppCompatActivity { 14 | 15 | protected int mTheme = ThemeManager.DEFAULT_THEME; 16 | 17 | @Override 18 | protected void onCreate(Bundle savedInstanceState) { 19 | if (savedInstanceState == null) { 20 | mTheme = ThemeManager.getCurTheme(this); 21 | } else { 22 | mTheme = savedInstanceState.getInt("theme"); 23 | } 24 | setTheme(mTheme); 25 | super.onCreate(savedInstanceState); 26 | 27 | } 28 | 29 | 30 | @Override 31 | protected void onResume() { 32 | super.onResume(); 33 | if (mTheme != ThemeManager.getCurTheme(this)) { 34 | reload(); 35 | } 36 | } 37 | 38 | public void reload() { 39 | Intent intent = getIntent(); 40 | overridePendingTransition(0, 0); 41 | intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); 42 | finish(); 43 | overridePendingTransition(0, 0); 44 | startActivity(intent); 45 | } 46 | 47 | 48 | // protected void openWebView(String url) { 49 | // Intent intent = new Intent(this, WebBrowserActivity.class); 50 | // intent.putExtra("url", url); 51 | // startActivity(intent); 52 | // } 53 | 54 | public Context getContext() { 55 | return getApplicationContext(); 56 | } 57 | 58 | public void toast(String msg) { 59 | Toast.makeText(App.getContext(), msg, Toast.LENGTH_SHORT).show(); 60 | } 61 | 62 | private ProgressHelper progressHelper = new ProgressHelper(this); 63 | 64 | public void showProgress() { 65 | showProgress(null); 66 | } 67 | 68 | public void showProgress(String msg) { 69 | progressHelper.showProgress(msg); 70 | } 71 | 72 | public void hideProgress() { 73 | progressHelper.hideProgress(); 74 | } 75 | 76 | 77 | } 78 | -------------------------------------------------------------------------------- /app/src/main/res/layout-v21/layout_post_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 22 | 23 | 33 | 34 | 39 | 40 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/presenter/UserCenterPresenter.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.presenter; 2 | 3 | import android.text.TextUtils; 4 | 5 | import com.google.gson.Gson; 6 | import com.ouwenjie.zhizhihu.common.Constant; 7 | import com.ouwenjie.zhizhihu.model.entity.SearchUser; 8 | import com.ouwenjie.zhizhihu.model.entity.UserDetail; 9 | import com.ouwenjie.zhizhihu.model.mImp.ApiImp; 10 | import com.ouwenjie.zhizhihu.model.mInterface.ApiInterface; 11 | import com.ouwenjie.zhizhihu.ui.viewInterface.UserCenterViewInterface; 12 | import com.ouwenjie.zhizhihu.utils.PreferencesUtil; 13 | 14 | import rx.Subscription; 15 | import rx.functions.Action1; 16 | 17 | /** 18 | * Created by ouwenjie on 2016/7/2. 19 | */ 20 | public class UserCenterPresenter extends MVPPresenter { 21 | 22 | private ApiInterface mApiInterface; 23 | private boolean mHasBindUser = false; 24 | private UserDetail mUserDetailInfo; 25 | 26 | public UserCenterPresenter(UserCenterViewInterface viewInterface) { 27 | super(viewInterface); 28 | mApiInterface = new ApiImp(); 29 | } 30 | 31 | @Override 32 | public void create() { 33 | 34 | } 35 | 36 | @Override 37 | public void destroy() { 38 | mCompositeSubscription.clear(); 39 | } 40 | 41 | public void loadData() { 42 | String userString = PreferencesUtil.getString(mContext, Constant.KEY_BIND_USER); 43 | if (!TextUtils.isEmpty(userString)) { 44 | mHasBindUser = true; 45 | final SearchUser user = new Gson().fromJson(userString, SearchUser.class); 46 | Subscription sub = mApiInterface.getUserDetail(user.getHash()) 47 | .subscribe(new Action1() { 48 | @Override 49 | public void call(UserDetail userDetail) { 50 | mUserDetailInfo = userDetail; 51 | mViewInterface.initData(mUserDetailInfo); 52 | } 53 | }, new Action1() { 54 | @Override 55 | public void call(Throwable e) { 56 | doRxError(e); 57 | } 58 | }); 59 | mCompositeSubscription.add(sub); 60 | } else { 61 | mHasBindUser = false; 62 | mViewInterface.showDefaultInfo(); 63 | 64 | } 65 | } 66 | 67 | public boolean hasBindUser() { 68 | return mHasBindUser; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/ui/view/swipebacklayout/Utils.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.ui.view.swipebacklayout; 2 | 3 | import android.app.Activity; 4 | 5 | import java.lang.reflect.Method; 6 | 7 | /** 8 | * Created by 文杰 on 2015/11/5. 9 | */ 10 | public class Utils { 11 | private Utils() { 12 | } 13 | 14 | /** 15 | * Convert a translucent themed Activity 16 | * {@link android.R.attr#windowIsTranslucent} to a fullscreen opaque 17 | * Activity. 18 | *

19 | * Call this whenever the background of a translucent Activity has changed 20 | * to become opaque. Doing so will allow the {@link android.view.Surface} of 21 | * the Activity behind to be released. 22 | *

23 | * This call has no effect on non-translucent activities or on activities 24 | * with the {@link android.R.attr#windowIsFloating} attribute. 25 | */ 26 | public static void convertActivityFromTranslucent(Activity activity) { 27 | try { 28 | Method method = Activity.class.getDeclaredMethod("convertFromTranslucent"); 29 | method.setAccessible(true); 30 | method.invoke(activity); 31 | } catch (Throwable t) { 32 | } 33 | } 34 | 35 | /** 36 | * Convert a translucent themed Activity 37 | * {@link android.R.attr#windowIsTranslucent} back from opaque to 38 | * translucent following a call to 39 | * {@link #convertActivityFromTranslucent(android.app.Activity)} . 40 | *

41 | * Calling this allows the Activity behind this one to be seen again. Once 42 | * all such Activities have been redrawn 43 | *

44 | * This call has no effect on non-translucent activities or on activities 45 | * with the {@link android.R.attr#windowIsFloating} attribute. 46 | */ 47 | public static void convertActivityToTranslucent(Activity activity) { 48 | try { 49 | Class[] classes = Activity.class.getDeclaredClasses(); 50 | Class translucentConversionListenerClazz = null; 51 | for (Class clazz : classes) { 52 | if (clazz.getSimpleName().contains("TranslucentConversionListener")) { 53 | translucentConversionListenerClazz = clazz; 54 | } 55 | } 56 | Method method = Activity.class.getDeclaredMethod("convertToTranslucent", 57 | translucentConversionListenerClazz); 58 | method.setAccessible(true); 59 | method.invoke(activity, new Object[] { 60 | null 61 | }); 62 | } catch (Throwable t) { 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/presenter/MVPPresenter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Saúl Molinero. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.ouwenjie.zhizhihu.presenter; 17 | 18 | import android.content.Context; 19 | 20 | import com.orhanobut.logger.Logger; 21 | import com.ouwenjie.zhizhihu.R; 22 | import com.ouwenjie.zhizhihu.common.ModelErrorException; 23 | import com.ouwenjie.zhizhihu.ui.viewInterface.MVPView; 24 | import com.ouwenjie.zhizhihu.utils.NetworkUtil; 25 | 26 | import rx.subscriptions.CompositeSubscription; 27 | 28 | /** 29 | * Presenter 抽象类,定义了基本的类型和流程 30 | */ 31 | public abstract class MVPPresenter { 32 | 33 | protected T mViewInterface; 34 | protected Context mContext; 35 | 36 | protected CompositeSubscription mCompositeSubscription; 37 | 38 | public MVPPresenter(T viewInterface) { 39 | this.mViewInterface = viewInterface; 40 | mContext = viewInterface.getContext(); 41 | mCompositeSubscription = new CompositeSubscription(); 42 | } 43 | 44 | /** 45 | * Called when the presenter is initialized 46 | */ 47 | public abstract void create(); 48 | 49 | /** 50 | * Called when the presenter is stop, 51 | * i.e when an activity * or a fragment finishes 52 | */ 53 | public abstract void destroy(); 54 | 55 | public T getAttachedView() { 56 | return mViewInterface; 57 | } 58 | 59 | protected void doRxError(Throwable e) { 60 | Logger.t("doRxError=> ").e(e.getMessage()); 61 | if (e instanceof ModelErrorException) { 62 | // 网络请求成功,但出现错误,则显示后台的 message 63 | mViewInterface.toast(e.getMessage()); 64 | } else { 65 | // 网络错误 66 | if (!NetworkUtil.isNetworkAvailable(mContext)) { 67 | mViewInterface.toast(mViewInterface.getContext().getString(R.string.label_network_not_available)); 68 | } else { 69 | // 其它错误 70 | mViewInterface.toast(mViewInterface.getContext().getString(R.string.label_operation_failed)); 71 | } 72 | } 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_top_user_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 21 | 22 | 27 | 28 | 36 | 37 | 45 | 46 | 47 | 48 | 55 | 56 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /app/src/main/res/layout-v21/layout_top_user_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 22 | 23 | 28 | 29 | 37 | 38 | 46 | 47 | 48 | 49 | 56 | 57 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/ui/activity/LoadingActivity.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.ui.activity; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.os.Handler; 6 | import android.os.Message; 7 | import android.view.Window; 8 | import android.view.WindowManager; 9 | import android.view.animation.Animation; 10 | import android.view.animation.AnimationUtils; 11 | import android.widget.ImageView; 12 | 13 | import com.ouwenjie.zhizhihu.R; 14 | import com.ouwenjie.zhizhihu.ui.activity.base.BaseActivity; 15 | 16 | import java.lang.ref.WeakReference; 17 | 18 | import butterknife.Bind; 19 | import butterknife.ButterKnife; 20 | 21 | public class LoadingActivity extends BaseActivity { 22 | 23 | public static final int MSG_PASS = 1; // 进入主页 24 | public final long MIN_WAITTING_MSEC = 1000; // 最少等待的毫秒数 25 | private Handler mHandler = new WeakHandler(this); 26 | 27 | @Bind(R.id.loading_img) 28 | ImageView mLoadingImg; 29 | @Bind(R.id.logo_img) 30 | ImageView mLogoImg; 31 | 32 | @Override 33 | protected void onCreate(Bundle savedInstanceState) { 34 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 35 | WindowManager.LayoutParams.FLAG_FULLSCREEN);// 实现窗口全屏 36 | requestWindowFeature(Window.FEATURE_NO_TITLE);// 设置无标题样式 37 | super.onCreate(savedInstanceState); 38 | setContentView(R.layout.activity_loading); 39 | ButterKnife.bind(this); 40 | 41 | } 42 | 43 | @Override 44 | protected void onStart() { 45 | super.onStart(); 46 | // 3 秒后进入主界面 47 | mHandler.removeMessages(MSG_PASS); 48 | mHandler.sendEmptyMessageDelayed(MSG_PASS, MIN_WAITTING_MSEC * 3); 49 | Animation alpha = AnimationUtils.loadAnimation(this, R.anim.alpha_0_1); 50 | mLogoImg.startAnimation(alpha); 51 | } 52 | 53 | /** 54 | * 进入主页 55 | */ 56 | private void pass() { 57 | Intent intent; 58 | intent = new Intent(getApplicationContext(), HomeActivity.class); 59 | startActivity(intent); 60 | finish(); 61 | } 62 | 63 | 64 | static class WeakHandler extends Handler { 65 | WeakReference mActivity; 66 | 67 | public WeakHandler(LoadingActivity activity) { 68 | mActivity = new WeakReference(activity); 69 | } 70 | 71 | @Override 72 | public void handleMessage(Message msg) { 73 | super.handleMessage(msg); 74 | LoadingActivity activity = mActivity.get(); 75 | if (null != activity) { 76 | switch (msg.what) { 77 | case MSG_PASS: // 跳转 78 | activity.pass(); 79 | break; 80 | default: 81 | break; 82 | } 83 | } 84 | } 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/ui/view/MultiSwipeRefreshLayout.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Drakeet 3 | * 4 | * This file is part of Meizhi 5 | * 6 | * Meizhi is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Meizhi is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with Meizhi. If not, see . 18 | */ 19 | 20 | package com.ouwenjie.zhizhihu.ui.view; 21 | 22 | import android.content.Context; 23 | import android.content.res.TypedArray; 24 | import android.graphics.drawable.Drawable; 25 | import android.support.v4.widget.SwipeRefreshLayout; 26 | import android.util.AttributeSet; 27 | 28 | import com.ouwenjie.zhizhihu.R; 29 | 30 | 31 | /** 32 | * Pick from Google io 2014 33 | * Created by drakeet on 1/3/15. 34 | */ 35 | public class MultiSwipeRefreshLayout extends SwipeRefreshLayout { 36 | 37 | private CanChildScrollUpCallback mCanChildScrollUpCallback; 38 | private Drawable mForegroundDrawable; 39 | 40 | public MultiSwipeRefreshLayout(Context context) { 41 | this(context, null); 42 | } 43 | 44 | 45 | public MultiSwipeRefreshLayout(Context context, AttributeSet attrs) { 46 | super(context, attrs); 47 | final TypedArray a = 48 | context.obtainStyledAttributes(attrs, R.styleable.MultiSwipeRefreshLayout, 0, 0); 49 | 50 | mForegroundDrawable = a.getDrawable(R.styleable.MultiSwipeRefreshLayout_foreground); 51 | if (mForegroundDrawable != null) { 52 | mForegroundDrawable.setCallback(this); 53 | setWillNotDraw(false); 54 | } 55 | a.recycle(); 56 | } 57 | 58 | 59 | @Override 60 | protected void onSizeChanged(int w, int h, int oldw, int oldh) { 61 | super.onSizeChanged(w, h, oldw, oldh); 62 | if (mForegroundDrawable != null) { 63 | mForegroundDrawable.setBounds(0, 0, w, h); 64 | } 65 | } 66 | 67 | 68 | public void setCanChildScrollUpCallback(CanChildScrollUpCallback canChildScrollUpCallback) { 69 | mCanChildScrollUpCallback = canChildScrollUpCallback; 70 | } 71 | 72 | 73 | public interface CanChildScrollUpCallback { 74 | boolean canSwipeRefreshChildScrollUp(); 75 | } 76 | 77 | 78 | @Override 79 | public boolean canChildScrollUp() { 80 | if (mCanChildScrollUpCallback != null) { 81 | return mCanChildScrollUpCallback.canSwipeRefreshChildScrollUp(); 82 | } 83 | return super.canChildScrollUp(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/model/api/ApiService.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.model.api; 2 | 3 | import com.ouwenjie.zhizhihu.model.entity.AnswerModel; 4 | import com.ouwenjie.zhizhihu.model.entity.CheckNewModel; 5 | import com.ouwenjie.zhizhihu.model.entity.PostsModel; 6 | import com.ouwenjie.zhizhihu.model.entity.SearchUserModel; 7 | import com.ouwenjie.zhizhihu.model.entity.TopUserModel; 8 | import com.ouwenjie.zhizhihu.model.entity.UserDetail; 9 | 10 | import retrofit2.http.GET; 11 | import retrofit2.http.Headers; 12 | import retrofit2.http.Path; 13 | import rx.Observable; 14 | 15 | /** 16 | * @link http://www.kanzhihu.com/api-document 17 | *

18 | * Created by 文杰 on 2015/10/18. 19 | */ 20 | public interface ApiService { 21 | 22 | /** 23 | * 获取最新的 Post 列表 24 | * 25 | * @return 26 | */ 27 | @Headers("Cache-Control: public, max-age=3600") 28 | @GET("getposts") 29 | Observable getPosts(); 30 | 31 | /** 32 | * 获取一个时间戳之前的 Post 33 | * 34 | * @param publishTime 时间戳 35 | * @return 36 | */ 37 | @Headers("Cache-Control: public, max-age=3600") 38 | @GET("getposts/{publishTime}") 39 | Observable getPosts(@Path("publishTime") String publishTime); 40 | 41 | /** 42 | * 检查「看知乎」首页在指定时间之后有没有更新 43 | * 44 | * @param publishTime 时间戳 45 | * @return 46 | */ 47 | @Headers("Cache-Control: public, max-age=3600") 48 | @GET("checknew/{publishTime}") 49 | Observable checkNew(@Path("publishTime") String publishTime); 50 | 51 | /** 52 | * 获取单篇 Post 的答案列表 53 | * 54 | * @param date 55 | * @param category 56 | * @return 57 | */ 58 | @Headers("Cache-Control: public, max-age=3600") 59 | @GET("getpostanswers/{date}/{category}") 60 | Observable getPostAnswers(@Path("date") String date, @Path("category") String category); 61 | 62 | /** 63 | * 获取单个用户的详细数据 64 | * 65 | * @param userHash 66 | * @return 67 | */ 68 | @Headers("Cache-Control: public, max-age=3600") 69 | @GET("userdetail2/{hash}") 70 | Observable getUserDetail(@Path("hash") String userHash); 71 | 72 | /** 73 | * 获取 top 3 用户 74 | * 75 | * @param type 76 | * @return 77 | */ 78 | @Headers("Cache-Control: public, max-age=3600") 79 | @GET("topuser/{type}/3") 80 | Observable getTop1User(@Path("type") String type); 81 | 82 | 83 | /** 84 | * 获取 top 用户 85 | * 86 | * @param type 87 | * @param page 88 | * @param item 89 | * @return 90 | */ 91 | @Headers("Cache-Control: public, max-age=3600") 92 | @GET("topuser/{type}/{page}/{item}") 93 | Observable getTopUser( 94 | @Path("type") String type, 95 | @Path("page") int page, 96 | @Path("item") int item 97 | ); 98 | 99 | /** 100 | * 搜索用户 101 | * 102 | * @param key 103 | * @return 104 | */ 105 | @Headers("Cache-Control: public, max-age=3600") 106 | @GET("searchuser/{key}") 107 | Observable searchUser(@Path("key") String key); 108 | 109 | } 110 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/ui/fragment/SwipeRefreshFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Drakeet 3 | * 4 | * This file is part of Meizhi 5 | * 6 | * Meizhi is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Meizhi is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with Meizhi. If not, see . 18 | */ 19 | 20 | package com.ouwenjie.zhizhihu.ui.fragment; 21 | 22 | import android.os.Bundle; 23 | import android.support.v4.widget.SwipeRefreshLayout; 24 | import android.view.View; 25 | 26 | import com.ouwenjie.zhizhihu.R; 27 | import com.ouwenjie.zhizhihu.ui.view.MultiSwipeRefreshLayout; 28 | 29 | 30 | /** 31 | * Created by drakeet on 8/11/15. 32 | */ 33 | public class SwipeRefreshFragment extends BaseFragment { 34 | 35 | public MultiSwipeRefreshLayout mSwipeRefreshLayout; 36 | 37 | @Override 38 | public void onViewCreated(View view, Bundle savedInstanceState) { 39 | super.onViewCreated(view, savedInstanceState); 40 | trySetupSwipeRefresh(view); 41 | } 42 | 43 | 44 | void trySetupSwipeRefresh(View root) { 45 | mSwipeRefreshLayout = (MultiSwipeRefreshLayout) root.findViewById(R.id.swipe_refresh_layout); 46 | if (mSwipeRefreshLayout != null) { 47 | mSwipeRefreshLayout.setColorSchemeResources( 48 | R.color.refresh_progress_2, 49 | R.color.refresh_progress_1, 50 | R.color.refresh_progress_3); 51 | mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { 52 | @Override 53 | public void onRefresh() { 54 | onRefreshing(); 55 | } 56 | }); 57 | } 58 | } 59 | 60 | public void onRefreshing() { 61 | setRefreshing(false); 62 | } 63 | 64 | public void setRefreshing(boolean refreshing) { 65 | if (mSwipeRefreshLayout == null) { 66 | return; 67 | } 68 | if (!refreshing) { 69 | // 防止刷新消失太快,让子弹飞一会儿 70 | mSwipeRefreshLayout.postDelayed(new Runnable() { 71 | @Override 72 | public void run() { 73 | mSwipeRefreshLayout.setRefreshing(false); 74 | } 75 | }, 1000); 76 | } else { 77 | mSwipeRefreshLayout.setRefreshing(true); 78 | } 79 | } 80 | 81 | 82 | public void setProgressViewOffset(boolean scale, int start, int end) { 83 | mSwipeRefreshLayout.setProgressViewOffset(scale, start, end); 84 | } 85 | 86 | 87 | public void setSwipeableChildren( 88 | MultiSwipeRefreshLayout.CanChildScrollUpCallback canChildScrollUpCallback) { 89 | mSwipeRefreshLayout.setCanChildScrollUpCallback(canChildScrollUpCallback); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/ui/activity/HomeActivity.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.ui.activity; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.IdRes; 5 | import android.widget.FrameLayout; 6 | 7 | import com.ouwenjie.zhizhihu.R; 8 | import com.ouwenjie.zhizhihu.ui.activity.base.BaseActivity; 9 | import com.ouwenjie.zhizhihu.ui.fragment.PostFragment; 10 | import com.ouwenjie.zhizhihu.ui.fragment.TopUserFragment; 11 | import com.ouwenjie.zhizhihu.ui.fragment.UserCenterFragment; 12 | import com.roughike.bottombar.BottomBar; 13 | import com.roughike.bottombar.OnMenuTabClickListener; 14 | 15 | import butterknife.Bind; 16 | import butterknife.ButterKnife; 17 | 18 | public class HomeActivity extends BaseActivity { 19 | 20 | @Bind(R.id.container) 21 | FrameLayout mContainer; 22 | 23 | private BottomBar mBottomBar; 24 | 25 | private PostFragment mPostFragment; 26 | private TopUserFragment mTopUserFragment; 27 | private UserCenterFragment mUserCenterFragment; 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | setContentView(R.layout.activity_home); 33 | ButterKnife.bind(this); 34 | 35 | mPostFragment = PostFragment.newInstance(); 36 | mTopUserFragment = TopUserFragment.newInstance(); 37 | mUserCenterFragment = UserCenterFragment.newInstance(null); 38 | 39 | getSupportFragmentManager().beginTransaction() 40 | .replace(R.id.container, mPostFragment).commit(); 41 | 42 | mBottomBar = BottomBar.attach(this, savedInstanceState); 43 | mBottomBar.setItemsFromMenu(R.menu.menu_home, new OnMenuTabClickListener() { 44 | @Override 45 | public void onMenuTabSelected(@IdRes int menuItemId) { 46 | // The user selected item number one. 47 | if (menuItemId == R.id.posts) { 48 | getSupportFragmentManager().beginTransaction() 49 | .replace(R.id.container, mPostFragment).commit(); 50 | } else if (menuItemId == R.id.bigv) { 51 | getSupportFragmentManager().beginTransaction() 52 | .replace(R.id.container, mTopUserFragment).commit(); 53 | } else if (menuItemId == R.id.me) { 54 | getSupportFragmentManager().beginTransaction() 55 | .replace(R.id.container, mUserCenterFragment).commit(); 56 | } 57 | } 58 | 59 | @Override 60 | public void onMenuTabReSelected(@IdRes int menuItemId) { 61 | // The user reselected item number one, scroll your content to top. 62 | if (menuItemId == R.id.posts) { 63 | // The user selected item number one. 64 | } else if (menuItemId == R.id.bigv) { 65 | 66 | } else if (menuItemId == R.id.me) { 67 | 68 | } 69 | } 70 | }); 71 | 72 | } 73 | 74 | @Override 75 | protected void onSaveInstanceState(Bundle outState) { 76 | super.onSaveInstanceState(outState); 77 | 78 | // Necessary to restore the BottomBar's state, otherwise we would 79 | // lose the current tab on orientation change. 80 | mBottomBar.onSaveInstanceState(outState); 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/presenter/PostListPresenter.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.presenter; 2 | 3 | import com.ouwenjie.zhizhihu.model.entity.Post; 4 | import com.ouwenjie.zhizhihu.model.mImp.ApiImp; 5 | import com.ouwenjie.zhizhihu.model.mInterface.ApiInterface; 6 | import com.ouwenjie.zhizhihu.ui.viewInterface.PostListViewInterface; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | import rx.Subscriber; 12 | import rx.Subscription; 13 | 14 | /** 15 | * Created by 文杰 on 2015/10/27. 16 | */ 17 | public class PostListPresenter extends MVPPresenter { 18 | 19 | private ApiInterface mApiInterface; 20 | 21 | private List mPosts = new ArrayList<>(); 22 | private String mLastPublishTime; 23 | 24 | private boolean mIsLoadingNextPage = false; 25 | 26 | public PostListPresenter(PostListViewInterface postListViewInterface) { 27 | super(postListViewInterface); 28 | mApiInterface = new ApiImp(); 29 | } 30 | 31 | @Override 32 | public void create() { 33 | 34 | } 35 | 36 | @Override 37 | public void destroy() { 38 | mCompositeSubscription.clear(); 39 | } 40 | 41 | /** 42 | * 初始化,加载第一页 43 | */ 44 | public void initData() { 45 | mViewInterface.setSwipeRefreshing(true); 46 | Subscription sub = mApiInterface.getPosts() 47 | .subscribe(new Subscriber>() { 48 | @Override 49 | public void onCompleted() { 50 | 51 | } 52 | 53 | @Override 54 | public void onError(Throwable e) { 55 | doRxError(e); 56 | } 57 | 58 | @Override 59 | public void onNext(List list) { 60 | mPosts = list; 61 | mViewInterface.initList(mPosts); 62 | mLastPublishTime = mPosts.get(mPosts.size() - 1).getPublishtime(); 63 | mViewInterface.setSwipeRefreshing(false); 64 | } 65 | }); 66 | mCompositeSubscription.add(sub); 67 | } 68 | 69 | /** 70 | * 加载下一页 71 | */ 72 | public void loadNextPage() { 73 | mViewInterface.setSwipeRefreshing(true); 74 | mIsLoadingNextPage = true; 75 | Subscription sub = mApiInterface.getPosts(mLastPublishTime) 76 | .subscribe(new Subscriber>() { 77 | @Override 78 | public void onCompleted() { 79 | 80 | } 81 | 82 | @Override 83 | public void onError(Throwable e) { 84 | doRxError(e); 85 | } 86 | 87 | @Override 88 | public void onNext(List list) { 89 | mPosts.addAll(list); 90 | mViewInterface.refreshList(); 91 | mLastPublishTime = mPosts.get(mPosts.size() - 1).getPublishtime(); 92 | mViewInterface.setSwipeRefreshing(false); 93 | mIsLoadingNextPage = false; 94 | } 95 | }); 96 | mCompositeSubscription.add(sub); 97 | } 98 | 99 | public boolean hasData() { 100 | return !mPosts.isEmpty(); 101 | } 102 | 103 | public boolean isLoadingNextPage() { 104 | return mIsLoadingNextPage; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/ui/activity/AppCompatPreferenceActivity.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.ui.activity; 2 | 3 | import android.content.res.Configuration; 4 | import android.os.Bundle; 5 | import android.preference.PreferenceActivity; 6 | import android.support.annotation.LayoutRes; 7 | import android.support.annotation.Nullable; 8 | import android.support.v7.app.ActionBar; 9 | import android.support.v7.app.AppCompatDelegate; 10 | import android.support.v7.widget.Toolbar; 11 | import android.view.MenuInflater; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | 15 | /** 16 | * A {@link android.preference.PreferenceActivity} which implements and proxies the necessary calls 17 | * to be used with AppCompat. 18 | */ 19 | public abstract class AppCompatPreferenceActivity extends PreferenceActivity { 20 | 21 | private AppCompatDelegate mDelegate; 22 | 23 | @Override 24 | protected void onCreate(Bundle savedInstanceState) { 25 | getDelegate().installViewFactory(); 26 | getDelegate().onCreate(savedInstanceState); 27 | super.onCreate(savedInstanceState); 28 | } 29 | 30 | @Override 31 | protected void onPostCreate(Bundle savedInstanceState) { 32 | super.onPostCreate(savedInstanceState); 33 | getDelegate().onPostCreate(savedInstanceState); 34 | } 35 | 36 | public ActionBar getSupportActionBar() { 37 | return getDelegate().getSupportActionBar(); 38 | } 39 | 40 | public void setSupportActionBar(@Nullable Toolbar toolbar) { 41 | getDelegate().setSupportActionBar(toolbar); 42 | } 43 | 44 | @Override 45 | public MenuInflater getMenuInflater() { 46 | return getDelegate().getMenuInflater(); 47 | } 48 | 49 | @Override 50 | public void setContentView(@LayoutRes int layoutResID) { 51 | getDelegate().setContentView(layoutResID); 52 | } 53 | 54 | @Override 55 | public void setContentView(View view) { 56 | getDelegate().setContentView(view); 57 | } 58 | 59 | @Override 60 | public void setContentView(View view, ViewGroup.LayoutParams params) { 61 | getDelegate().setContentView(view, params); 62 | } 63 | 64 | @Override 65 | public void addContentView(View view, ViewGroup.LayoutParams params) { 66 | getDelegate().addContentView(view, params); 67 | } 68 | 69 | @Override 70 | protected void onPostResume() { 71 | super.onPostResume(); 72 | getDelegate().onPostResume(); 73 | } 74 | 75 | @Override 76 | protected void onTitleChanged(CharSequence title, int color) { 77 | super.onTitleChanged(title, color); 78 | getDelegate().setTitle(title); 79 | } 80 | 81 | @Override 82 | public void onConfigurationChanged(Configuration newConfig) { 83 | super.onConfigurationChanged(newConfig); 84 | getDelegate().onConfigurationChanged(newConfig); 85 | } 86 | 87 | @Override 88 | protected void onStop() { 89 | super.onStop(); 90 | getDelegate().onStop(); 91 | } 92 | 93 | @Override 94 | protected void onDestroy() { 95 | super.onDestroy(); 96 | getDelegate().onDestroy(); 97 | } 98 | 99 | public void invalidateOptionsMenu() { 100 | getDelegate().invalidateOptionsMenu(); 101 | } 102 | 103 | private AppCompatDelegate getDelegate() { 104 | if (mDelegate == null) { 105 | mDelegate = AppCompatDelegate.create(this, null); 106 | } 107 | return mDelegate; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'realm-android' 3 | 4 | android { 5 | compileSdkVersion 24 6 | buildToolsVersion "24.0.0" 7 | 8 | defaultConfig { 9 | applicationId "com.ouwenjie.zhizhihu" 10 | minSdkVersion 19 11 | targetSdkVersion 22 12 | versionCode 1 13 | versionName "1.0" 14 | } 15 | 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | debug { 22 | minifyEnabled false 23 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 24 | } 25 | } 26 | 27 | // 打包配置 28 | packagingOptions { // 打包配置 29 | 30 | exclude 'META-INF/dependencies.txt' 31 | exclude 'META-INF/DEPENDENCIES.txt' 32 | exclude 'META-INF/DEPENDENCIES' 33 | exclude 'META-INF/license.txt' 34 | exclude 'META-INF/LICENSE.txt' 35 | exclude 'META-INF/LICENSE' 36 | exclude 'META-INF/notice.txt' 37 | exclude 'META-INF/NOTICE.txt' 38 | exclude 'META-INF/NOTICE' 39 | exclude 'META-INF/LGPL2.1' 40 | 41 | // 为什么加入这个呢?防止冲突,比如我同时用了dagger-compiler就会报错,说下面这个`Processor`重复了 42 | exclude 'META-INF/services/javax.annotation.processing.Processor' 43 | } 44 | 45 | // 这个是解决lint报错的代码 46 | lintOptions { 47 | abortOnError false 48 | // 防止在发布的时候出现因MissingTranslation导致Build Failed! 49 | disable 'MissingTranslation' 50 | disable 'ExtraTranslation' 51 | disable 'InvalidPackage' 52 | } 53 | 54 | // 不同的指令集分开打包 55 | splits { 56 | abi { 57 | enable true 58 | reset() 59 | include 'armeabi' 60 | universalApk false 61 | } 62 | } 63 | 64 | // // 使用Java1.8 65 | // compileOptions { 66 | // sourceCompatibility JavaVersion.VERSION_1_8 67 | // targetCompatibility JavaVersion.VERSION_1_8 68 | // } 69 | } 70 | 71 | repositories { 72 | maven { url "https://jitpack.io" } 73 | } 74 | 75 | dependencies { 76 | compile fileTree(include: ['*.jar'], dir: 'libs') 77 | compile 'com.android.support:support-v4:24.0.0' 78 | compile 'com.android.support:appcompat-v7:24.0.0' 79 | compile 'com.android.support:design:24.0.0' 80 | compile 'com.android.support:palette-v7:24.0.0' 81 | compile 'com.android.support:cardview-v7:24.0.0' 82 | compile 'com.android.support:recyclerview-v7:24.0.0' 83 | 84 | compile 'com.jakewharton:butterknife:7.0.1' 85 | compile 'com.squareup:otto:1.3.8' 86 | compile 'com.squareup.retrofit2:retrofit:2.1.0' // 会引用 okHttp 87 | compile 'com.squareup.retrofit2:converter-gson:2.1.0' // 会引用 Gson 88 | compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0' // 会引用 RxJava 89 | compile 'io.reactivex:rxandroid:1.2.1' 90 | compile 'io.reactivex:rxjava:1.1.6' 91 | compile 'com.github.bumptech.glide:glide:3.7.0' 92 | 93 | compile 'com.facebook.stetho:stetho:1.3.1' 94 | compile 'com.facebook.stetho:stetho-okhttp3:1.3.1' 95 | compile 'com.roughike:bottom-bar:1.3.9' 96 | compile 'com.miguelcatalan:materialsearchview:1.4.0' 97 | compile 'com.github.orhanobut:logger:1.12' 98 | compile 'com.nineoldandroids:library:2.4.0' 99 | compile 'de.hdodenhof:circleimageview:2.0.0' 100 | compile 'com.jcodecraeer:xrecyclerview:1.2.7' 101 | compile 'com.github.PhilJay:MPAndroidChart:v2.2.3' 102 | } 103 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 20 | 24 | 25 | 26 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 42 | 46 | 51 | 55 | 59 | 63 | 66 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/utils/DataCleanUtil.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.utils; 2 | 3 | import android.content.Context; 4 | import android.os.Environment; 5 | 6 | import java.io.File; 7 | import java.math.BigDecimal; 8 | 9 | /** 10 | * Created by Jack on 2015/11/17. 11 | */ 12 | public class DataCleanUtil { 13 | 14 | public static String getTotalCacheSize(Context context) throws Exception { 15 | long cacheSize = getFolderSize(context.getCacheDir()); 16 | if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { 17 | cacheSize += getFolderSize(context.getExternalCacheDir()); 18 | } 19 | return getFormatSize(cacheSize); 20 | } 21 | 22 | 23 | public static void clearAllCache(Context context) { 24 | deleteDir(context.getCacheDir()); 25 | if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { 26 | deleteDir(context.getExternalCacheDir()); 27 | } 28 | } 29 | 30 | private static boolean deleteDir(File dir) { 31 | if (dir != null && dir.isDirectory()) { 32 | String[] children = dir.list(); 33 | for (int i = 0; i < children.length; i++) { 34 | boolean success = deleteDir(new File(dir, children[i])); 35 | if (!success) { 36 | return false; 37 | } 38 | } 39 | } 40 | return dir.delete(); 41 | } 42 | 43 | // 获取文件 44 | //Context.getExternalFilesDir() --> SDCard/Android/data/你的应用的包名/files/ 目录,一般放一些长时间保存的数据 45 | //Context.getExternalCacheDir() --> SDCard/Android/data/你的应用包名/cache/目录,一般存放临时缓存数据 46 | public static long getFolderSize(File file) throws Exception { 47 | long size = 0; 48 | try { 49 | File[] fileList = file.listFiles(); 50 | for (int i = 0; i < fileList.length; i++) { 51 | // 如果下面还有文件 52 | if (fileList[i].isDirectory()) { 53 | size = size + getFolderSize(fileList[i]); 54 | } else { 55 | size = size + fileList[i].length(); 56 | } 57 | } 58 | } catch (Exception e) { 59 | e.printStackTrace(); 60 | } 61 | return size; 62 | } 63 | 64 | /** 65 | * 格式化单位 66 | * 67 | * @param size 68 | * @return 69 | */ 70 | public static String getFormatSize(double size) { 71 | double kiloByte = size / 1024; 72 | if (kiloByte < 1) { 73 | // return size + "Byte"; 74 | return "0K"; 75 | } 76 | 77 | double megaByte = kiloByte / 1024; 78 | if (megaByte < 1) { 79 | BigDecimal result1 = new BigDecimal(Double.toString(kiloByte)); 80 | return result1.setScale(2, BigDecimal.ROUND_HALF_UP) 81 | .toPlainString() + "KB"; 82 | } 83 | 84 | double gigaByte = megaByte / 1024; 85 | if (gigaByte < 1) { 86 | BigDecimal result2 = new BigDecimal(Double.toString(megaByte)); 87 | return result2.setScale(2, BigDecimal.ROUND_HALF_UP) 88 | .toPlainString() + "MB"; 89 | } 90 | 91 | double teraBytes = gigaByte / 1024; 92 | if (teraBytes < 1) { 93 | BigDecimal result3 = new BigDecimal(Double.toString(gigaByte)); 94 | return result3.setScale(2, BigDecimal.ROUND_HALF_UP) 95 | .toPlainString() + "GB"; 96 | } 97 | BigDecimal result4 = new BigDecimal(teraBytes); 98 | return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() 99 | + "TB"; 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/ui/adapter/PostListAdapter.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.ui.adapter; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.support.v4.app.Fragment; 6 | import android.support.v7.widget.CardView; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.ImageView; 12 | import android.widget.TextView; 13 | 14 | import com.bumptech.glide.Glide; 15 | import com.ouwenjie.zhizhihu.R; 16 | import com.ouwenjie.zhizhihu.model.entity.Post; 17 | 18 | import java.util.List; 19 | 20 | import butterknife.Bind; 21 | import butterknife.ButterKnife; 22 | 23 | /** 24 | * Created by 文杰 on 2015/10/18. 25 | */ 26 | public class PostListAdapter extends RecyclerView.Adapter { 27 | 28 | private List mPostList; 29 | private Context mContext; 30 | private OnItemClickListener mOnItemClickListener; 31 | 32 | public PostListAdapter(Activity activity, List postList) { 33 | this.mContext = activity; 34 | this.mPostList = postList; 35 | } 36 | 37 | public PostListAdapter(Fragment fragment, List postList) { 38 | this.mContext = fragment.getContext(); 39 | this.mPostList = postList; 40 | } 41 | 42 | @Override 43 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 44 | final View itemView = LayoutInflater.from(parent.getContext()) 45 | .inflate(R.layout.layout_post_list_item, parent, false); 46 | itemView.setOnClickListener(new View.OnClickListener() { 47 | @Override 48 | public void onClick(final View v) { 49 | if (mOnItemClickListener != null) { 50 | mOnItemClickListener.onItemClick(v, (Integer) v.getTag()); 51 | } 52 | } 53 | }); 54 | return new ViewHolder(itemView); 55 | } 56 | 57 | @Override 58 | public void onBindViewHolder(ViewHolder holder, int position) { 59 | Post post = mPostList.get(position); 60 | String date = post.getDate(); 61 | String name = post.getName(); 62 | String picUrl = post.getPic(); 63 | String publishtime = post.getPublishtime(); 64 | int count = post.getCount(); 65 | String excerpt = post.getExcerpt(); 66 | 67 | Glide.with(mContext) 68 | .load(picUrl) 69 | .into(holder.postPicImg); 70 | 71 | switch (name) { 72 | case "recent": 73 | name = "近日热门"; 74 | break; 75 | case "yesterday": 76 | name = "昨日最新"; 77 | break; 78 | case "archive": 79 | name = "历史精华"; 80 | break; 81 | default: 82 | break; 83 | } 84 | 85 | String txt = date + " " + name; 86 | holder.dateAndNameTxt.setText(txt); 87 | holder.excerptTxt.setText(excerpt); 88 | holder.itemView.setTag(position); 89 | } 90 | 91 | @Override 92 | public int getItemCount() { 93 | return mPostList.size(); 94 | } 95 | 96 | public class ViewHolder extends RecyclerView.ViewHolder { 97 | 98 | @Bind(R.id.post_pic_img) 99 | ImageView postPicImg; 100 | @Bind(R.id.date_and_name_txt) 101 | TextView dateAndNameTxt; 102 | @Bind(R.id.excerpt_txt) 103 | TextView excerptTxt; 104 | @Bind(R.id.layout_item_root) 105 | CardView layoutItemRoot; 106 | 107 | public ViewHolder(View itemView) { 108 | super(itemView); 109 | ButterKnife.bind(this, itemView); 110 | } 111 | } 112 | 113 | public void setOnItemClickListener(OnItemClickListener onItemClickListener) { 114 | this.mOnItemClickListener = onItemClickListener; 115 | } 116 | 117 | public interface OnItemClickListener { 118 | void onItemClick(View view, int position); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /app/src/main/java/com/ouwenjie/zhizhihu/model/entity/Answer.java: -------------------------------------------------------------------------------- 1 | package com.ouwenjie.zhizhihu.model.entity; 2 | 3 | import io.realm.RealmObject; 4 | 5 | /** 6 | * Created by 文杰 on 2015/10/20. 7 | */ 8 | public class Answer extends RealmObject { 9 | 10 | String title; 11 | String time; 12 | String summary; 13 | String questionid; 14 | String answerid; 15 | String authorname; 16 | String authorhash; 17 | String avatar; 18 | String vote; 19 | 20 | public Answer() { 21 | } 22 | 23 | public String getTitle() { 24 | return title; 25 | } 26 | 27 | public void setTitle(String title) { 28 | this.title = title; 29 | } 30 | 31 | public String getTime() { 32 | return time; 33 | } 34 | 35 | public void setTime(String time) { 36 | this.time = time; 37 | } 38 | 39 | public String getSummary() { 40 | return summary; 41 | } 42 | 43 | public void setSummary(String summary) { 44 | this.summary = summary; 45 | } 46 | 47 | public String getQuestionid() { 48 | return questionid; 49 | } 50 | 51 | public void setQuestionid(String questionid) { 52 | this.questionid = questionid; 53 | } 54 | 55 | public String getAnswerid() { 56 | return answerid; 57 | } 58 | 59 | public void setAnswerid(String answerid) { 60 | this.answerid = answerid; 61 | } 62 | 63 | public String getAuthorname() { 64 | return authorname; 65 | } 66 | 67 | public void setAuthorname(String authorname) { 68 | this.authorname = authorname; 69 | } 70 | 71 | public String getAuthorhash() { 72 | return authorhash; 73 | } 74 | 75 | public void setAuthorhash(String authorhash) { 76 | this.authorhash = authorhash; 77 | } 78 | 79 | public String getAvatar() { 80 | return avatar; 81 | } 82 | 83 | public void setAvatar(String avatar) { 84 | this.avatar = avatar; 85 | } 86 | 87 | public String getVote() { 88 | return vote; 89 | } 90 | 91 | public void setVote(String vote) { 92 | this.vote = vote; 93 | } 94 | 95 | @Override 96 | public boolean equals(Object o) { 97 | if (this == o) return true; 98 | if (o == null || getClass() != o.getClass()) return false; 99 | 100 | Answer answer = (Answer) o; 101 | 102 | if (title != null ? !title.equals(answer.title) : answer.title != null) return false; 103 | if (time != null ? !time.equals(answer.time) : answer.time != null) return false; 104 | if (summary != null ? !summary.equals(answer.summary) : answer.summary != null) 105 | return false; 106 | if (questionid != null ? !questionid.equals(answer.questionid) : answer.questionid != null) 107 | return false; 108 | if (answerid != null ? !answerid.equals(answer.answerid) : answer.answerid != null) 109 | return false; 110 | if (authorname != null ? !authorname.equals(answer.authorname) : answer.authorname != null) 111 | return false; 112 | if (authorhash != null ? !authorhash.equals(answer.authorhash) : answer.authorhash != null) 113 | return false; 114 | if (avatar != null ? !avatar.equals(answer.avatar) : answer.avatar != null) return false; 115 | return vote != null ? vote.equals(answer.vote) : answer.vote == null; 116 | 117 | } 118 | 119 | @Override 120 | public int hashCode() { 121 | int result = title != null ? title.hashCode() : 0; 122 | result = 31 * result + (time != null ? time.hashCode() : 0); 123 | result = 31 * result + (summary != null ? summary.hashCode() : 0); 124 | result = 31 * result + (questionid != null ? questionid.hashCode() : 0); 125 | result = 31 * result + (answerid != null ? answerid.hashCode() : 0); 126 | result = 31 * result + (authorname != null ? authorname.hashCode() : 0); 127 | result = 31 * result + (authorhash != null ? authorhash.hashCode() : 0); 128 | result = 31 * result + (avatar != null ? avatar.hashCode() : 0); 129 | result = 31 * result + (vote != null ? vote.hashCode() : 0); 130 | return result; 131 | } 132 | 133 | } 134 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_about_us.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 18 | 19 | 23 | 24 | 30 | 31 | 36 | 37 | 43 | 44 | 45 | 49 | 50 | 51 | 52 | 59 | 60 | 64 | 65 | 74 | 75 | 81 | 82 | 89 | 90 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_answer_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 21 | 22 | 31 | 32 | 37 | 38 | 44 | 45 | 49 | 50 | 61 | 62 | 67 | 68 | 77 | 78 | 90 | 91 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /app/src/main/res/layout-v21/layout_answer_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 22 | 23 | 32 | 33 | 38 | 39 | 45 | 46 | 50 | 51 | 62 | 63 | 68 | 69 | 78 | 79 | 91 | 92 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_feedback.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 19 | 20 | 21 | 22 | 30 | 31 | 37 | 38 | 44 | 45 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 69 | 70 | 81 | 82 | 83 | 84 | 85 | 86 | 91 | 92 | 98 | 99 | 105 | 106 | 114 | 115 | 116 | 117 | 121 | 122 |