From cedaf0241fe8e81fc092c90bdde15cdb6f9f3f4c Mon Sep 17 00:00:00 2001 From: leeeyou Date: Thu, 9 Nov 2017 11:25:55 +0800 Subject: [PATCH 001/150] =?UTF-8?q?jks=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 2 +- keystore/tinker.jks | Bin 0 -> 2182 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 keystore/tinker.jks diff --git a/app/build.gradle b/app/build.gradle index 7a396eb..89f907c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -25,7 +25,7 @@ android { config{ keyAlias 'leeeyoukeystore' keyPassword '123999000' - storeFile file('D:\\doc\\keystore\\windowkeystore\\tinker.jks') + storeFile file('..\\keystore\\tinker.jks') storePassword '123999000' } } diff --git a/keystore/tinker.jks b/keystore/tinker.jks new file mode 100644 index 0000000000000000000000000000000000000000..778cbfd8d4b7643d4296950bf659e5d527bf56ad GIT binary patch literal 2182 zcmb`H_cPp!8pglh-6gWhhUihEL=ARVi;(1~QKMu9(aVam8&+F_kQHTFCOU}{;fRC9 zA^O#W8$D5Wql6tU5pwj160UpZ-Wh+u{o$GU%=61T@AJO%oP0m|4gdh;OyJ)_;ILS1 zm|w6jHY_m6F93VyJKGGC;sAgNM3P{?kQ~f#d1ep>%0W0mkO_d1V5`*dr>+|(2EjWT zx4ax#cj$~XMk$JD!?WB<;ZiYoB#)POT#&RK+|xvB7n=1cWVfEG06s;DH9y|<4{-UC zJN3=CDVf7c;f%iFFY<_$`qB@;+)COKcWeJ=LD?OhJB{OtcMNtOaY-2x7JpV+oY2c1 z(=6*_Dox=_R?>+>^(HmYyjAM0aTS~U*aolb`{LxA-2xj0h2l3-YmWllC|+A%*`CX_ zzD_2vFW)ivgZ>+zw?>c+MN{XBx2&$K3YVar`xf_m?$O26&{YE{q7Ho>15kV=Za}`a zT%nmOi+u`AMXe798vnIfnX*ST<@*upC{cQ?p&(L{b2$KS7vpYIeQLYT`ZaUUhBl48dTl-OmZN@I? za3sR!?&u-aUgsJSB|`Qglv;uxk)fn zm9Vq=zImGZi`8-&X4V?qN&i-5@`Y_i1|IQBK?5Sxd)FxrU6 ztl$>=eJ6^@l?{!GA1ZVe{OOVu?D0teL9Yd~owK#hgLqWIo)~iZDyPN({?nov3iW2G z(2n|qdq#b7nxX5#Tg?~_A`w23s!CFV`-4X2-(w*;&BT5gpKZ@wHS4UCgra+8TL~ij zT8#82s50rTN3exula&ESURBV>jA=n@b6G0NNuE>aw=y3fvVym%&?Ft|${$UgysN65@1U=$hfe?85YR@wch!(Gwkx&jP|bq$7$( zDzwAXsxwZsN1Q0L(0x>$X>1RxDja3l*e)EdTo8ASb$ zSlID>?m~<60L^3p^QYTJ>*BAQU5WJ=>Ho3$5|v${QM$kH4i0$ z2mna};SdrC0<*5@OJ(gI1ya{#Xt%M!x8xw37BJCiA#_ zdz$7$TKeG?lc9raq8H-mrN*WEKvEuNJ^kX00R4z&U1IH++k-0(b+UFgz5K1aZ`NdA zBWZ3w{;u$>Ri*!4;sbX*mTh9Q-=$3N z>*yucPxOn_W2jzautHA#QM+~*R`rjrT#Sf>ZY@d5+x4x9hG}?8_U#z^ewD|b(rL4z zGs0^`$M5n=oX_A!eV~G5Qbk0X!YRlv5PgkBa>+aYpTIylPlen-kwZtak;B!JVeWD1 zg=}3K1PTIRu^3VmDSUQYVGbBCjC*7^&?D(%F|npZN8|yK=FrUe5_~?yvu`*H5d%~#ic?Abs`Yc^# z60+v`5^hjE5{`BE=Gn597{gUxXmf!w(HF}e-p^$@h|Zy>N5%jAz~zvsIk&|gmK9e1 zgq-X0?6XhL+o<*HDg$hI48>!JJ`(J6p{L>Z-uas`F+%a}oTTwmi6}h9zOenHR+@r@ zR(pv(69F%VD~)gE3lDfmJtO3~F8%7sF=?nnAp(`)p|W_{_M& Tymtpur)>HC4O6xIiim#$$E>^O literal 0 HcmV?d00001 From f6f4b8d73bd4719ef2e7305f13b2532e2c819eb5 Mon Sep 17 00:00:00 2001 From: leeeyou Date: Thu, 9 Nov 2017 11:45:58 +0800 Subject: [PATCH 002/150] update ic_launcher --- app/src/main/ic_launcher-web.png | Bin 0 -> 72657 bytes app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 5807 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 3265 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 7638 -> 8417 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 14053 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 21072 bytes 6 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/src/main/ic_launcher-web.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png diff --git a/app/src/main/ic_launcher-web.png b/app/src/main/ic_launcher-web.png new file mode 100644 index 0000000000000000000000000000000000000000..c89f255e36894edebb837a37793ffbf1e6339900 GIT binary patch literal 72657 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4ea5c5f2c57e80a49b7ddc8ee7b2214aa74487e4 GIT binary patch literal 3265 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 56eb0b8807af6cdff60f07232585a76cec6aa70b..fb957186242b2a7ce2b64bb5335775bb7ecac483 100644 GIT binary patch literal 8417 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 D|7!t5 literal 7638 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 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..441001f194e20fc8245ddc2ea905c73de8772083 GIT binary patch literal 14053 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 XlppIlT3Iyl00000NkvXXu0mjf$qvk_ literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..3b30aa15aa3c34d35df250e1ac6a6695fc2356ff GIT binary patch literal 21072 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 Date: Sat, 24 Feb 2018 14:12:33 +0800 Subject: [PATCH 003/150] Optimize fragment code and comments --- .../zhihuribao/view/fragment/BaseFragment.kt | 2 +- .../zhihuribao/view/fragment/OneFragment.kt | 32 +++++++++++-------- .../view/fragment/StoryFragment.java | 8 +++-- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/BaseFragment.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/BaseFragment.kt index 3a59364..4bb4310 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/BaseFragment.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/BaseFragment.kt @@ -4,7 +4,7 @@ import android.support.v4.app.Fragment /** * @author: leeeyou - * @description: 基类 + * @description: fragment base class * @date: 2017/4/26 */ abstract class BaseFragment : Fragment() { diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/OneFragment.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/OneFragment.kt index aea884d..63f69e4 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/OneFragment.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/OneFragment.kt @@ -24,9 +24,11 @@ import java.util.* import javax.inject.Inject /** - * Created by leeeyou on 2017/4/24. + * ClassName: OneFragment + * Description: 【一个】fragment , Kotlin style * - * 【一个】主界面,Kotlin风格 + * Author: leeeyou + * Date: 2017/4/24 13:46 */ class OneFragment : BaseFragment() { @@ -36,15 +38,15 @@ class OneFragment : BaseFragment() { @Inject lateinit var mIdObservable: Observable - internal var mNoMoreDataView: View? = null + private var mNoMoreDataView: View? = null - lateinit var mIdList: Array - var mIndexAdapter: MultipleItemQuickAdapterForOneIndex? = null + private lateinit var mIdList: Array + private var mIndexAdapter: MultipleItemQuickAdapterForOneIndex? = null - var mPosition: Int = 0 + private var mPosition: Int = 0 - override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? = - container!!.inflate(R.layout.fragment_one) + override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): + View? = container!!.inflate(R.layout.fragment_one) override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) @@ -56,15 +58,17 @@ class OneFragment : BaseFragment() { recyclerViewOne?.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) mIndexAdapter = MultipleItemQuickAdapterForOneIndex(null) - mIndexAdapter?.setOnLoadMoreListener { + mIndexAdapter?.setOnLoadMoreListener({ if (mPosition < mIdList.size - 1) { loadIndexData(++mPosition) } - } + }, recyclerViewOne) mIndexAdapter?.openLoadAnimation(BaseQuickAdapter.SCALEIN) + recyclerViewOne.adapter = mIndexAdapter } + //get the ID collection for all categories private fun fetchIdData() { mIdObservable.subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) @@ -116,20 +120,20 @@ class OneFragment : BaseFragment() { private fun parseIndexData(index: Index): MutableList { val tempDataList: MutableList = ArrayList() - //如果是下拉刷新,则添加天气UI + //if it is a drop-down refresh, add the weather UI val isPullToRefresh = mPosition == 0 if (isPullToRefresh) { tempDataList.add(OneIndexMultipleItem(OneIndexMultipleItem.WEATHER, null, index.data.weather)) } - //解析内容 + //parse data val contentList = index.data.content_list for (i in contentList.indices) { tempDataList.add(OneIndexMultipleItem(if (i == 0) OneIndexMultipleItem.TOP else OneIndexMultipleItem.READ, contentList[i], null)) tempDataList.add(OneIndexMultipleItem(OneIndexMultipleItem.BLANK, null, null)) } - //如果当前mPosition的值等于mIdList的最大值,则结束加载更多 + //if the current value of mPosition is equal to the maximum value of mIdList, the end is loaded more val isLoadMoreEnd = mPosition == mIdList.size - 1 if (isLoadMoreEnd) { loadMoreEnd() @@ -147,10 +151,12 @@ class OneFragment : BaseFragment() { fetchIdData() } + private fun loadMoreEnd() { mIndexAdapter?.loadMoreEnd() mIndexAdapter?.setEnableLoadMore(false) if (mNoMoreDataView == null) { + @SuppressWarnings("unchecked") mNoMoreDataView = LayoutInflater.from(context).inflate(R.layout.not_loading, null, false) } mIndexAdapter?.addFooterView(mNoMoreDataView) diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/StoryFragment.java b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/StoryFragment.java index ae18bda..09bdce1 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/StoryFragment.java +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/StoryFragment.java @@ -32,14 +32,18 @@ import rx.schedulers.Schedulers; /** - * 【知乎日报】主界面,Java风格 + * ClassName: StoryFragment + * Description: 【知乎日报】fragment , Java style + * + * Author: leeeyou + * Date: 2017/4/24 13:46 */ public class StoryFragment extends BaseFragment { private RecyclerView mRecyclerView; private StoryAdapter mAdapter; - //加载更多 - 最多加载到哪天的日期列表 + //when loading more, up to the date of the data can be loaded private String[] dateList = new String[7]; private int mDatePosition = 0; private int mMostDate = 7; From 5818f9acb25bcffd3a2f4b78e8b39fd9dbee6aad Mon Sep 17 00:00:00 2001 From: leeeyou Date: Sat, 24 Feb 2018 14:27:42 +0800 Subject: [PATCH 004/150] Optimize Activity code and comments --- .../view/activity/BaseCenterActivity.java | 12 ++++++++---- .../view/activity/BaseOriginalActivity.java | 14 ++++++++++---- .../zhihuribao/view/activity/IndexActivity.kt | 2 +- .../view/activity/StoryDetailActivity.java | 7 ++----- 4 files changed, 21 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/BaseCenterActivity.java b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/BaseCenterActivity.java index 73c1ef9..e819bbc 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/BaseCenterActivity.java +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/BaseCenterActivity.java @@ -9,7 +9,11 @@ import com.xyz.leeeyou.zhihuribao.utils.ToolbarHelper; /** - * 基类,Toolbar样式的BaseActivity,标题能居中显示 + * ClassName: BaseCenterActivity + * Description: The title can be centered + * + * Author: leeeyou + * Date: 2017/8/17 09:19 */ public abstract class BaseCenterActivity extends AppCompatActivity { @@ -36,11 +40,11 @@ public void setContentView(View view) { } private void setCenterTitle(String title) { - TextView toolbar_center_title = swithCenterTextVisible(View.VISIBLE); + TextView toolbar_center_title = switchCenterTextVisible(View.VISIBLE); toolbar_center_title.setText(title); } - private TextView swithCenterTextVisible(int visible) { + private TextView switchCenterTextVisible(int visible) { TextView toolbar_center_title = (TextView) findViewById(R.id.toolbar_center_title); if (toolbar_center_title != null) { toolbar_center_title.setVisibility(visible); @@ -62,7 +66,7 @@ public void setLeftTitleAndHideCenterText(String title) { ToolbarHelper.setLeftTitle(getSupportActionBar(), title); ToolbarHelper.hideHomeAsUp(getSupportActionBar()); - swithCenterTextVisible(View.GONE); + switchCenterTextVisible(View.GONE); } public void setCenterTitleOnly(String title) { diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/BaseOriginalActivity.java b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/BaseOriginalActivity.java index 50456c3..634d921 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/BaseOriginalActivity.java +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/BaseOriginalActivity.java @@ -8,10 +8,11 @@ import com.xyz.leeeyou.zhihuribao.utils.ToolbarHelper; /** - * @author: leeeyou - * @filename: 基类 - * @description: 原生Toolbar样式的BaseActivity - * @date: 2017/8/17 09:19 + * ClassName: BaseOriginalActivity + * Description: Toolbar native style + * + * Author: leeeyou + * Date: 2017/8/17 09:19 */ public abstract class BaseOriginalActivity extends AppCompatActivity { @@ -47,4 +48,9 @@ public void setLeftTitleAndDisplayHomeAsUp(String title) { ToolbarHelper.showHomeAsUp(getSupportActionBar()); } + @Override + public boolean onSupportNavigateUp() { + finish(); + return super.onSupportNavigateUp(); + } } diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt index dcc470d..4492b55 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt @@ -46,7 +46,7 @@ class IndexActivity : BaseOriginalActivity() { } private fun initAdapter() { - //Create a collection object using arrayOf + //create a collection object using arrayOf val fragmentList = arrayOf(StoryFragment(), OneFragment()) val titleList = arrayOf("知乎日报", "一个") diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/StoryDetailActivity.java b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/StoryDetailActivity.java index 6b45b38..e51f710 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/StoryDetailActivity.java +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/StoryDetailActivity.java @@ -44,11 +44,8 @@ protected void onCreate(Bundle savedInstanceState) { String storyTitle = getIntent().getStringExtra("storyTitle"); injectModule(); - - setLeftTitleAndDoNotDisplayHomeAsUp(storyTitle); - + setLeftTitleAndDisplayHomeAsUp(storyTitle); initWebView(); - getStoryDetail(); } @@ -79,7 +76,7 @@ public void getStoryDetail() { @Override public void call() { mMaterialDialog = new MaterialDialog.Builder(StoryDetailActivity.this) - .content("请等待...") + .content("Loading ...") .progress(true, 0) .show(); } From f3747ec5422c979fe6956de3fd24aaa5bc627f0b Mon Sep 17 00:00:00 2001 From: leeeyou Date: Sat, 24 Feb 2018 15:20:10 +0800 Subject: [PATCH 005/150] Optimize code and comments --- .../java/com/xyz/leeeyou/zhihuribao/App.kt | 5 ++- .../zhihuribao/SampleApplicationLike.java | 4 +- .../zhihuribao/adapter/StoryAdapter.kt | 26 ++++++------- .../zhihuribao/adapter/ViewPagerAdapter.kt | 8 +++- ...rOneIndex.kt => MultiItemAdapterForOne.kt} | 26 +++++++------ .../zhihuribao/data/model/one/Author.kt | 3 -- .../zhihuribao/data/model/one/ContentList.kt | 3 -- .../leeeyou/zhihuribao/data/model/one/ID.kt | 22 ++++++++++- .../zhihuribao/data/model/one/Index.kt | 3 -- .../zhihuribao/data/model/one/IndexData.kt | 29 ++++++++++++-- .../zhihuribao/data/model/one/OneIndex.kt | 3 -- .../leeeyou/zhihuribao/data/model/one/Tag.kt | 3 -- .../zhihuribao/data/model/one/Weather.kt | 3 -- .../zhihuribao/data/model/ribao/RiBao.kt | 11 ++++-- .../zhihuribao/data/model/ribao/Story.kt | 3 -- .../data/model/ribao/StoryDetail.kt | 3 -- .../zhihuribao/data/service/OneService.kt | 6 ++- .../zhihuribao/data/service/ServiceFactory.kt | 6 ++- .../data/service/ZhiHuRiBaoService.kt | 6 ++- .../zhihuribao/di/component/OneComponent.kt | 6 ++- .../zhihuribao/di/component/StoryComponent.kt | 6 ++- .../leeeyou/zhihuribao/di/module/OneModule.kt | 8 +++- .../zhihuribao/di/module/StoryModule.kt | 6 ++- .../leeeyou/zhihuribao/utils/HtmlUtils.java | 3 -- .../leeeyou/zhihuribao/utils/InflateUtil.kt | 7 ++-- .../com/xyz/leeeyou/zhihuribao/utils/T.java | 38 +++---------------- .../zhihuribao/utils/ToolbarHelper.java | 8 ++-- ...xMultipleItem.kt => OneMultiItemEntity.kt} | 12 ++++-- .../zhihuribao/view/fragment/OneFragment.kt | 18 ++++----- 29 files changed, 159 insertions(+), 126 deletions(-) rename app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/one/{MultipleItemQuickAdapterForOneIndex.kt => MultiItemAdapterForOne.kt} (64%) rename app/src/main/java/com/xyz/leeeyou/zhihuribao/vi/one/{OneIndexMultipleItem.kt => OneMultiItemEntity.kt} (51%) diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/App.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/App.kt index 72feacb..ead9b7d 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/App.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/App.kt @@ -8,7 +8,10 @@ import com.tencent.bugly.beta.Beta import net.danlew.android.joda.JodaTimeAndroid /** - * Created by leeeyou on 2017/4/21. + * ClassName: App + * + * Author: leeeyou + * Date: 2018/2/24 14:27 */ class App : Application(){ override fun onCreate() { diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/SampleApplicationLike.java b/app/src/main/java/com/xyz/leeeyou/zhihuribao/SampleApplicationLike.java index 4f43e18..c4dc675 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/SampleApplicationLike.java +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/SampleApplicationLike.java @@ -29,7 +29,7 @@ public void onCreate() { super.onCreate(); JodaTimeAndroid.init(getApplication()); - // 调试时,将第三个参数改为true + // Debugging, the third parameter to true Bugly.init(getApplication(), "8f4e37e626", true); } @@ -41,7 +41,7 @@ public void onBaseContextAttached(Context base) { // you must install multiDex whatever tinker is installed! MultiDex.install(base); - // 安装tinker + // install tinker Beta.installTinker(this); } diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/StoryAdapter.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/StoryAdapter.kt index b67207a..b92c1c7 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/StoryAdapter.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/StoryAdapter.kt @@ -9,24 +9,24 @@ import com.xyz.leeeyou.zhihuribao.data.model.ribao.Story import com.xyz.leeeyou.zhihuribao.view.activity.StoryDetailActivity /** - * Created by leeeyou on 16/9/27. + * ClassName: StoryAdapter + * Author: leeeyou + * Date: 2016/9/27 14:45 */ - class StoryAdapter(layoutResId: Int, data: List?) : BaseQuickAdapter(layoutResId, data) { override fun convert(vh: BaseViewHolder, story: Story?) { - if (story != null) { - vh.setText(R.id.tv_story_title, story.title) - .setText(R.id.tv_story_time, story.date) - .setOnClickListener(R.id.rl_item_recommend) { -// mContext = null - mContext.startActivity(Intent(mContext, StoryDetailActivity::class.java) - .putExtra("storyId", story.id) - .putExtra("storyTitle", story.title)) - } + if(story == null) return + + vh.setText(R.id.tv_story_title, story.title) + .setText(R.id.tv_story_time, story.date) + .setOnClickListener(R.id.rl_item_recommend) { + mContext.startActivity(Intent(mContext, StoryDetailActivity::class.java) + .putExtra("storyId", story.id) + .putExtra("storyTitle", story.title)) + } - Glide.with(mContext).load(story.images[0]).into(vh.getView(R.id.iv_story_image)) - } + Glide.with(mContext).load(story.images[0]).into(vh.getView(R.id.iv_story_image)) } } diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/ViewPagerAdapter.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/ViewPagerAdapter.kt index 4849c7e..9cee1df 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/ViewPagerAdapter.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/ViewPagerAdapter.kt @@ -6,13 +6,17 @@ import android.support.v4.app.FragmentStatePagerAdapter import com.xyz.leeeyou.zhihuribao.view.fragment.BaseFragment /** - * Created by leeeyou on 2017/4/26. + * ClassName: ViewPagerAdapter + * Description: main activity adapter + * + * Author: leeeyou + * Date: 2018/2/24 15:05 */ class ViewPagerAdapter(fm: FragmentManager, private val mFragmentList: Array, private val titleList: Array) : FragmentStatePagerAdapter(fm) { - var mCurrentFragment: BaseFragment? = null + private var mCurrentFragment: BaseFragment? = null override fun getItem(position: Int): Fragment = mFragmentList[position] diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/one/MultipleItemQuickAdapterForOneIndex.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/one/MultiItemAdapterForOne.kt similarity index 64% rename from app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/one/MultipleItemQuickAdapterForOneIndex.kt rename to app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/one/MultiItemAdapterForOne.kt index bacd1ad..6a8c256 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/one/MultipleItemQuickAdapterForOneIndex.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/one/MultiItemAdapterForOne.kt @@ -4,27 +4,31 @@ import com.bumptech.glide.Glide import com.chad.library.adapter.base.BaseMultiItemQuickAdapter import com.chad.library.adapter.base.BaseViewHolder import com.xyz.leeeyou.zhihuribao.R -import com.xyz.leeeyou.zhihuribao.vi.one.OneIndexMultipleItem +import com.xyz.leeeyou.zhihuribao.vi.one.OneMultiItemEntity /** - * Created by leeeyou on 2017/4/25. + * ClassName: MultiItemAdapterForOne + * Description: [ One ] module, multi-layout adapter + * + * Author: leeeyou + * Date: 2018/2/24 14:33 */ -class MultipleItemQuickAdapterForOneIndex(data: MutableList?) : BaseMultiItemQuickAdapter(data) { +class MultiItemAdapterForOne(data: MutableList?) : BaseMultiItemQuickAdapter(data) { init { - addItemType(OneIndexMultipleItem.BLANK, R.layout.item_one_index_blank) - addItemType(OneIndexMultipleItem.WEATHER, R.layout.item_one_index_weather) - addItemType(OneIndexMultipleItem.TOP, R.layout.item_one_index_top) - addItemType(OneIndexMultipleItem.READ, R.layout.item_one_index_read) + addItemType(OneMultiItemEntity.BLANK, R.layout.item_one_index_blank) + addItemType(OneMultiItemEntity.WEATHER, R.layout.item_one_index_weather) + addItemType(OneMultiItemEntity.TOP, R.layout.item_one_index_top) + addItemType(OneMultiItemEntity.READ, R.layout.item_one_index_read) } - override fun convert(vh: BaseViewHolder, item: OneIndexMultipleItem) { + override fun convert(vh: BaseViewHolder, item: OneMultiItemEntity) { when (item.itemType) { - OneIndexMultipleItem.WEATHER -> { + OneMultiItemEntity.WEATHER -> { vh.setText(R.id.tv_date, item.weather?.date) .setText(R.id.tv_climate, item.weather?.climate + "," + item.weather?.city_name) } - OneIndexMultipleItem.TOP -> { + OneMultiItemEntity.TOP -> { Glide.with(mContext).load(item.indexData?.img_url).into(vh.getView(R.id.img)) vh.setText(R.id.tv_author, item.indexData?.title + " | " + item.indexData?.pic_info) .setText(R.id.tv_forward, item.indexData?.forward) @@ -33,7 +37,7 @@ class MultipleItemQuickAdapterForOneIndex(data: MutableList { + OneMultiItemEntity.READ -> { Glide.with(mContext).load(item.indexData?.img_url).into(vh.getView(R.id.img)) vh.setText(R.id.tv_title, item.indexData?.title) .setText(R.id.tv_author_name, "文/" + item.indexData?.author?.user_name) diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Author.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Author.kt index 3dc41f9..e3321ce 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Author.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Author.kt @@ -1,8 +1,5 @@ package com.xyz.leeeyou.zhihuribao.data.model.one -/** - * Created by leeeyou on 2017/4/24. - */ data class Author( var user_id: String, var user_name: String, diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/ContentList.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/ContentList.kt index eff302d..66a90b6 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/ContentList.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/ContentList.kt @@ -1,6 +1,3 @@ package com.xyz.leeeyou.zhihuribao.data.model.one -/** - * Created by leeeyou on 2017/4/24. - */ data class ContentList(var contentList: Array) \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/ID.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/ID.kt index f23bb06..57c9af9 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/ID.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/ID.kt @@ -1,6 +1,26 @@ package com.xyz.leeeyou.zhihuribao.data.model.one +import java.util.* + /** * Created by leeeyou on 2017/4/24. */ -data class ID(var res: Int, var data: Array) \ No newline at end of file +data class ID(var res: Int, var data: Array) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as ID + + if (res != other.res) return false + if (!Arrays.equals(data, other.data)) return false + + return true + } + + override fun hashCode(): Int { + var result = res + result = 31 * result + Arrays.hashCode(data) + return result + } +} \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Index.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Index.kt index 5bbfb86..5080dab 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Index.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Index.kt @@ -1,6 +1,3 @@ package com.xyz.leeeyou.zhihuribao.data.model.one -/** - * Created by leeeyou on 2017/4/24. - */ data class Index(var res: Int, var data: IndexData) \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/IndexData.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/IndexData.kt index 95d9710..1a9155d 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/IndexData.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/IndexData.kt @@ -1,9 +1,30 @@ package com.xyz.leeeyou.zhihuribao.data.model.one -/** - * Created by leeeyou on 2017/4/24. - */ +import java.util.* + data class IndexData(var id: String, var date: String, var weather: Weather, - var content_list: Array) + var content_list: Array) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as IndexData + + if (id != other.id) return false + if (date != other.date) return false + if (weather != other.weather) return false + if (!Arrays.equals(content_list, other.content_list)) return false + + return true + } + + override fun hashCode(): Int { + var result = id.hashCode() + result = 31 * result + date.hashCode() + result = 31 * result + weather.hashCode() + result = 31 * result + Arrays.hashCode(content_list) + return result + } +} diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/OneIndex.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/OneIndex.kt index 7ff3995..856e002 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/OneIndex.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/OneIndex.kt @@ -1,8 +1,5 @@ package com.xyz.leeeyou.zhihuribao.data.model.one -/** - * Created by leeeyou on 2017/4/24. - */ data class OneIndex( var id: String, var category: String, diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Tag.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Tag.kt index 0f8db2d..f7ae41c 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Tag.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Tag.kt @@ -1,6 +1,3 @@ package com.xyz.leeeyou.zhihuribao.data.model.one -/** - * Created by leeeyou on 2017/4/24. - */ data class Tag(var id: String, var title: String) \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Weather.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Weather.kt index 4d7cc45..f9dde4c 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Weather.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Weather.kt @@ -1,8 +1,5 @@ package com.xyz.leeeyou.zhihuribao.data.model.one -/** - * Created by leeeyou on 2017/4/25. - */ data class Weather( var city_name: String, var date: String, diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/RiBao.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/RiBao.kt index 344c418..8973f55 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/RiBao.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/RiBao.kt @@ -1,11 +1,14 @@ package com.xyz.leeeyou.zhihuribao.data.model.ribao /** - * Created by leeeyou on 2017/4/21. + * ClassName: + * Description: The data class is a very powerful class that + * lets you avoid creating boilerplate code in Java + * that holds POJOs that are state-controlled but have a very simple operation. * - * getLatestRiBao返回的数据结构 + * They usually only provide simple getters and setters for accessing their properties. * - * 数据类是一种非常强大的类,它可以让你避免创建Java中的用于保存状态但又操作非常简单的POJO的模版代码。 - * 它们通常只提供了用于访问它们属性的简单的getter 和setter。 + * Author: leeeyou + * Date: 2017/4/21 15:07 */ data class RiBao(var date: String, var stories: List) \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/Story.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/Story.kt index 59929be..2c9c531 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/Story.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/Story.kt @@ -1,8 +1,5 @@ package com.xyz.leeeyou.zhihuribao.data.model.ribao -/** - * Created by leeeyou on 2017/4/21. - */ data class Story(var images: List, var type: Int, var id: Int, diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/StoryDetail.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/StoryDetail.kt index 8f0e1c5..c04dc58 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/StoryDetail.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/StoryDetail.kt @@ -1,8 +1,5 @@ package com.xyz.leeeyou.zhihuribao.data.model.ribao -/** - * Created by leeeyou on 2017/4/21. - */ data class StoryDetail(var body: String, var image_source: String, var title: String, diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/OneService.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/OneService.kt index 4dc5ce7..7cb26e6 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/OneService.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/OneService.kt @@ -7,9 +7,11 @@ import retrofit.http.Path import rx.Observable /** - * Created by leeeyou on 2017/4/24. + * ClassName:OneService + * Description: [ One ] module service * - * restful + * Author: leeeyou + * Date: 2018/4/24 15:14 */ interface OneService { @GET("/api/onelist/{id}/0?cchannel=wdj&version=4.0.2&uuid=ffffffff-a90e-706a-63f7-ccf973aae5ee&platform=android") diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/ServiceFactory.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/ServiceFactory.kt index e0fb81f..91b7c14 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/ServiceFactory.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/ServiceFactory.kt @@ -5,7 +5,11 @@ import retrofit.Retrofit import retrofit.RxJavaCallAdapterFactory /** - * Created by leeeyou on 2017/4/24. + * ClassName: ServiceFactory + * Description: The factory class mainly offers two kinds of Retrofit services, Rx mode and normal mode + * + * Author: leeeyou + * Date: 2018/4/24 15:11 */ class ServiceFactory { companion object { diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/ZhiHuRiBaoService.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/ZhiHuRiBaoService.kt index 4af34d2..390f57f 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/ZhiHuRiBaoService.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/ZhiHuRiBaoService.kt @@ -7,7 +7,11 @@ import retrofit.http.Path import rx.Observable /** - * Created by leeeyou on 2017/4/24. + * ClassName: ZhiHuRiBaoService + * Description: [ ZhiHuRiBao ] module service + * + * Author: leeeyou + * Date: 2018/4/24 15:14 */ interface ZhiHuRiBaoService { @GET("/api/4/news/before/{dateTime}") diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/OneComponent.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/OneComponent.kt index 0303e89..3a29d1e 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/OneComponent.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/OneComponent.kt @@ -6,7 +6,11 @@ import dagger.Component import javax.inject.Singleton /** - * Created by leeeyou on 2017/4/24. + * ClassName: OneComponent + * Description: [ One ] module Component + * + * Author: leeeyou + * Date: 2018/2/24 15:15 */ @Singleton @Component(modules = arrayOf(OneModule::class)) diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/StoryComponent.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/StoryComponent.kt index dc1eac4..24d72e8 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/StoryComponent.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/StoryComponent.kt @@ -7,7 +7,11 @@ import dagger.Component import javax.inject.Singleton /** - * Created by leeeyou on 2017/4/24. + * ClassName: StoryComponent + * Description: [ Story ] module Component + * + * Author: leeeyou + * Date: 2018/2/24 15:15 */ @Singleton @Component(modules = arrayOf(StoryModule::class)) diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/OneModule.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/OneModule.kt index 655ddb2..4a94096 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/OneModule.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/OneModule.kt @@ -10,7 +10,11 @@ import rx.Observable import javax.inject.Singleton /** - * Created by leeeyou on 2017/4/24. + * ClassName: OneModule + * Description: + * + * Author: leeeyou + * Date: 2018/2/24 15:16 */ @Singleton @Module @@ -35,7 +39,7 @@ class OneModule { @Singleton @Provides - fun ProvideIdList(): Observable { + fun provideIdList(): Observable { return ServiceFactory.Companion .createRxRetrofitService(OneService::class.java, endPoint) .getIdList() diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/StoryModule.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/StoryModule.kt index ac9d6b5..cf8d180 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/StoryModule.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/StoryModule.kt @@ -10,7 +10,11 @@ import rx.Observable import javax.inject.Singleton /** - * Created by leeeyou on 2017/4/24. + * ClassName: StoryModule + * Description: + * + * Author: leeeyou + * Date: 2018/2/24 15:16 */ @Singleton @Module diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/utils/HtmlUtils.java b/app/src/main/java/com/xyz/leeeyou/zhihuribao/utils/HtmlUtils.java index 7eb827b..a5aadcc 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/utils/HtmlUtils.java +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/utils/HtmlUtils.java @@ -2,9 +2,6 @@ import java.util.List; -/** - * Created by diff on 2016/2/4. - */ public class HtmlUtils { public static String structHtml(String oriStr, List cssList) { StringBuilder htmlString = new StringBuilder(""); diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/utils/InflateUtil.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/utils/InflateUtil.kt index 00fcb30..9a5a30f 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/utils/InflateUtil.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/utils/InflateUtil.kt @@ -5,9 +5,10 @@ import android.view.View import android.view.ViewGroup /** - * Created by leeeyou on 2017/4/24. - * - * 扩展inflate方法 + * Description: Expand the inflate method + * + * Author: leeeyou + * Date: 2017/4/24 15:18 */ fun ViewGroup.inflate(layoutId: Int): View = LayoutInflater.from(context).inflate(layoutId, this, false) \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/utils/T.java b/app/src/main/java/com/xyz/leeeyou/zhihuribao/utils/T.java index d6d5648..d5cdf59 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/utils/T.java +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/utils/T.java @@ -4,7 +4,11 @@ import android.widget.Toast; /** - * Toast统一管理类 + * ClassName: T + * Description: Toast unified management class + * + * Author: leeeyou + * Date: 2018/2/24 15:19 */ public class T { @@ -15,10 +19,6 @@ private T() { public static boolean isShow = true; - /** - * 短时间显示Toast - * - */ public static void showShort(Context context, CharSequence message) { if (isShow) { if (context != null && message != null) { @@ -27,10 +27,6 @@ public static void showShort(Context context, CharSequence message) { } } - /** - * 短时间显示Toast - * - */ public static void showShort(Context context, int message) { if (isShow) { if (context != null) { @@ -39,10 +35,6 @@ public static void showShort(Context context, int message) { } } - /** - * 长时间显示Toast - * - */ public static void showLong(Context context, CharSequence message) { if (isShow) { if (context != null && message != null) { @@ -51,12 +43,6 @@ public static void showLong(Context context, CharSequence message) { } } - /** - * 长时间显示Toast - * - * @param context - * @param message - */ public static void showLong(Context context, int message) { if (isShow) { if (context != null) { @@ -65,13 +51,6 @@ public static void showLong(Context context, int message) { } } - /** - * 自定义显示Toast时间 - * - * @param context - * @param message - * @param duration - */ public static void show(Context context, CharSequence message, int duration) { if (isShow) { if (context != null && message != null) @@ -79,13 +58,6 @@ public static void show(Context context, CharSequence message, int duration) { } } - /** - * 自定义显示Toast时间 - * - * @param context - * @param message - * @param duration - */ public static void show(Context context, int message, int duration) { if (isShow) { if (context != null) { diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/utils/ToolbarHelper.java b/app/src/main/java/com/xyz/leeeyou/zhihuribao/utils/ToolbarHelper.java index 04fb9f5..6db0aff 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/utils/ToolbarHelper.java +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/utils/ToolbarHelper.java @@ -13,9 +13,11 @@ import com.xyz.leeeyou.zhihuribao.R; /** - * Created by leeeyou on 16/5/10. - *

- * Toolbar辅助类,抽取Original和Center中的公共方法 + * ClassName: ToolbarHelper + * Description: Toolbar helper class to extract public methods from Original and Center + * + * Author: leeeyou + * Date: 2016/5/10 15:18 */ public class ToolbarHelper { diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/vi/one/OneIndexMultipleItem.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/vi/one/OneMultiItemEntity.kt similarity index 51% rename from app/src/main/java/com/xyz/leeeyou/zhihuribao/vi/one/OneIndexMultipleItem.kt rename to app/src/main/java/com/xyz/leeeyou/zhihuribao/vi/one/OneMultiItemEntity.kt index 3062169..3e50079 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/vi/one/OneIndexMultipleItem.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/vi/one/OneMultiItemEntity.kt @@ -5,11 +5,15 @@ import com.xyz.leeeyou.zhihuribao.data.model.one.OneIndex import com.xyz.leeeyou.zhihuribao.data.model.one.Weather /** - * Created by leeeyou on 2017/4/25. + * ClassName: OneMultiItemEntity + * Description: [ One ] module, multi-layout entity class + * + * Author: leeeyou + * Date: 2018/2/24 14:31 */ -class OneIndexMultipleItem(private val itemType: Int, - val indexData: OneIndex? = null, - val weather: Weather? = null) : MultiItemEntity { +class OneMultiItemEntity(private val itemType: Int, + val indexData: OneIndex? = null, + val weather: Weather? = null) : MultiItemEntity { companion object { val BLANK = -1 val WEATHER = 0 diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/OneFragment.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/OneFragment.kt index 63f69e4..c3ea9d5 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/OneFragment.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/OneFragment.kt @@ -7,13 +7,13 @@ import android.view.View import android.view.ViewGroup import com.chad.library.adapter.base.BaseQuickAdapter import com.xyz.leeeyou.zhihuribao.R -import com.xyz.leeeyou.zhihuribao.adapter.one.MultipleItemQuickAdapterForOneIndex +import com.xyz.leeeyou.zhihuribao.adapter.one.MultiItemAdapterForOne import com.xyz.leeeyou.zhihuribao.data.model.one.ID import com.xyz.leeeyou.zhihuribao.data.model.one.Index import com.xyz.leeeyou.zhihuribao.di.component.DaggerOneComponent import com.xyz.leeeyou.zhihuribao.di.module.OneModule import com.xyz.leeeyou.zhihuribao.utils.inflate -import com.xyz.leeeyou.zhihuribao.vi.one.OneIndexMultipleItem +import com.xyz.leeeyou.zhihuribao.vi.one.OneMultiItemEntity import com.xyz.leeeyou.zhihuribao.view.activity.IndexActivity import kotlinx.android.synthetic.main.fragment_one.* import rx.Observable @@ -41,7 +41,7 @@ class OneFragment : BaseFragment() { private var mNoMoreDataView: View? = null private lateinit var mIdList: Array - private var mIndexAdapter: MultipleItemQuickAdapterForOneIndex? = null + private var mIndexAdapter: MultiItemAdapterForOne? = null private var mPosition: Int = 0 @@ -57,7 +57,7 @@ class OneFragment : BaseFragment() { private fun initAdapter() { recyclerViewOne?.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) - mIndexAdapter = MultipleItemQuickAdapterForOneIndex(null) + mIndexAdapter = MultiItemAdapterForOne(null) mIndexAdapter?.setOnLoadMoreListener({ if (mPosition < mIdList.size - 1) { loadIndexData(++mPosition) @@ -117,20 +117,20 @@ class OneFragment : BaseFragment() { }) } - private fun parseIndexData(index: Index): MutableList { - val tempDataList: MutableList = ArrayList() + private fun parseIndexData(index: Index): MutableList { + val tempDataList: MutableList = ArrayList() //if it is a drop-down refresh, add the weather UI val isPullToRefresh = mPosition == 0 if (isPullToRefresh) { - tempDataList.add(OneIndexMultipleItem(OneIndexMultipleItem.WEATHER, null, index.data.weather)) + tempDataList.add(OneMultiItemEntity(OneMultiItemEntity.WEATHER, null, index.data.weather)) } //parse data val contentList = index.data.content_list for (i in contentList.indices) { - tempDataList.add(OneIndexMultipleItem(if (i == 0) OneIndexMultipleItem.TOP else OneIndexMultipleItem.READ, contentList[i], null)) - tempDataList.add(OneIndexMultipleItem(OneIndexMultipleItem.BLANK, null, null)) + tempDataList.add(OneMultiItemEntity(if (i == 0) OneMultiItemEntity.TOP else OneMultiItemEntity.READ, contentList[i], null)) + tempDataList.add(OneMultiItemEntity(OneMultiItemEntity.BLANK, null, null)) } //if the current value of mPosition is equal to the maximum value of mIdList, the end is loaded more From 1c163623f3e709d3cf706211f0dd563f905f9246 Mon Sep 17 00:00:00 2001 From: leeeyou Date: Sat, 24 Feb 2018 15:24:00 +0800 Subject: [PATCH 006/150] Optimize comments --- app/build.gradle | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 89f907c..b76b732 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,7 +16,7 @@ android { versionName "1.1.4" ndk { - //设置支持的SO库架构 + //Set up a supported SO library architecture abiFilters 'armeabi'//, 'x86'//, 'armeabi-v7a', 'x86_64', 'arm64-v8a' } } @@ -33,8 +33,8 @@ android { buildTypes { release { minifyEnabled true - zipAlignEnabled true //是否优化apk文件,将apk文件中未压缩的数据在4个字节边界上对齐 - shrinkResources true //是否去除无用资源 + zipAlignEnabled true //Whether to optimize the apk file, the uncompressed data in the apk file aligned on the 4-byte boundary + shrinkResources true //Whether to remove useless resources proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.config } @@ -73,8 +73,8 @@ dependencies { compile 'in.srain.cube:ultra-ptr:1.0.11' - compile "com.android.support:multidex:1.0.1" // 多dex配置 + compile "com.android.support:multidex:1.0.1" compile 'com.tencent.bugly:crashreport_upgrade:1.3.1' - compile 'com.tencent.bugly:nativecrashreport:latest.release' //其中latest.release指代最新版本号,也可以指定明确的版本号,例如2.2.0 + compile 'com.tencent.bugly:nativecrashreport:latest.release' //The latest.release refers to the latest version number, you can also specify a clear version number, for example, 2.2.0 } \ No newline at end of file From e40756d420f94fd0d280a8703c0c808cc3467468 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Tue, 26 Jun 2018 16:55:31 +0800 Subject: [PATCH 007/150] update kotlin version --- app/build.gradle | 12 +++++++----- build.gradle | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index b76b732..db764fd 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,12 +17,12 @@ android { ndk { //Set up a supported SO library architecture - abiFilters 'armeabi'//, 'x86'//, 'armeabi-v7a', 'x86_64', 'arm64-v8a' + abiFilters 'armeabi', 'x86'//, 'armeabi-v7a', 'x86_64', 'arm64-v8a' } } - signingConfigs{ - config{ + signingConfigs { + config { keyAlias 'leeeyoukeystore' keyPassword '123999000' storeFile file('..\\keystore\\tinker.jks') @@ -33,7 +33,8 @@ android { buildTypes { release { minifyEnabled true - zipAlignEnabled true //Whether to optimize the apk file, the uncompressed data in the apk file aligned on the 4-byte boundary + zipAlignEnabled true + //Whether to optimize the apk file, the uncompressed data in the apk file aligned on the 4-byte boundary shrinkResources true //Whether to remove useless resources proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.config @@ -75,6 +76,7 @@ dependencies { compile "com.android.support:multidex:1.0.1" compile 'com.tencent.bugly:crashreport_upgrade:1.3.1' - compile 'com.tencent.bugly:nativecrashreport:latest.release' //The latest.release refers to the latest version number, you can also specify a clear version number, for example, 2.2.0 + compile 'com.tencent.bugly:nativecrashreport:latest.release' + //The latest.release refers to the latest version number, you can also specify a clear version number, for example, 2.2.0 } \ No newline at end of file diff --git a/build.gradle b/build.gradle index 0078b4c..f4dea65 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.1.0' + ext.kotlin_version = '1.2.50' repositories { jcenter() } From 0c9bb04016b1c8d8c8afafc26cc34e3a7db86fe7 Mon Sep 17 00:00:00 2001 From: leeeyou Date: Tue, 4 Sep 2018 23:27:01 +0800 Subject: [PATCH 008/150] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 2 +- build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index db764fd..5ba9fd0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -70,7 +70,7 @@ dependencies { compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.14' compile 'net.danlew:android.joda:2.9.4.1' compile 'com.afollestad.material-dialogs:core:0.9.0.2' - compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" + compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" compile 'in.srain.cube:ultra-ptr:1.0.11' diff --git a/build.gradle b/build.gradle index f4dea65..987b15c 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.2.50' + ext.kotlin_version = '1.2.61' repositories { jcenter() } From 3ab112bc0326c31f9a51c8f9782592366ba9838c Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Wed, 12 Dec 2018 16:42:17 +0800 Subject: [PATCH 009/150] Upgrade gradle version number --- build.gradle | 10 ++++++---- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index 987b15c..1213a98 100644 --- a/build.gradle +++ b/build.gradle @@ -1,14 +1,15 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.2.61' + ext.kotlin_version = '1.3.0' repositories { jcenter() + google() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.2.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath "com.tencent.bugly:tinker-support:1.0.8" + classpath "com.tencent.bugly:tinker-support:1.1.2" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } @@ -16,8 +17,9 @@ buildscript { allprojects { repositories { + mavenCentral() + google() jcenter() - maven { url "https://jitpack.io/" } } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2f1f7b1..704f40f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Jul 17 10:41:25 CST 2017 +#Wed Dec 12 15:08:52 CST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip From 944a931da081efae449b6b99eb4423972122579b Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Wed, 12 Dec 2018 16:42:46 +0800 Subject: [PATCH 010/150] Upgrade BaseRecyclerViewAdapterHelper version number --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 5ba9fd0..4ed48e9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -67,7 +67,7 @@ dependencies { compile 'com.ogaclejapan.smarttablayout:library:1.6.1@aar' - compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.14' + compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.44' compile 'net.danlew:android.joda:2.9.4.1' compile 'com.afollestad.material-dialogs:core:0.9.0.2' compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" From e0d40768ed07b47d83c01bc23127a23c09feb313 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Wed, 12 Dec 2018 16:43:22 +0800 Subject: [PATCH 011/150] Update One code --- .../zhihuribao/di/component/OneComponent.kt | 2 +- .../leeeyou/zhihuribao/di/module/OneModule.kt | 16 +++--- .../zhihuribao/view/fragment/OneFragment.kt | 54 +++++++++---------- 3 files changed, 37 insertions(+), 35 deletions(-) diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/OneComponent.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/OneComponent.kt index 3a29d1e..e7aa697 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/OneComponent.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/OneComponent.kt @@ -13,7 +13,7 @@ import javax.inject.Singleton * Date: 2018/2/24 15:15 */ @Singleton -@Component(modules = arrayOf(OneModule::class)) +@Component(modules = [OneModule::class]) interface OneComponent { fun inject(oneFragment: OneFragment) } \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/OneModule.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/OneModule.kt index 4a94096..32dfca4 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/OneModule.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/OneModule.kt @@ -11,15 +11,17 @@ import javax.inject.Singleton /** * ClassName: OneModule - * Description: - * - * Author: leeeyou - * Date: 2018/2/24 15:16 + * Description: + * + * Author: leeeyou + * Date: 2018/2/24 15:16 */ + +private const val endPoint = "http://v3.wufazhuce.com:8000/" + @Singleton @Module class OneModule { - private val endPoint = "http://v3.wufazhuce.com:8000/" var id: Int = 0 @@ -32,7 +34,7 @@ class OneModule { @Singleton @Provides fun provideOne(): Observable { - return ServiceFactory.Companion + return ServiceFactory .createRxRetrofitService(OneService::class.java, endPoint) .getIndexList(id) } @@ -40,7 +42,7 @@ class OneModule { @Singleton @Provides fun provideIdList(): Observable { - return ServiceFactory.Companion + return ServiceFactory .createRxRetrofitService(OneService::class.java, endPoint) .getIdList() } diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/OneFragment.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/OneFragment.kt index c3ea9d5..2775bb3 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/OneFragment.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/OneFragment.kt @@ -38,33 +38,37 @@ class OneFragment : BaseFragment() { @Inject lateinit var mIdObservable: Observable - private var mNoMoreDataView: View? = null - private lateinit var mIdList: Array - private var mIndexAdapter: MultiItemAdapterForOne? = null - + private lateinit var mIndexAdapter: MultiItemAdapterForOne private var mPosition: Int = 0 - override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): - View? = container!!.inflate(R.layout.fragment_one) + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return container?.inflate(R.layout.fragment_one) + } override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) - initAdapter() + initRecyclerView() updateData() } - private fun initAdapter() { - recyclerViewOne?.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) + private fun initRecyclerView() { + initLayoutManager() + initAdapter() + } + private fun initLayoutManager() { + recyclerViewOne.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) + } + + private fun initAdapter() { mIndexAdapter = MultiItemAdapterForOne(null) - mIndexAdapter?.setOnLoadMoreListener({ + mIndexAdapter.setOnLoadMoreListener({ if (mPosition < mIdList.size - 1) { loadIndexData(++mPosition) } }, recyclerViewOne) - mIndexAdapter?.openLoadAnimation(BaseQuickAdapter.SCALEIN) - + mIndexAdapter.openLoadAnimation(BaseQuickAdapter.SCALEIN) recyclerViewOne.adapter = mIndexAdapter } @@ -106,13 +110,12 @@ class OneFragment : BaseFragment() { (activity as IndexActivity).refreshComplete() val indexData = parseIndexData(it) - val isPullToRefresh = mPosition == 0 if (isPullToRefresh) { - mIndexAdapter?.setNewData(indexData) + mIndexAdapter.setNewData(indexData) } else { - mIndexAdapter?.addData(indexData) - mIndexAdapter?.loadMoreComplete() + mIndexAdapter.addData(indexData) + mIndexAdapter.loadMoreComplete() } }) } @@ -128,8 +131,8 @@ class OneFragment : BaseFragment() { //parse data val contentList = index.data.content_list - for (i in contentList.indices) { - tempDataList.add(OneMultiItemEntity(if (i == 0) OneMultiItemEntity.TOP else OneMultiItemEntity.READ, contentList[i], null)) + for (contentIndex in contentList.indices) { + tempDataList.add(OneMultiItemEntity(if (contentIndex == 0) OneMultiItemEntity.TOP else OneMultiItemEntity.READ, contentList[contentIndex], null)) tempDataList.add(OneMultiItemEntity(OneMultiItemEntity.BLANK, null, null)) } @@ -145,21 +148,18 @@ class OneFragment : BaseFragment() { override fun checkCanDoRefresh(): Boolean = !recyclerViewOne.canScrollVertically(-1) override fun updateData() { - mIndexAdapter?.setEnableLoadMore(true) - mIndexAdapter?.removeAllFooterView() + mIndexAdapter.setEnableLoadMore(true) + mIndexAdapter.removeAllFooterView() DaggerOneComponent.builder().oneModule(OneModule()).build().inject(this) fetchIdData() } - private fun loadMoreEnd() { - mIndexAdapter?.loadMoreEnd() - mIndexAdapter?.setEnableLoadMore(false) - if (mNoMoreDataView == null) { - @SuppressWarnings("unchecked") - mNoMoreDataView = LayoutInflater.from(context).inflate(R.layout.not_loading, null, false) + with(View.inflate(context, R.layout.not_loading, null)) { + mIndexAdapter.loadMoreEnd() + mIndexAdapter.setEnableLoadMore(false) + mIndexAdapter.addFooterView(this) } - mIndexAdapter?.addFooterView(mNoMoreDataView) } } \ No newline at end of file From 01b13e1c27c2c6235fe0ab0c52a61a733d8a9028 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Wed, 12 Dec 2018 16:59:38 +0800 Subject: [PATCH 012/150] Upgrade sdk version number --- app/build.gradle | 48 +++++++++---------- .../view/activity/StoryDetailActivity.java | 15 +++--- 2 files changed, 31 insertions(+), 32 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 4ed48e9..ff3ac77 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,13 +5,13 @@ apply plugin: 'kotlin-android-extensions' apply from: 'tinker-support.gradle' android { - compileSdkVersion 25 - buildToolsVersion "25.0.2" + compileSdkVersion 28 + buildToolsVersion '28.0.3' defaultConfig { applicationId "com.xyz.leeeyou.zhihuribao" minSdkVersion 15 - targetSdkVersion 25 + targetSdkVersion 28 versionCode 2 versionName "1.1.4" @@ -47,36 +47,36 @@ android { } dependencies { - compile fileTree(include: ['*.jar'], dir: 'libs') - testCompile 'junit:junit:4.12' - compile 'com.android.support:appcompat-v7:25.1.0' - compile 'com.android.support:design:25.1.0' + implementation fileTree(include: ['*.jar'], dir: 'libs') + testImplementation 'junit:junit:4.12' + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support:design:28.0.0' - compile 'com.google.dagger:dagger:2.4' + implementation 'com.google.dagger:dagger:2.4' kapt 'com.google.dagger:dagger-compiler:2.4' - provided 'org.glassfish:javax.annotation:10.0-b28' + compileOnly 'org.glassfish:javax.annotation:10.0-b28' - compile 'com.squareup.retrofit:retrofit:2.0.0-beta2' - compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2' - compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2' + implementation 'com.squareup.retrofit:retrofit:2.0.0-beta2' + implementation 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2' + implementation 'com.squareup.retrofit:converter-gson:2.0.0-beta2' - compile 'io.reactivex:rxandroid:1.0.1' - compile 'io.reactivex:rxkotlin:1.0.0' + implementation 'io.reactivex:rxandroid:1.0.1' + implementation 'io.reactivex:rxkotlin:1.0.0' - compile 'com.github.bumptech.glide:glide:3.7.0' + implementation 'com.github.bumptech.glide:glide:3.7.0' - compile 'com.ogaclejapan.smarttablayout:library:1.6.1@aar' + implementation 'com.ogaclejapan.smarttablayout:library:1.6.1@aar' - compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.44' - compile 'net.danlew:android.joda:2.9.4.1' - compile 'com.afollestad.material-dialogs:core:0.9.0.2' - compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" + implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.44' + implementation 'net.danlew:android.joda:2.9.4.1' + implementation 'com.afollestad.material-dialogs:core:0.9.0.2' + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - compile 'in.srain.cube:ultra-ptr:1.0.11' + implementation 'in.srain.cube:ultra-ptr:1.0.11' - compile "com.android.support:multidex:1.0.1" - compile 'com.tencent.bugly:crashreport_upgrade:1.3.1' - compile 'com.tencent.bugly:nativecrashreport:latest.release' + implementation "com.android.support:multidex:1.0.1" + implementation 'com.tencent.bugly:crashreport_upgrade:1.3.1' + implementation 'com.tencent.bugly:nativecrashreport:latest.release' //The latest.release refers to the latest version number, you can also specify a clear version number, for example, 2.2.0 } \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/StoryDetailActivity.java b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/StoryDetailActivity.java index e51f710..21f9950 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/StoryDetailActivity.java +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/StoryDetailActivity.java @@ -3,7 +3,6 @@ import android.os.Bundle; import android.webkit.WebView; -import com.afollestad.materialdialogs.MaterialDialog; import com.xyz.leeeyou.zhihuribao.R; import com.xyz.leeeyou.zhihuribao.data.model.ribao.StoryDetail; import com.xyz.leeeyou.zhihuribao.di.component.DaggerStoryComponent; @@ -31,7 +30,7 @@ public class StoryDetailActivity extends BaseOriginalActivity { private StoryComponent storyComponent; private StoryModule storyModule; - private MaterialDialog mMaterialDialog; +// private MaterialDialog mMaterialDialog; @Override protected void onCreate(Bundle savedInstanceState) { @@ -75,10 +74,10 @@ public void getStoryDetail() { .doOnSubscribe(new Action0() { @Override public void call() { - mMaterialDialog = new MaterialDialog.Builder(StoryDetailActivity.this) - .content("Loading ...") - .progress(true, 0) - .show(); +// mMaterialDialog = new MaterialDialog.Builder(StoryDetailActivity.this) +// .content("Loading ...") +// .progress(true, 0) +// .show(); } }) .subscribeOn(AndroidSchedulers.mainThread()) @@ -86,12 +85,12 @@ public void call() { .subscribe(new Subscriber() { @Override public void onCompleted() { - mMaterialDialog.dismiss(); +// mMaterialDialog.dismiss(); } @Override public void onError(Throwable e) { - mMaterialDialog.dismiss(); +// mMaterialDialog.dismiss(); e.printStackTrace(); } From 8612c5e07c91b6d454d2964bac119cd1cb95c4e4 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Wed, 12 Dec 2018 17:29:09 +0800 Subject: [PATCH 013/150] Remove bugly tinker --- README-zh.md | 1 - README.md | 1 - app/build.gradle | 12 +-- app/proguard-rules.pro | 2 +- app/src/main/AndroidManifest.xml | 2 +- .../{App.kt => KotlinApplication.kt} | 5 +- .../leeeyou/zhihuribao/SampleApplication.java | 11 --- .../zhihuribao/SampleApplicationLike.java | 53 ---------- app/tinker-support.gradle | 91 ------------------ build.gradle | 1 - keystore/{tinker.jks => Rskotlin.jks} | Bin 11 files changed, 9 insertions(+), 170 deletions(-) rename app/src/main/java/com/xyz/leeeyou/zhihuribao/{App.kt => KotlinApplication.kt} (86%) delete mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/SampleApplication.java delete mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/SampleApplicationLike.java delete mode 100644 app/tinker-support.gradle rename keystore/{tinker.jks => Rskotlin.jks} (100%) diff --git a/README-zh.md b/README-zh.md index 828a94f..481d9b6 100644 --- a/README-zh.md +++ b/README-zh.md @@ -21,4 +21,3 @@ - 利用WebView展示详情 - 引入Glide加载图片 - 引入ultra-ptr:1.0实现上拉加载更多 -- 引入bugly tinker实现热修复功能 diff --git a/README.md b/README.md index 80d49bc..ee0b819 100644 --- a/README.md +++ b/README.md @@ -19,4 +19,3 @@ Rs(Read the selection) Kotlin Edition is a simple app developed by Kotlin, mainl - Use WebView to show details - Introduced Glide to load the picture - Introduced ultra-ptr: 1.0 to achieve pull-ups to load more -- Introduced bugly tinker diff --git a/app/build.gradle b/app/build.gradle index ff3ac77..f34c63e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,7 +2,6 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-android-extensions' -apply from: 'tinker-support.gradle' android { compileSdkVersion 28 @@ -25,7 +24,7 @@ android { config { keyAlias 'leeeyoukeystore' keyPassword '123999000' - storeFile file('..\\keystore\\tinker.jks') + storeFile file('..\\keystore\\Rskotlin.jks') storePassword '123999000' } } @@ -74,9 +73,10 @@ dependencies { implementation 'in.srain.cube:ultra-ptr:1.0.11' - implementation "com.android.support:multidex:1.0.1" - implementation 'com.tencent.bugly:crashreport_upgrade:1.3.1' - implementation 'com.tencent.bugly:nativecrashreport:latest.release' - //The latest.release refers to the latest version number, you can also specify a clear version number, for example, 2.2.0 + implementation "com.android.support:multidex:1.0.3" + + //bugly + implementation 'com.tencent.bugly:crashreport_upgrade:1.3.6' + implementation 'com.tencent.bugly:nativecrashreport:3.6.0' } \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 4a22553..71d0186 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -89,4 +89,4 @@ } -keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef { rx.internal.util.atomic.LinkedQueueNode consumerNode; -} \ No newline at end of file +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5e832fb..2068176 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -10,7 +10,7 @@ Date: Wed, 12 Dec 2018 17:30:44 +0800 Subject: [PATCH 014/150] Upgrade Dagger version number --- app/build.gradle | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index f34c63e..bf07b64 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -51,8 +51,9 @@ dependencies { implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support:design:28.0.0' - implementation 'com.google.dagger:dagger:2.4' - kapt 'com.google.dagger:dagger-compiler:2.4' + //dagger + implementation 'com.google.dagger:dagger:2.12' + kapt 'com.google.dagger:dagger-compiler:2.12' compileOnly 'org.glassfish:javax.annotation:10.0-b28' implementation 'com.squareup.retrofit:retrofit:2.0.0-beta2' From a63e02486491730306079287b6ad86de9805ac31 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Wed, 12 Dec 2018 17:32:01 +0800 Subject: [PATCH 015/150] Upgrade rxandroid version number --- app/build.gradle | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index bf07b64..d8a17f3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -50,34 +50,32 @@ dependencies { testImplementation 'junit:junit:4.12' implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support:design:28.0.0' + implementation "com.android.support:multidex:1.0.3" //dagger implementation 'com.google.dagger:dagger:2.12' kapt 'com.google.dagger:dagger-compiler:2.12' compileOnly 'org.glassfish:javax.annotation:10.0-b28' + //retrofit implementation 'com.squareup.retrofit:retrofit:2.0.0-beta2' implementation 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2' implementation 'com.squareup.retrofit:converter-gson:2.0.0-beta2' - implementation 'io.reactivex:rxandroid:1.0.1' + //rx + implementation 'io.reactivex:rxandroid:1.2.1' implementation 'io.reactivex:rxkotlin:1.0.0' - implementation 'com.github.bumptech.glide:glide:3.7.0' + //bugly + implementation 'com.tencent.bugly:crashreport_upgrade:1.3.6' + implementation 'com.tencent.bugly:nativecrashreport:3.6.0' + implementation 'com.github.bumptech.glide:glide:3.7.0' implementation 'com.ogaclejapan.smarttablayout:library:1.6.1@aar' - implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.44' implementation 'net.danlew:android.joda:2.9.4.1' implementation 'com.afollestad.material-dialogs:core:0.9.0.2' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation 'in.srain.cube:ultra-ptr:1.0.11' - implementation "com.android.support:multidex:1.0.3" - - //bugly - implementation 'com.tencent.bugly:crashreport_upgrade:1.3.6' - implementation 'com.tencent.bugly:nativecrashreport:3.6.0' - } \ No newline at end of file From 97a48bb69aee9e7a2dceaf69b252afbf3e1b4fb2 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Wed, 12 Dec 2018 17:35:19 +0800 Subject: [PATCH 016/150] Upgrade glide version number --- app/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d8a17f3..43176a3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -70,12 +70,12 @@ dependencies { implementation 'com.tencent.bugly:crashreport_upgrade:1.3.6' implementation 'com.tencent.bugly:nativecrashreport:3.6.0' - implementation 'com.github.bumptech.glide:glide:3.7.0' + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" + implementation 'com.github.bumptech.glide:glide:4.6.1' implementation 'com.ogaclejapan.smarttablayout:library:1.6.1@aar' implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.44' - implementation 'net.danlew:android.joda:2.9.4.1' + implementation 'net.danlew:android.joda:2.9.9.4' implementation 'com.afollestad.material-dialogs:core:0.9.0.2' - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation 'in.srain.cube:ultra-ptr:1.0.11' } \ No newline at end of file From 1ac00a001a5b9088e709a8303fd5d5b74a58ea61 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Wed, 12 Dec 2018 17:40:18 +0800 Subject: [PATCH 017/150] Update part of the code --- .../leeeyou/zhihuribao/di/component/StoryComponent.kt | 2 +- .../com/xyz/leeeyou/zhihuribao/di/module/StoryModule.kt | 9 ++++----- .../leeeyou/zhihuribao/view/activity/IndexActivity.kt | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/StoryComponent.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/StoryComponent.kt index 24d72e8..9de830f 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/StoryComponent.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/StoryComponent.kt @@ -14,7 +14,7 @@ import javax.inject.Singleton * Date: 2018/2/24 15:15 */ @Singleton -@Component(modules = arrayOf(StoryModule::class)) +@Component(modules = [StoryModule::class]) interface StoryComponent { fun inject(storyDetailActivity: StoryDetailActivity) diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/StoryModule.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/StoryModule.kt index cf8d180..bf84b36 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/StoryModule.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/StoryModule.kt @@ -16,12 +16,11 @@ import javax.inject.Singleton * Author: leeeyou * Date: 2018/2/24 15:16 */ +private const val endPoint = "http://news-at.zhihu.com/" + @Singleton @Module class StoryModule { - private val endPoint = "http://news-at.zhihu.com/" -// val endPoint2 = "http://news.at.zhihu.com/" - var storyId: Int = 0 var date: String = "" @@ -34,7 +33,7 @@ class StoryModule { @Singleton @Provides fun provideStories(): Observable { - return ServiceFactory.Companion + return ServiceFactory .createRxRetrofitService(ZhiHuRiBaoService::class.java, endPoint) .getLatestRiBao(date) } @@ -42,7 +41,7 @@ class StoryModule { @Singleton @Provides fun provideStoryDetail(): Observable { - return ServiceFactory.Companion + return ServiceFactory .createRxRetrofitService(ZhiHuRiBaoService::class.java, endPoint) .getStoryDetailById(storyId) } diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt index 4492b55..d6b4ba6 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt @@ -11,8 +11,9 @@ import com.xyz.leeeyou.zhihuribao.view.fragment.OneFragment import com.xyz.leeeyou.zhihuribao.view.fragment.StoryFragment import kotlinx.android.synthetic.main.activity_index.* +private const val FIRST_PAGE_INDEX: Int = 0 + class IndexActivity : BaseOriginalActivity() { - private val FIRST_PAGE_INDEX: Int = 0 private lateinit var mViewPagerAdapter: ViewPagerAdapter @@ -22,7 +23,6 @@ class IndexActivity : BaseOriginalActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_index) - initAdapter() initViewPager() initPtr() From 04dfbded69002b7960ef9a036fea08cb3c8392ca Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Thu, 13 Dec 2018 09:42:14 +0800 Subject: [PATCH 018/150] Update signature configuration method --- app/build.gradle | 20 ++++++++++++++------ keystore/Rskotlin.jks | Bin 2182 -> 0 bytes 2 files changed, 14 insertions(+), 6 deletions(-) delete mode 100644 keystore/Rskotlin.jks diff --git a/app/build.gradle b/app/build.gradle index 43176a3..ce9df27 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,6 +3,10 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-android-extensions' +def keystorePropertiesFile = rootProject.file("D:\\keystore\\RsKotlin\\RsKotlinKeystore.properties") +def keystoreProperties = new Properties() +keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) + android { compileSdkVersion 28 buildToolsVersion '28.0.3' @@ -11,8 +15,8 @@ android { applicationId "com.xyz.leeeyou.zhihuribao" minSdkVersion 15 targetSdkVersion 28 - versionCode 2 - versionName "1.1.4" + versionCode 115 + versionName "1.1.5" ndk { //Set up a supported SO library architecture @@ -20,12 +24,16 @@ android { } } + lintOptions { + abortOnError false + } + signingConfigs { config { - keyAlias 'leeeyoukeystore' - keyPassword '123999000' - storeFile file('..\\keystore\\Rskotlin.jks') - storePassword '123999000' + keyAlias keystoreProperties['keyAlias'] + keyPassword keystoreProperties['keyPassword'] + storeFile file(keystoreProperties['storeFile']) + storePassword keystoreProperties['storePassword'] } } diff --git a/keystore/Rskotlin.jks b/keystore/Rskotlin.jks deleted file mode 100644 index 778cbfd8d4b7643d4296950bf659e5d527bf56ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2182 zcmb`H_cPp!8pglh-6gWhhUihEL=ARVi;(1~QKMu9(aVam8&+F_kQHTFCOU}{;fRC9 zA^O#W8$D5Wql6tU5pwj160UpZ-Wh+u{o$GU%=61T@AJO%oP0m|4gdh;OyJ)_;ILS1 zm|w6jHY_m6F93VyJKGGC;sAgNM3P{?kQ~f#d1ep>%0W0mkO_d1V5`*dr>+|(2EjWT zx4ax#cj$~XMk$JD!?WB<;ZiYoB#)POT#&RK+|xvB7n=1cWVfEG06s;DH9y|<4{-UC zJN3=CDVf7c;f%iFFY<_$`qB@;+)COKcWeJ=LD?OhJB{OtcMNtOaY-2x7JpV+oY2c1 z(=6*_Dox=_R?>+>^(HmYyjAM0aTS~U*aolb`{LxA-2xj0h2l3-YmWllC|+A%*`CX_ zzD_2vFW)ivgZ>+zw?>c+MN{XBx2&$K3YVar`xf_m?$O26&{YE{q7Ho>15kV=Za}`a zT%nmOi+u`AMXe798vnIfnX*ST<@*upC{cQ?p&(L{b2$KS7vpYIeQLYT`ZaUUhBl48dTl-OmZN@I? za3sR!?&u-aUgsJSB|`Qglv;uxk)fn zm9Vq=zImGZi`8-&X4V?qN&i-5@`Y_i1|IQBK?5Sxd)FxrU6 ztl$>=eJ6^@l?{!GA1ZVe{OOVu?D0teL9Yd~owK#hgLqWIo)~iZDyPN({?nov3iW2G z(2n|qdq#b7nxX5#Tg?~_A`w23s!CFV`-4X2-(w*;&BT5gpKZ@wHS4UCgra+8TL~ij zT8#82s50rTN3exula&ESURBV>jA=n@b6G0NNuE>aw=y3fvVym%&?Ft|${$UgysN65@1U=$hfe?85YR@wch!(Gwkx&jP|bq$7$( zDzwAXsxwZsN1Q0L(0x>$X>1RxDja3l*e)EdTo8ASb$ zSlID>?m~<60L^3p^QYTJ>*BAQU5WJ=>Ho3$5|v${QM$kH4i0$ z2mna};SdrC0<*5@OJ(gI1ya{#Xt%M!x8xw37BJCiA#_ zdz$7$TKeG?lc9raq8H-mrN*WEKvEuNJ^kX00R4z&U1IH++k-0(b+UFgz5K1aZ`NdA zBWZ3w{;u$>Ri*!4;sbX*mTh9Q-=$3N z>*yucPxOn_W2jzautHA#QM+~*R`rjrT#Sf>ZY@d5+x4x9hG}?8_U#z^ewD|b(rL4z zGs0^`$M5n=oX_A!eV~G5Qbk0X!YRlv5PgkBa>+aYpTIylPlen-kwZtak;B!JVeWD1 zg=}3K1PTIRu^3VmDSUQYVGbBCjC*7^&?D(%F|npZN8|yK=FrUe5_~?yvu`*H5d%~#ic?Abs`Yc^# z60+v`5^hjE5{`BE=Gn597{gUxXmf!w(HF}e-p^$@h|Zy>N5%jAz~zvsIk&|gmK9e1 zgq-X0?6XhL+o<*HDg$hI48>!JJ`(J6p{L>Z-uas`F+%a}oTTwmi6}h9zOenHR+@r@ zR(pv(69F%VD~)gE3lDfmJtO3~F8%7sF=?nnAp(`)p|W_{_M& Tymtpur)>HC4O6xIiim#$$E>^O From e817f906703b62d30909003931548e0057075683 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Thu, 13 Dec 2018 09:44:21 +0800 Subject: [PATCH 019/150] Update readme --- README-zh.md | 4 ++-- README.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README-zh.md b/README-zh.md index 481d9b6..5e698d9 100644 --- a/README-zh.md +++ b/README-zh.md @@ -12,8 +12,8 @@ ## 特点 -- 引入Kotlin1.1.0版开发 -- 引入Dagger2.4结合Kotlin +- 引入Kotlin1.3.0版开发 +- 引入Dagger2.12结合Kotlin - 引入Retrofit2.0结合Kotlin,抽取ServiceFactory - 引入RxAndroid和RxKotlin - 引入Toolbar并抽取基类 diff --git a/README.md b/README.md index ee0b819..4cde481 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ Rs(Read the selection) Kotlin Edition is a simple app developed by Kotlin, mainl '>Get it on Google Play ## Features -- Introduced Kotlin1.1.0 version development -- Introduced Dagger 2.4 with Kotlin +- Introduced Kotlin1.3.0 version development +- Introduced Dagger 2.12 with Kotlin - Introduced Retrofit2.0 combined with Kotlin, extract ServiceFactory - Introduced RxAndroid and RxKotlin - Introduced the Toolbar and extracts the base class From 3f58831b18f1e1f7378d4df05c7d2199d3b6271e Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Thu, 13 Dec 2018 10:00:32 +0800 Subject: [PATCH 020/150] const val --- .../leeeyou/zhihuribao/vi/one/OneMultiItemEntity.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/vi/one/OneMultiItemEntity.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/vi/one/OneMultiItemEntity.kt index 3e50079..f32bd74 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/vi/one/OneMultiItemEntity.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/vi/one/OneMultiItemEntity.kt @@ -7,18 +7,18 @@ import com.xyz.leeeyou.zhihuribao.data.model.one.Weather /** * ClassName: OneMultiItemEntity * Description: [ One ] module, multi-layout entity class - * - * Author: leeeyou + * + * Author: leeeyou * Date: 2018/2/24 14:31 */ class OneMultiItemEntity(private val itemType: Int, val indexData: OneIndex? = null, val weather: Weather? = null) : MultiItemEntity { companion object { - val BLANK = -1 - val WEATHER = 0 - val TOP = 1 - val READ = 2 + const val BLANK = -1 + const val WEATHER = 0 + const val TOP = 1 + const val READ = 2 } override fun getItemType(): Int = itemType From 60cebca8ae1922ee87909b0dc7a7648daabc5b45 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Wed, 19 Dec 2018 22:21:15 +0800 Subject: [PATCH 021/150] remove smartTabLayout --- app/build.gradle | 1 - .../zhihuribao/view/activity/IndexActivity.kt | 11 ++++--- .../view/fragment/WanAndroidFragment.kt | 30 ++++++++++++++++++ .../view/fragment/WeatherFragment.kt | 30 ++++++++++++++++++ app/src/main/res/layout/activity_index.xml | 31 ++++++++----------- .../main/res/layout/fragment_wan_android.xml | 8 +++++ app/src/main/res/layout/fragment_weather.xml | 8 +++++ 7 files changed, 95 insertions(+), 24 deletions(-) create mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidFragment.kt create mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WeatherFragment.kt create mode 100644 app/src/main/res/layout/fragment_wan_android.xml create mode 100644 app/src/main/res/layout/fragment_weather.xml diff --git a/app/build.gradle b/app/build.gradle index ce9df27..9b76ec6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -80,7 +80,6 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation 'com.github.bumptech.glide:glide:4.6.1' - implementation 'com.ogaclejapan.smarttablayout:library:1.6.1@aar' implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.44' implementation 'net.danlew:android.joda:2.9.9.4' implementation 'com.afollestad.material-dialogs:core:0.9.0.2' diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt index d6b4ba6..3186df9 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt @@ -7,8 +7,9 @@ import android.support.v4.view.ViewPager import android.view.View import com.xyz.leeeyou.zhihuribao.R import com.xyz.leeeyou.zhihuribao.adapter.ViewPagerAdapter -import com.xyz.leeeyou.zhihuribao.view.fragment.OneFragment import com.xyz.leeeyou.zhihuribao.view.fragment.StoryFragment +import com.xyz.leeeyou.zhihuribao.view.fragment.WanAndroidFragment +import com.xyz.leeeyou.zhihuribao.view.fragment.WeatherFragment import kotlinx.android.synthetic.main.activity_index.* private const val FIRST_PAGE_INDEX: Int = 0 @@ -42,13 +43,13 @@ class IndexActivity : BaseOriginalActivity() { } }) - smartTabLayout.setViewPager(viewPager) + tabLayout.setupWithViewPager(viewPager) } private fun initAdapter() { //create a collection object using arrayOf - val fragmentList = arrayOf(StoryFragment(), OneFragment()) - val titleList = arrayOf("知乎日报", "一个") + val fragmentList = arrayOf(WeatherFragment(), WanAndroidFragment(), StoryFragment()) + val titleList = arrayOf("天气", "WanAndroid", "知乎日报") mViewPagerAdapter = ViewPagerAdapter(supportFragmentManager, fragmentList, titleList) mViewPagerAdapter.switchTo(FIRST_PAGE_INDEX) @@ -58,7 +59,7 @@ class IndexActivity : BaseOriginalActivity() { store_house_ptr_frame.disableWhenHorizontalMove(true) store_house_ptr_frame.setPtrHandler(object : PtrHandler { override fun onRefreshBegin(frame: PtrFrameLayout?) { - mViewPagerAdapter.updateData() +// mViewPagerAdapter.updateData() } override fun checkCanDoRefresh(frame: PtrFrameLayout?, content: View?, header: View?): diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidFragment.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidFragment.kt new file mode 100644 index 0000000..4e0619b --- /dev/null +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidFragment.kt @@ -0,0 +1,30 @@ +package com.xyz.leeeyou.zhihuribao.view.fragment + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.xyz.leeeyou.zhihuribao.R +import com.xyz.leeeyou.zhihuribao.utils.inflate + +/** + * ClassName: WeatherFragment + * Description: 天气展示 + * + * Author: leeeyou + * Date: 2017/4/24 13:46 + */ +class WanAndroidFragment : BaseFragment() { + override fun updateData() { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun checkCanDoRefresh(): Boolean { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return container?.inflate(R.layout.fragment_wan_android) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WeatherFragment.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WeatherFragment.kt new file mode 100644 index 0000000..977781e --- /dev/null +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WeatherFragment.kt @@ -0,0 +1,30 @@ +package com.xyz.leeeyou.zhihuribao.view.fragment + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.xyz.leeeyou.zhihuribao.R +import com.xyz.leeeyou.zhihuribao.utils.inflate + +/** + * ClassName: WeatherFragment + * Description: 天气展示 + * + * Author: leeeyou + * Date: 2017/4/24 13:46 + */ +class WeatherFragment : BaseFragment() { + override fun updateData() { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun checkCanDoRefresh(): Boolean { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return container?.inflate(R.layout.fragment_weather) + } + +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_index.xml b/app/src/main/res/layout/activity_index.xml index 692b7ca..2ead490 100644 --- a/app/src/main/res/layout/activity_index.xml +++ b/app/src/main/res/layout/activity_index.xml @@ -1,24 +1,19 @@ + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="#fff" + android:orientation="vertical"> - + android:layout_height="48dp" + android:layout_gravity="center_horizontal" + app:tabSelectedTextColor="#000070" + app:tabTextAppearance="@android:style/TextAppearance.Widget.TabWidget" + app:tabTextColor="#000000"/> + android:layout_below="@id/smartTabLayout"/> diff --git a/app/src/main/res/layout/fragment_wan_android.xml b/app/src/main/res/layout/fragment_wan_android.xml new file mode 100644 index 0000000..6d6ffe3 --- /dev/null +++ b/app/src/main/res/layout/fragment_wan_android.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_weather.xml b/app/src/main/res/layout/fragment_weather.xml new file mode 100644 index 0000000..2a507ee --- /dev/null +++ b/app/src/main/res/layout/fragment_weather.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file From 4c4c078dad4ac089712db8753b24157b25631675 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Wed, 19 Dec 2018 22:50:10 +0800 Subject: [PATCH 022/150] Build UI framework --- .../zhihuribao/view/activity/IndexActivity.kt | 6 ++-- .../view/fragment/WanAndroidFragment.kt | 19 +++++++++- .../fragment/WanAndroidProjectFragment.kt | 30 ++++++++++++++++ .../fragment/WanAndroidRecommendFragment.kt | 30 ++++++++++++++++ .../view/fragment/WanAndroidSystemFragment.kt | 30 ++++++++++++++++ .../view/fragment/WeatherFragment.kt | 2 +- app/src/main/res/layout/activity_index.xml | 4 +-- .../main/res/layout/fragment_wan_android.xml | 36 +++++++++++++++---- .../layout/fragment_wan_android_project.xml | 8 +++++ .../layout/fragment_wan_android_recommend.xml | 8 +++++ .../layout/fragment_wan_android_system.xml | 8 +++++ 11 files changed, 168 insertions(+), 13 deletions(-) create mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidProjectFragment.kt create mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidRecommendFragment.kt create mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidSystemFragment.kt create mode 100644 app/src/main/res/layout/fragment_wan_android_project.xml create mode 100644 app/src/main/res/layout/fragment_wan_android_recommend.xml create mode 100644 app/src/main/res/layout/fragment_wan_android_system.xml diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt index 3186df9..5daaf6f 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt @@ -30,8 +30,8 @@ class IndexActivity : BaseOriginalActivity() { } private fun initViewPager() { - viewPager.adapter = mViewPagerAdapter - viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { + indexViewPager.adapter = mViewPagerAdapter + indexViewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { override fun onPageScrollStateChanged(state: Int) { } @@ -43,7 +43,7 @@ class IndexActivity : BaseOriginalActivity() { } }) - tabLayout.setupWithViewPager(viewPager) + indexTabLayout.setupWithViewPager(indexViewPager) } private fun initAdapter() { diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidFragment.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidFragment.kt index 4e0619b..718f4f2 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidFragment.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidFragment.kt @@ -5,7 +5,9 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import com.xyz.leeeyou.zhihuribao.R +import com.xyz.leeeyou.zhihuribao.adapter.ViewPagerAdapter import com.xyz.leeeyou.zhihuribao.utils.inflate +import kotlinx.android.synthetic.main.fragment_wan_android.* /** * ClassName: WeatherFragment @@ -15,16 +17,31 @@ import com.xyz.leeeyou.zhihuribao.utils.inflate * Date: 2017/4/24 13:46 */ class WanAndroidFragment : BaseFragment() { + private lateinit var mViewPagerAdapter: ViewPagerAdapter + override fun updateData() { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } override fun checkCanDoRefresh(): Boolean { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + return false } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return container?.inflate(R.layout.fragment_wan_android) } + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + + //create a collection object using arrayOf + val fragmentList = arrayOf(WanAndroidRecommendFragment(), WanAndroidSystemFragment(), WanAndroidProjectFragment()) + val titleList = arrayOf("推荐", "体系", "项目") + + mViewPagerAdapter = ViewPagerAdapter(activity!!.supportFragmentManager, fragmentList, titleList) + wanAndroidViewPager.adapter = mViewPagerAdapter + + wanAndroidTabLayout.setupWithViewPager(wanAndroidViewPager) + } + } \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidProjectFragment.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidProjectFragment.kt new file mode 100644 index 0000000..037b118 --- /dev/null +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidProjectFragment.kt @@ -0,0 +1,30 @@ +package com.xyz.leeeyou.zhihuribao.view.fragment + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.xyz.leeeyou.zhihuribao.R +import com.xyz.leeeyou.zhihuribao.utils.inflate + +/** + * ClassName: WeatherFragment + * Description: 项目展示 + * + * Author: leeeyou + * Date: 2017/4/24 13:46 + */ +class WanAndroidProjectFragment : BaseFragment() { + override fun updateData() { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun checkCanDoRefresh(): Boolean { + return false + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return container?.inflate(R.layout.fragment_wan_android_project) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidRecommendFragment.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidRecommendFragment.kt new file mode 100644 index 0000000..e7808ee --- /dev/null +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidRecommendFragment.kt @@ -0,0 +1,30 @@ +package com.xyz.leeeyou.zhihuribao.view.fragment + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.xyz.leeeyou.zhihuribao.R +import com.xyz.leeeyou.zhihuribao.utils.inflate + +/** + * ClassName: WeatherFragment + * Description: 推荐展示 + * + * Author: leeeyou + * Date: 2017/4/24 13:46 + */ +class WanAndroidRecommendFragment : BaseFragment() { + override fun updateData() { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun checkCanDoRefresh(): Boolean { + return false + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return container?.inflate(R.layout.fragment_wan_android_recommend) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidSystemFragment.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidSystemFragment.kt new file mode 100644 index 0000000..c92698a --- /dev/null +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidSystemFragment.kt @@ -0,0 +1,30 @@ +package com.xyz.leeeyou.zhihuribao.view.fragment + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.xyz.leeeyou.zhihuribao.R +import com.xyz.leeeyou.zhihuribao.utils.inflate + +/** + * ClassName: WeatherFragment + * Description: 体系展示 + * + * Author: leeeyou + * Date: 2017/4/24 13:46 + */ +class WanAndroidSystemFragment : BaseFragment() { + override fun updateData() { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun checkCanDoRefresh(): Boolean { + return false + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return container?.inflate(R.layout.fragment_wan_android_system) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WeatherFragment.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WeatherFragment.kt index 977781e..3a25d89 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WeatherFragment.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WeatherFragment.kt @@ -20,7 +20,7 @@ class WeatherFragment : BaseFragment() { } override fun checkCanDoRefresh(): Boolean { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + return false } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { diff --git a/app/src/main/res/layout/activity_index.xml b/app/src/main/res/layout/activity_index.xml index 2ead490..8934d0e 100644 --- a/app/src/main/res/layout/activity_index.xml +++ b/app/src/main/res/layout/activity_index.xml @@ -7,7 +7,7 @@ android:orientation="vertical"> diff --git a/app/src/main/res/layout/fragment_wan_android.xml b/app/src/main/res/layout/fragment_wan_android.xml index 6d6ffe3..a0332dc 100644 --- a/app/src/main/res/layout/fragment_wan_android.xml +++ b/app/src/main/res/layout/fragment_wan_android.xml @@ -1,8 +1,32 @@ - + + + + + + + + + + - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_wan_android_project.xml b/app/src/main/res/layout/fragment_wan_android_project.xml new file mode 100644 index 0000000..822e843 --- /dev/null +++ b/app/src/main/res/layout/fragment_wan_android_project.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_wan_android_recommend.xml b/app/src/main/res/layout/fragment_wan_android_recommend.xml new file mode 100644 index 0000000..9469e4a --- /dev/null +++ b/app/src/main/res/layout/fragment_wan_android_recommend.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_wan_android_system.xml b/app/src/main/res/layout/fragment_wan_android_system.xml new file mode 100644 index 0000000..e938bbe --- /dev/null +++ b/app/src/main/res/layout/fragment_wan_android_system.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file From 4e2b6ab42c18fcb97d104acbaaa100c133bcc025 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Wed, 19 Dec 2018 22:55:27 +0800 Subject: [PATCH 023/150] Build UI framework --- .../com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt | 2 +- .../leeeyou/zhihuribao/view/fragment/WanAndroidFragment.kt | 4 ++-- .../zhihuribao/view/fragment/WanAndroidProjectFragment.kt | 2 +- .../zhihuribao/view/fragment/WanAndroidRecommendFragment.kt | 4 ++-- .../zhihuribao/view/fragment/WanAndroidSystemFragment.kt | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt index 5daaf6f..8160969 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt @@ -59,7 +59,7 @@ class IndexActivity : BaseOriginalActivity() { store_house_ptr_frame.disableWhenHorizontalMove(true) store_house_ptr_frame.setPtrHandler(object : PtrHandler { override fun onRefreshBegin(frame: PtrFrameLayout?) { -// mViewPagerAdapter.updateData() + mViewPagerAdapter.updateData() } override fun checkCanDoRefresh(frame: PtrFrameLayout?, content: View?, header: View?): diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidFragment.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidFragment.kt index 718f4f2..76ef902 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidFragment.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidFragment.kt @@ -10,8 +10,8 @@ import com.xyz.leeeyou.zhihuribao.utils.inflate import kotlinx.android.synthetic.main.fragment_wan_android.* /** - * ClassName: WeatherFragment - * Description: 天气展示 + * ClassName: WanAndroidFragment + * Description: 玩Android * * Author: leeeyou * Date: 2017/4/24 13:46 diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidProjectFragment.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidProjectFragment.kt index 037b118..cdeff90 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidProjectFragment.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidProjectFragment.kt @@ -8,7 +8,7 @@ import com.xyz.leeeyou.zhihuribao.R import com.xyz.leeeyou.zhihuribao.utils.inflate /** - * ClassName: WeatherFragment + * ClassName: WeatherFragment * Description: 项目展示 * * Author: leeeyou diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidRecommendFragment.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidRecommendFragment.kt index e7808ee..48ac8f1 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidRecommendFragment.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidRecommendFragment.kt @@ -8,7 +8,7 @@ import com.xyz.leeeyou.zhihuribao.R import com.xyz.leeeyou.zhihuribao.utils.inflate /** - * ClassName: WeatherFragment + * ClassName: WeatherFragment * Description: 推荐展示 * * Author: leeeyou @@ -20,7 +20,7 @@ class WanAndroidRecommendFragment : BaseFragment() { } override fun checkCanDoRefresh(): Boolean { - return false + return true } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidSystemFragment.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidSystemFragment.kt index c92698a..4dd3b33 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidSystemFragment.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/WanAndroidSystemFragment.kt @@ -8,7 +8,7 @@ import com.xyz.leeeyou.zhihuribao.R import com.xyz.leeeyou.zhihuribao.utils.inflate /** - * ClassName: WeatherFragment + * ClassName: WeatherFragment * Description: 体系展示 * * Author: leeeyou From d62ca2d6b026208c44737b32517c234ba7ad175e Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Thu, 20 Dec 2018 23:10:24 +0800 Subject: [PATCH 024/150] Delete One Module --- app/build.gradle | 1 + .../adapter/one/MultiItemAdapterForOne.kt | 52 ------ .../zhihuribao/di/component/OneComponent.kt | 19 -- .../leeeyou/zhihuribao/di/module/OneModule.kt | 50 ------ .../zhihuribao/vi/one/OneMultiItemEntity.kt | 26 --- .../zhihuribao/view/fragment/OneFragment.kt | 165 ------------------ 6 files changed, 1 insertion(+), 312 deletions(-) delete mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/one/MultiItemAdapterForOne.kt delete mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/OneComponent.kt delete mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/OneModule.kt delete mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/vi/one/OneMultiItemEntity.kt delete mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/OneFragment.kt diff --git a/app/build.gradle b/app/build.gradle index 9b76ec6..3c44c75 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,6 +56,7 @@ android { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') testImplementation 'junit:junit:4.12' + //noinspection GradleCompatible implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support:design:28.0.0' implementation "com.android.support:multidex:1.0.3" diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/one/MultiItemAdapterForOne.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/one/MultiItemAdapterForOne.kt deleted file mode 100644 index 6a8c256..0000000 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/one/MultiItemAdapterForOne.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.xyz.leeeyou.zhihuribao.adapter.one - -import com.bumptech.glide.Glide -import com.chad.library.adapter.base.BaseMultiItemQuickAdapter -import com.chad.library.adapter.base.BaseViewHolder -import com.xyz.leeeyou.zhihuribao.R -import com.xyz.leeeyou.zhihuribao.vi.one.OneMultiItemEntity - -/** - * ClassName: MultiItemAdapterForOne - * Description: [ One ] module, multi-layout adapter - * - * Author: leeeyou - * Date: 2018/2/24 14:33 - */ -class MultiItemAdapterForOne(data: MutableList?) : BaseMultiItemQuickAdapter(data) { - - init { - addItemType(OneMultiItemEntity.BLANK, R.layout.item_one_index_blank) - addItemType(OneMultiItemEntity.WEATHER, R.layout.item_one_index_weather) - addItemType(OneMultiItemEntity.TOP, R.layout.item_one_index_top) - addItemType(OneMultiItemEntity.READ, R.layout.item_one_index_read) - } - - override fun convert(vh: BaseViewHolder, item: OneMultiItemEntity) { - when (item.itemType) { - OneMultiItemEntity.WEATHER -> { - vh.setText(R.id.tv_date, item.weather?.date) - .setText(R.id.tv_climate, item.weather?.climate + "," + item.weather?.city_name) - } - OneMultiItemEntity.TOP -> { - Glide.with(mContext).load(item.indexData?.img_url).into(vh.getView(R.id.img)) - vh.setText(R.id.tv_author, item.indexData?.title + " | " + item.indexData?.pic_info) - .setText(R.id.tv_forward, item.indexData?.forward) - .setText(R.id.tv_words_info, item.indexData?.words_info) - .setText(R.id.tv_like, item.indexData?.like_count.toString() + "个赞") - .setOnClickListener(R.id.tv_share) {} - .setOnClickListener(R.id.rl_item_one_index_top) {} - } - OneMultiItemEntity.READ -> { - Glide.with(mContext).load(item.indexData?.img_url).into(vh.getView(R.id.img)) - vh.setText(R.id.tv_title, item.indexData?.title) - .setText(R.id.tv_author_name, "文/" + item.indexData?.author?.user_name) - .setText(R.id.tv_forward, item.indexData?.forward) - .setText(R.id.tv_like, item.indexData?.like_count.toString() + "个赞") - .setOnClickListener(R.id.tv_share) {} - .setOnClickListener(R.id.rl_item_one_index_read) {} - } - } - } - -} diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/OneComponent.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/OneComponent.kt deleted file mode 100644 index e7aa697..0000000 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/OneComponent.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.xyz.leeeyou.zhihuribao.di.component - -import com.xyz.leeeyou.zhihuribao.di.module.OneModule -import com.xyz.leeeyou.zhihuribao.view.fragment.OneFragment -import dagger.Component -import javax.inject.Singleton - -/** - * ClassName: OneComponent - * Description: [ One ] module Component - * - * Author: leeeyou - * Date: 2018/2/24 15:15 - */ -@Singleton -@Component(modules = [OneModule::class]) -interface OneComponent { - fun inject(oneFragment: OneFragment) -} \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/OneModule.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/OneModule.kt deleted file mode 100644 index 32dfca4..0000000 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/OneModule.kt +++ /dev/null @@ -1,50 +0,0 @@ -package com.xyz.leeeyou.zhihuribao.di.module - -import com.xyz.leeeyou.zhihuribao.data.model.one.ID -import com.xyz.leeeyou.zhihuribao.data.model.one.Index -import com.xyz.leeeyou.zhihuribao.data.service.OneService -import com.xyz.leeeyou.zhihuribao.data.service.ServiceFactory -import dagger.Module -import dagger.Provides -import rx.Observable -import javax.inject.Singleton - -/** - * ClassName: OneModule - * Description: - * - * Author: leeeyou - * Date: 2018/2/24 15:16 - */ - -private const val endPoint = "http://v3.wufazhuce.com:8000/" - -@Singleton -@Module -class OneModule { - - var id: Int = 0 - - constructor(id: Int) { - this.id = id - } - - constructor() - - @Singleton - @Provides - fun provideOne(): Observable { - return ServiceFactory - .createRxRetrofitService(OneService::class.java, endPoint) - .getIndexList(id) - } - - @Singleton - @Provides - fun provideIdList(): Observable { - return ServiceFactory - .createRxRetrofitService(OneService::class.java, endPoint) - .getIdList() - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/vi/one/OneMultiItemEntity.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/vi/one/OneMultiItemEntity.kt deleted file mode 100644 index f32bd74..0000000 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/vi/one/OneMultiItemEntity.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.xyz.leeeyou.zhihuribao.vi.one - -import com.chad.library.adapter.base.entity.MultiItemEntity -import com.xyz.leeeyou.zhihuribao.data.model.one.OneIndex -import com.xyz.leeeyou.zhihuribao.data.model.one.Weather - -/** - * ClassName: OneMultiItemEntity - * Description: [ One ] module, multi-layout entity class - * - * Author: leeeyou - * Date: 2018/2/24 14:31 - */ -class OneMultiItemEntity(private val itemType: Int, - val indexData: OneIndex? = null, - val weather: Weather? = null) : MultiItemEntity { - companion object { - const val BLANK = -1 - const val WEATHER = 0 - const val TOP = 1 - const val READ = 2 - } - - override fun getItemType(): Int = itemType - -} \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/OneFragment.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/OneFragment.kt deleted file mode 100644 index 2775bb3..0000000 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/OneFragment.kt +++ /dev/null @@ -1,165 +0,0 @@ -package com.xyz.leeeyou.zhihuribao.view.fragment - -import android.os.Bundle -import android.support.v7.widget.LinearLayoutManager -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import com.chad.library.adapter.base.BaseQuickAdapter -import com.xyz.leeeyou.zhihuribao.R -import com.xyz.leeeyou.zhihuribao.adapter.one.MultiItemAdapterForOne -import com.xyz.leeeyou.zhihuribao.data.model.one.ID -import com.xyz.leeeyou.zhihuribao.data.model.one.Index -import com.xyz.leeeyou.zhihuribao.di.component.DaggerOneComponent -import com.xyz.leeeyou.zhihuribao.di.module.OneModule -import com.xyz.leeeyou.zhihuribao.utils.inflate -import com.xyz.leeeyou.zhihuribao.vi.one.OneMultiItemEntity -import com.xyz.leeeyou.zhihuribao.view.activity.IndexActivity -import kotlinx.android.synthetic.main.fragment_one.* -import rx.Observable -import rx.android.schedulers.AndroidSchedulers -import rx.lang.kotlin.subscribeBy -import rx.schedulers.Schedulers -import java.util.* -import javax.inject.Inject - -/** - * ClassName: OneFragment - * Description: 【一个】fragment , Kotlin style - * - * Author: leeeyou - * Date: 2017/4/24 13:46 - */ -class OneFragment : BaseFragment() { - - @Inject - lateinit var mIndexObservable: Observable - - @Inject - lateinit var mIdObservable: Observable - - private lateinit var mIdList: Array - private lateinit var mIndexAdapter: MultiItemAdapterForOne - private var mPosition: Int = 0 - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return container?.inflate(R.layout.fragment_one) - } - - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) - initRecyclerView() - updateData() - } - - private fun initRecyclerView() { - initLayoutManager() - initAdapter() - } - - private fun initLayoutManager() { - recyclerViewOne.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) - } - - private fun initAdapter() { - mIndexAdapter = MultiItemAdapterForOne(null) - mIndexAdapter.setOnLoadMoreListener({ - if (mPosition < mIdList.size - 1) { - loadIndexData(++mPosition) - } - }, recyclerViewOne) - mIndexAdapter.openLoadAnimation(BaseQuickAdapter.SCALEIN) - recyclerViewOne.adapter = mIndexAdapter - } - - //get the ID collection for all categories - private fun fetchIdData() { - mIdObservable.subscribeOn(Schedulers.newThread()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribeBy( - onError = { - (activity as IndexActivity).refreshComplete() - it.printStackTrace() - }, - onNext = { - mIdList = it.data - mPosition = 0 - loadIndexData(mPosition) - } - ) - } - - private fun loadIndexData(position: Int) { - DaggerOneComponent.builder() - .oneModule(OneModule(mIdList[position].toInt())) - .build() - .inject(this) - - fetchIndexData() - } - - private fun fetchIndexData() { - mIndexObservable.subscribeOn(Schedulers.newThread()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribeBy( - onError = { - (activity as IndexActivity).refreshComplete() - it.printStackTrace() - }, - onNext = { - (activity as IndexActivity).refreshComplete() - - val indexData = parseIndexData(it) - val isPullToRefresh = mPosition == 0 - if (isPullToRefresh) { - mIndexAdapter.setNewData(indexData) - } else { - mIndexAdapter.addData(indexData) - mIndexAdapter.loadMoreComplete() - } - }) - } - - private fun parseIndexData(index: Index): MutableList { - val tempDataList: MutableList = ArrayList() - - //if it is a drop-down refresh, add the weather UI - val isPullToRefresh = mPosition == 0 - if (isPullToRefresh) { - tempDataList.add(OneMultiItemEntity(OneMultiItemEntity.WEATHER, null, index.data.weather)) - } - - //parse data - val contentList = index.data.content_list - for (contentIndex in contentList.indices) { - tempDataList.add(OneMultiItemEntity(if (contentIndex == 0) OneMultiItemEntity.TOP else OneMultiItemEntity.READ, contentList[contentIndex], null)) - tempDataList.add(OneMultiItemEntity(OneMultiItemEntity.BLANK, null, null)) - } - - //if the current value of mPosition is equal to the maximum value of mIdList, the end is loaded more - val isLoadMoreEnd = mPosition == mIdList.size - 1 - if (isLoadMoreEnd) { - loadMoreEnd() - } - - return tempDataList - } - - override fun checkCanDoRefresh(): Boolean = !recyclerViewOne.canScrollVertically(-1) - - override fun updateData() { - mIndexAdapter.setEnableLoadMore(true) - mIndexAdapter.removeAllFooterView() - DaggerOneComponent.builder().oneModule(OneModule()).build().inject(this) - fetchIdData() - } - - private fun loadMoreEnd() { - with(View.inflate(context, R.layout.not_loading, null)) { - mIndexAdapter.loadMoreEnd() - mIndexAdapter.setEnableLoadMore(false) - mIndexAdapter.addFooterView(this) - } - } - -} \ No newline at end of file From 00347075aa4ae053e7a227a0393c8ff783b27f95 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Thu, 20 Dec 2018 23:45:12 +0800 Subject: [PATCH 025/150] Remove Dagger2 --- .../zhihuribao/di/component/StoryComponent.kt | 22 --------- .../zhihuribao/di/module/StoryModule.kt | 49 ------------------- .../zhihuribao/di/module/StoryModule2.kt | 21 ++++++++ .../view/activity/BaseCenterActivity.java | 5 -- .../view/activity/BaseOriginalActivity.java | 5 -- .../zhihuribao/view/activity/IndexActivity.kt | 3 -- .../view/activity/StoryDetailActivity.java | 35 ++----------- .../view/fragment/StoryFragment.java | 13 ++--- 8 files changed, 30 insertions(+), 123 deletions(-) delete mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/StoryComponent.kt delete mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/StoryModule.kt create mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/StoryModule2.kt diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/StoryComponent.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/StoryComponent.kt deleted file mode 100644 index 9de830f..0000000 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/component/StoryComponent.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.xyz.leeeyou.zhihuribao.di.component - -import com.xyz.leeeyou.zhihuribao.di.module.StoryModule -import com.xyz.leeeyou.zhihuribao.view.activity.StoryDetailActivity -import com.xyz.leeeyou.zhihuribao.view.fragment.StoryFragment -import dagger.Component -import javax.inject.Singleton - -/** - * ClassName: StoryComponent - * Description: [ Story ] module Component - * - * Author: leeeyou - * Date: 2018/2/24 15:15 - */ -@Singleton -@Component(modules = [StoryModule::class]) -interface StoryComponent { - fun inject(storyDetailActivity: StoryDetailActivity) - - fun inject(storyFragment: StoryFragment) -} \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/StoryModule.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/StoryModule.kt deleted file mode 100644 index bf84b36..0000000 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/StoryModule.kt +++ /dev/null @@ -1,49 +0,0 @@ -package com.xyz.leeeyou.zhihuribao.di.module - -import com.xyz.leeeyou.zhihuribao.data.model.ribao.RiBao -import com.xyz.leeeyou.zhihuribao.data.model.ribao.StoryDetail -import com.xyz.leeeyou.zhihuribao.data.service.ServiceFactory -import com.xyz.leeeyou.zhihuribao.data.service.ZhiHuRiBaoService -import dagger.Module -import dagger.Provides -import rx.Observable -import javax.inject.Singleton - -/** - * ClassName: StoryModule - * Description: - * - * Author: leeeyou - * Date: 2018/2/24 15:16 - */ -private const val endPoint = "http://news-at.zhihu.com/" - -@Singleton -@Module -class StoryModule { - var storyId: Int = 0 - var date: String = "" - - constructor() - - constructor(date: String) { - this.date = date - } - - @Singleton - @Provides - fun provideStories(): Observable { - return ServiceFactory - .createRxRetrofitService(ZhiHuRiBaoService::class.java, endPoint) - .getLatestRiBao(date) - } - - @Singleton - @Provides - fun provideStoryDetail(): Observable { - return ServiceFactory - .createRxRetrofitService(ZhiHuRiBaoService::class.java, endPoint) - .getStoryDetailById(storyId) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/StoryModule2.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/StoryModule2.kt new file mode 100644 index 0000000..cf16848 --- /dev/null +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/StoryModule2.kt @@ -0,0 +1,21 @@ +package com.xyz.leeeyou.zhihuribao.di.module + +import com.xyz.leeeyou.zhihuribao.data.model.ribao.RiBao +import com.xyz.leeeyou.zhihuribao.data.model.ribao.StoryDetail +import com.xyz.leeeyou.zhihuribao.data.service.ServiceFactory +import com.xyz.leeeyou.zhihuribao.data.service.ZhiHuRiBaoService +import rx.Observable + +private const val endPoint = "http://news-at.zhihu.com/" + +fun fetchStoryListByDate(date: String): Observable { + return ServiceFactory + .createRxRetrofitService(ZhiHuRiBaoService::class.java, endPoint) + .getLatestRiBao(date) +} + +fun fetchStoryDetailById(storyId: Int): Observable { + return ServiceFactory + .createRxRetrofitService(ZhiHuRiBaoService::class.java, endPoint) + .getStoryDetailById(storyId) +} \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/BaseCenterActivity.java b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/BaseCenterActivity.java index e819bbc..ffe3488 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/BaseCenterActivity.java +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/BaseCenterActivity.java @@ -21,14 +21,9 @@ public abstract class BaseCenterActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setContentView(R.layout.activity_base_center); - - setupActivityComponent(); - ToolbarHelper.checkSdkVersionToTranslucentFlag(getWindow()); } - abstract void setupActivityComponent(); - @Override public void setContentView(int layoutResID) { ToolbarHelper.setContentView(this, layoutResID); diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/BaseOriginalActivity.java b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/BaseOriginalActivity.java index 634d921..50a61d5 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/BaseOriginalActivity.java +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/BaseOriginalActivity.java @@ -20,14 +20,9 @@ public abstract class BaseOriginalActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setContentView(R.layout.activity_base_original); - - setupActivityComponent(); - ToolbarHelper.checkSdkVersionToTranslucentFlag(getWindow()); } - abstract void setupActivityComponent(); - @Override public void setContentView(int layoutResID) { ToolbarHelper.setContentView(this, layoutResID); diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt index 8160969..94f98b1 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/IndexActivity.kt @@ -18,9 +18,6 @@ class IndexActivity : BaseOriginalActivity() { private lateinit var mViewPagerAdapter: ViewPagerAdapter - override fun setupActivityComponent() { - } - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_index) diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/StoryDetailActivity.java b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/StoryDetailActivity.java index 21f9950..098e42d 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/StoryDetailActivity.java +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/StoryDetailActivity.java @@ -5,14 +5,9 @@ import com.xyz.leeeyou.zhihuribao.R; import com.xyz.leeeyou.zhihuribao.data.model.ribao.StoryDetail; -import com.xyz.leeeyou.zhihuribao.di.component.DaggerStoryComponent; -import com.xyz.leeeyou.zhihuribao.di.component.StoryComponent; -import com.xyz.leeeyou.zhihuribao.di.module.StoryModule; +import com.xyz.leeeyou.zhihuribao.di.module.StoryModule2Kt; import com.xyz.leeeyou.zhihuribao.utils.HtmlUtils; -import javax.inject.Inject; - -import rx.Observable; import rx.Subscriber; import rx.android.schedulers.AndroidSchedulers; import rx.functions.Action0; @@ -24,52 +19,30 @@ public class StoryDetailActivity extends BaseOriginalActivity { WebView story_web; - @Inject - Observable detailObservable; - - private StoryComponent storyComponent; - private StoryModule storyModule; - -// private MaterialDialog mMaterialDialog; - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_story_detail); - story_web = (WebView) findViewById(R.id.story_web); + story_web = findViewById(R.id.story_web); storyId = getIntent().getIntExtra("storyId", -1); String storyTitle = getIntent().getStringExtra("storyTitle"); - injectModule(); setLeftTitleAndDisplayHomeAsUp(storyTitle); initWebView(); getStoryDetail(); } - private void injectModule() { - storyModule.setStoryId(storyId); - storyComponent.inject(this); - } - private void initWebView() { story_web.setVerticalScrollBarEnabled(false); story_web.getSettings().setDefaultTextEncodingName("UTF-8"); } - @Override - void setupActivityComponent() { - storyModule = new StoryModule(); - - storyComponent = DaggerStoryComponent - .builder() - .storyModule(storyModule) - .build(); - } public void getStoryDetail() { - detailObservable + StoryModule2Kt + .fetchStoryDetailById(storyId) .subscribeOn(Schedulers.newThread()) .doOnSubscribe(new Action0() { @Override diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/StoryFragment.java b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/StoryFragment.java index 09bdce1..f9bf4b3 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/StoryFragment.java +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/StoryFragment.java @@ -14,8 +14,7 @@ import com.xyz.leeeyou.zhihuribao.adapter.StoryAdapter; import com.xyz.leeeyou.zhihuribao.data.model.ribao.RiBao; import com.xyz.leeeyou.zhihuribao.data.model.ribao.Story; -import com.xyz.leeeyou.zhihuribao.di.component.DaggerStoryComponent; -import com.xyz.leeeyou.zhihuribao.di.module.StoryModule; +import com.xyz.leeeyou.zhihuribao.di.module.StoryModule2Kt; import com.xyz.leeeyou.zhihuribao.utils.T; import com.xyz.leeeyou.zhihuribao.view.activity.IndexActivity; @@ -23,8 +22,6 @@ import java.util.List; -import javax.inject.Inject; - import rx.Observable; import rx.Subscriber; import rx.android.schedulers.AndroidSchedulers; @@ -34,7 +31,7 @@ /** * ClassName: StoryFragment * Description: 【知乎日报】fragment , Java style - * + *

* Author: leeeyou * Date: 2017/4/24 13:46 */ @@ -48,7 +45,6 @@ public class StoryFragment extends BaseFragment { private int mDatePosition = 0; private int mMostDate = 7; - @Inject Observable storyObservable; @Override @@ -61,6 +57,7 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); + initDateList(); initAdapter(); updateData(); @@ -76,7 +73,7 @@ private void initAdapter() { @Override public void onLoadMoreRequested() { if (mDatePosition < mMostDate - 1) { - DaggerStoryComponent.builder().storyModule(new StoryModule(dateList[++mDatePosition])).build().inject(StoryFragment.this); + storyObservable = StoryModule2Kt.fetchStoryListByDate(dateList[++mDatePosition]); fetchStoryData(); } else { mAdapter.loadMoreEnd(); @@ -157,7 +154,7 @@ public boolean checkCanDoRefresh() { public void updateData() { mAdapter.removeAllFooterView(); mDatePosition = 0; - DaggerStoryComponent.builder().storyModule(new StoryModule(dateList[mDatePosition])).build().inject(this); + storyObservable = StoryModule2Kt.fetchStoryListByDate(dateList[mDatePosition]); fetchStoryData(); } From 27f36a1e1bc72ccc02cca94f124c64f5020e340e Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Thu, 20 Dec 2018 23:50:29 +0800 Subject: [PATCH 026/150] Delete One Content --- .../zhihuribao/data/model/one/Author.kt | 13 ------ .../zhihuribao/data/model/one/ContentList.kt | 3 -- .../leeeyou/zhihuribao/data/model/one/ID.kt | 26 ----------- .../zhihuribao/data/model/one/Index.kt | 3 -- .../zhihuribao/data/model/one/IndexData.kt | 30 ------------- .../zhihuribao/data/model/one/OneIndex.kt | 43 ------------------- .../leeeyou/zhihuribao/data/model/one/Tag.kt | 3 -- .../zhihuribao/data/model/one/Weather.kt | 11 ----- .../zhihuribao/data/service/OneService.kt | 22 ---------- 9 files changed, 154 deletions(-) delete mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Author.kt delete mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/ContentList.kt delete mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/ID.kt delete mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Index.kt delete mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/IndexData.kt delete mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/OneIndex.kt delete mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Tag.kt delete mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Weather.kt delete mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/OneService.kt diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Author.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Author.kt deleted file mode 100644 index e3321ce..0000000 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Author.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.xyz.leeeyou.zhihuribao.data.model.one - -data class Author( - var user_id: String, - var user_name: String, - var desc: String, - var wb_name: String, - var is_settled: String, - var settled_type: String, - var summary: String, - var fans_total: String, - var web_url: String -) \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/ContentList.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/ContentList.kt deleted file mode 100644 index 66a90b6..0000000 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/ContentList.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.xyz.leeeyou.zhihuribao.data.model.one - -data class ContentList(var contentList: Array) \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/ID.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/ID.kt deleted file mode 100644 index 57c9af9..0000000 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/ID.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.xyz.leeeyou.zhihuribao.data.model.one - -import java.util.* - -/** - * Created by leeeyou on 2017/4/24. - */ -data class ID(var res: Int, var data: Array) { - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as ID - - if (res != other.res) return false - if (!Arrays.equals(data, other.data)) return false - - return true - } - - override fun hashCode(): Int { - var result = res - result = 31 * result + Arrays.hashCode(data) - return result - } -} \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Index.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Index.kt deleted file mode 100644 index 5080dab..0000000 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Index.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.xyz.leeeyou.zhihuribao.data.model.one - -data class Index(var res: Int, var data: IndexData) \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/IndexData.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/IndexData.kt deleted file mode 100644 index 1a9155d..0000000 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/IndexData.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.xyz.leeeyou.zhihuribao.data.model.one - -import java.util.* - -data class IndexData(var id: String, - var date: String, - var weather: Weather, - var content_list: Array) { - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as IndexData - - if (id != other.id) return false - if (date != other.date) return false - if (weather != other.weather) return false - if (!Arrays.equals(content_list, other.content_list)) return false - - return true - } - - override fun hashCode(): Int { - var result = id.hashCode() - result = 31 * result + date.hashCode() - result = 31 * result + weather.hashCode() - result = 31 * result + Arrays.hashCode(content_list) - return result - } -} diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/OneIndex.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/OneIndex.kt deleted file mode 100644 index 856e002..0000000 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/OneIndex.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.xyz.leeeyou.zhihuribao.data.model.one - -data class OneIndex( - var id: String, - var category: String, - var display_category: Int, - var item_id: String, - var title: String, - var forward: String, - var img_url: String, - var like_count: Int, - var post_date: String, - var last_update_date: String, - var author: Author, - var video_url: String, - var audio_url: String, - var audio_platform: String, - var start_video: String, - var volume: String, - var pic_info: String, - var words_info: String, - var subtitle: String, - var number: Int, - var serial_id: Int, - var serial_list: Array, - var movie_story_id: Int, - var ad_id: Int, - var ad_type: Int, - var ad_pvurl: String, - var ad_linkurl: String, - var ad_makettime: String, - var ad_closetime: String, - var ad_share_cnt: String, - var ad_pvurl_vendor: String, - var content_id: String, - var content_type: String, - var content_bgcolor: String, - var share_url: String, - var tag_list: Array, - var music_name: String, - var audio_author: String, - var audio_album: String -) \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Tag.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Tag.kt deleted file mode 100644 index f7ae41c..0000000 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Tag.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.xyz.leeeyou.zhihuribao.data.model.one - -data class Tag(var id: String, var title: String) \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Weather.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Weather.kt deleted file mode 100644 index f9dde4c..0000000 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/one/Weather.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.xyz.leeeyou.zhihuribao.data.model.one - -data class Weather( - var city_name: String, - var date: String, - var temperature: String, - var humidity: String, - var climate: String, - var wind_direction: String, - var hurricane: String -) \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/OneService.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/OneService.kt deleted file mode 100644 index 7cb26e6..0000000 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/OneService.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.xyz.leeeyou.zhihuribao.data.service - -import com.xyz.leeeyou.zhihuribao.data.model.one.ID -import com.xyz.leeeyou.zhihuribao.data.model.one.Index -import retrofit.http.GET -import retrofit.http.Path -import rx.Observable - -/** - * ClassName:OneService - * Description: [ One ] module service - * - * Author: leeeyou - * Date: 2018/4/24 15:14 - */ -interface OneService { - @GET("/api/onelist/{id}/0?cchannel=wdj&version=4.0.2&uuid=ffffffff-a90e-706a-63f7-ccf973aae5ee&platform=android") - fun getIndexList(@Path("id") id: Int): Observable - - @GET("/api/onelist/idlist/?channel=wdj&version=4.0.2&uuid=ffffffff-a90e-706a-63f7-ccf973aae5ee&platform=android") - fun getIdList(): Observable -} \ No newline at end of file From 8be1feb2f1e9809a3aa33c7745d978e622fe3092 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Thu, 20 Dec 2018 23:52:11 +0800 Subject: [PATCH 027/150] Remove Dagger2 gradle config --- app/build.gradle | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 3c44c75..00edf54 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -61,11 +61,6 @@ dependencies { implementation 'com.android.support:design:28.0.0' implementation "com.android.support:multidex:1.0.3" - //dagger - implementation 'com.google.dagger:dagger:2.12' - kapt 'com.google.dagger:dagger-compiler:2.12' - compileOnly 'org.glassfish:javax.annotation:10.0-b28' - //retrofit implementation 'com.squareup.retrofit:retrofit:2.0.0-beta2' implementation 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2' From c0757d944dd04671b9e18de46d42804dee759c30 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Thu, 20 Dec 2018 23:55:10 +0800 Subject: [PATCH 028/150] Change Story module name to ZhiHuDaily module --- app/src/main/AndroidManifest.xml | 2 +- .../{StoryAdapter.kt => ZhiHuDailyAdapter.kt} | 6 +++--- .../{StoryModule2.kt => ZhiHuDailyRepository.kt} | 0 .../zhihuribao/view/activity/IndexActivity.kt | 4 ++-- ...Activity.java => ZhiHuDailyDetailActivity.java} | 6 +++--- ...{StoryFragment.java => ZhiHuDailyFragment.java} | 14 +++++++------- 6 files changed, 16 insertions(+), 16 deletions(-) rename app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/{StoryAdapter.kt => ZhiHuDailyAdapter.kt} (75%) rename app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/{StoryModule2.kt => ZhiHuDailyRepository.kt} (100%) rename app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/{StoryDetailActivity.java => ZhiHuDailyDetailActivity.java} (93%) rename app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/{StoryFragment.java => ZhiHuDailyFragment.java} (91%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2068176..7934adc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -24,7 +24,7 @@ ?) : BaseQuickAdapter(layoutResId, data) { +class ZhiHuDailyAdapter(layoutResId: Int, data: List?) : BaseQuickAdapter(layoutResId, data) { override fun convert(vh: BaseViewHolder, story: Story?) { if(story == null) return @@ -21,7 +21,7 @@ class StoryAdapter(layoutResId: Int, data: List?) : BaseQuickAdapter Date: Fri, 21 Dec 2018 11:26:33 +0800 Subject: [PATCH 029/150] Change Story module name to ZhiHuDaily module --- .../zhihuribao/adapter/ZhiHuDailyAdapter.kt | 6 +++--- .../zhihuribao/data/model/ribao/Story.kt | 9 --------- .../data/model/ribao/StoryDetail.kt | 14 ------------- .../model/ribao/{RiBao.kt => ZhiHuDaily.kt} | 2 +- .../data/model/ribao/ZhiHuDailyDetail.kt | 14 +++++++++++++ .../data/model/ribao/ZhiHuDailyItem.kt | 9 +++++++++ .../data/service/ZhiHuRiBaoService.kt | 8 ++++---- .../di/module/ZhiHuDailyRepository.kt | 12 +++++------ .../activity/ZhiHuDailyDetailActivity.java | 6 +++--- .../view/fragment/ZhiHuDailyFragment.java | 20 +++++++++---------- 10 files changed, 50 insertions(+), 50 deletions(-) delete mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/Story.kt delete mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/StoryDetail.kt rename app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/{RiBao.kt => ZhiHuDaily.kt} (86%) create mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/ZhiHuDailyDetail.kt create mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/ZhiHuDailyItem.kt diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/ZhiHuDailyAdapter.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/ZhiHuDailyAdapter.kt index 8d0d43a..31223b8 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/ZhiHuDailyAdapter.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/ZhiHuDailyAdapter.kt @@ -5,7 +5,7 @@ import com.bumptech.glide.Glide import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.BaseViewHolder import com.xyz.leeeyou.zhihuribao.R -import com.xyz.leeeyou.zhihuribao.data.model.ribao.Story +import com.xyz.leeeyou.zhihuribao.data.model.ribao.ZhiHuDailyItem import com.xyz.leeeyou.zhihuribao.view.activity.ZhiHuDailyDetailActivity /** @@ -13,9 +13,9 @@ import com.xyz.leeeyou.zhihuribao.view.activity.ZhiHuDailyDetailActivity * Author: leeeyou * Date: 2016/9/27 14:45 */ -class ZhiHuDailyAdapter(layoutResId: Int, data: List?) : BaseQuickAdapter(layoutResId, data) { +class ZhiHuDailyAdapter(layoutResId: Int, data: List?) : BaseQuickAdapter(layoutResId, data) { - override fun convert(vh: BaseViewHolder, story: Story?) { + override fun convert(vh: BaseViewHolder, story: ZhiHuDailyItem?) { if(story == null) return vh.setText(R.id.tv_story_title, story.title) diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/Story.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/Story.kt deleted file mode 100644 index 2c9c531..0000000 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/Story.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.xyz.leeeyou.zhihuribao.data.model.ribao - -data class Story(var images: List, - var type: Int, - var id: Int, - var ga_prefix: String, - var title: String, - var date: String -) \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/StoryDetail.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/StoryDetail.kt deleted file mode 100644 index c04dc58..0000000 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/StoryDetail.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.xyz.leeeyou.zhihuribao.data.model.ribao - -data class StoryDetail(var body: String, - var image_source: String, - var title: String, - var image: String, - var share_url: String, - var js: List, - var ga_prefix: String, - var images: List, - var type: Int, - var id: Int, - var css: List -) \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/RiBao.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/ZhiHuDaily.kt similarity index 86% rename from app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/RiBao.kt rename to app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/ZhiHuDaily.kt index 8973f55..b7edbc3 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/RiBao.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/ZhiHuDaily.kt @@ -11,4 +11,4 @@ package com.xyz.leeeyou.zhihuribao.data.model.ribao * Author: leeeyou * Date: 2017/4/21 15:07 */ -data class RiBao(var date: String, var stories: List) \ No newline at end of file +data class ZhiHuDaily(var date: String, var stories: List) \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/ZhiHuDailyDetail.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/ZhiHuDailyDetail.kt new file mode 100644 index 0000000..41a5c3d --- /dev/null +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/ZhiHuDailyDetail.kt @@ -0,0 +1,14 @@ +package com.xyz.leeeyou.zhihuribao.data.model.ribao + +data class ZhiHuDailyDetail(var body: String, + var image_source: String, + var title: String, + var image: String, + var share_url: String, + var js: List, + var ga_prefix: String, + var images: List, + var type: Int, + var id: Int, + var css: List +) \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/ZhiHuDailyItem.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/ZhiHuDailyItem.kt new file mode 100644 index 0000000..9a68620 --- /dev/null +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/ZhiHuDailyItem.kt @@ -0,0 +1,9 @@ +package com.xyz.leeeyou.zhihuribao.data.model.ribao + +data class ZhiHuDailyItem(var images: List, + var type: Int, + var id: Int, + var ga_prefix: String, + var title: String, + var date: String +) \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/ZhiHuRiBaoService.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/ZhiHuRiBaoService.kt index 390f57f..3903372 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/ZhiHuRiBaoService.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/ZhiHuRiBaoService.kt @@ -1,7 +1,7 @@ package com.xyz.leeeyou.zhihuribao.data.service -import com.xyz.leeeyou.zhihuribao.data.model.ribao.RiBao -import com.xyz.leeeyou.zhihuribao.data.model.ribao.StoryDetail +import com.xyz.leeeyou.zhihuribao.data.model.ribao.ZhiHuDaily +import com.xyz.leeeyou.zhihuribao.data.model.ribao.ZhiHuDailyDetail import retrofit.http.GET import retrofit.http.Path import rx.Observable @@ -15,8 +15,8 @@ import rx.Observable */ interface ZhiHuRiBaoService { @GET("/api/4/news/before/{dateTime}") - fun getLatestRiBao(@Path("dateTime") dateTime: String): Observable + fun getLatestZhiHuDaily(@Path("dateTime") dateTime: String): Observable @GET("/api/4/news/{id}") - fun getStoryDetailById(@Path("id") id: Int): Observable + fun getZhiHuDailyDetailById(@Path("id") id: Int): Observable } \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/ZhiHuDailyRepository.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/ZhiHuDailyRepository.kt index cf16848..ab2aa62 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/ZhiHuDailyRepository.kt +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/ZhiHuDailyRepository.kt @@ -1,21 +1,21 @@ package com.xyz.leeeyou.zhihuribao.di.module -import com.xyz.leeeyou.zhihuribao.data.model.ribao.RiBao -import com.xyz.leeeyou.zhihuribao.data.model.ribao.StoryDetail +import com.xyz.leeeyou.zhihuribao.data.model.ribao.ZhiHuDaily +import com.xyz.leeeyou.zhihuribao.data.model.ribao.ZhiHuDailyDetail import com.xyz.leeeyou.zhihuribao.data.service.ServiceFactory import com.xyz.leeeyou.zhihuribao.data.service.ZhiHuRiBaoService import rx.Observable private const val endPoint = "http://news-at.zhihu.com/" -fun fetchStoryListByDate(date: String): Observable { +fun fetchStoryListByDate(date: String): Observable { return ServiceFactory .createRxRetrofitService(ZhiHuRiBaoService::class.java, endPoint) - .getLatestRiBao(date) + .getLatestZhiHuDaily(date) } -fun fetchStoryDetailById(storyId: Int): Observable { +fun fetchStoryDetailById(storyId: Int): Observable { return ServiceFactory .createRxRetrofitService(ZhiHuRiBaoService::class.java, endPoint) - .getStoryDetailById(storyId) + .getZhiHuDailyDetailById(storyId) } \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/ZhiHuDailyDetailActivity.java b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/ZhiHuDailyDetailActivity.java index cd00e4e..5d9f76e 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/ZhiHuDailyDetailActivity.java +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/ZhiHuDailyDetailActivity.java @@ -4,7 +4,7 @@ import android.webkit.WebView; import com.xyz.leeeyou.zhihuribao.R; -import com.xyz.leeeyou.zhihuribao.data.model.ribao.StoryDetail; +import com.xyz.leeeyou.zhihuribao.data.model.ribao.ZhiHuDailyDetail; import com.xyz.leeeyou.zhihuribao.di.module.ZhiHuDailyRepositoryKt; import com.xyz.leeeyou.zhihuribao.utils.HtmlUtils; @@ -55,7 +55,7 @@ public void call() { }) .subscribeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Subscriber() { + .subscribe(new Subscriber() { @Override public void onCompleted() { // mMaterialDialog.dismiss(); @@ -68,7 +68,7 @@ public void onError(Throwable e) { } @Override - public void onNext(StoryDetail storyDetail) { + public void onNext(ZhiHuDailyDetail storyDetail) { story_web.loadData(HtmlUtils.structHtml(storyDetail.getBody(), storyDetail.getCss()), "text/html; charset=UTF-8", null); } }); diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/ZhiHuDailyFragment.java b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/ZhiHuDailyFragment.java index 44709a2..fb3fbaf 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/ZhiHuDailyFragment.java +++ b/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/ZhiHuDailyFragment.java @@ -12,8 +12,8 @@ import com.chad.library.adapter.base.BaseQuickAdapter; import com.xyz.leeeyou.zhihuribao.R; import com.xyz.leeeyou.zhihuribao.adapter.ZhiHuDailyAdapter; -import com.xyz.leeeyou.zhihuribao.data.model.ribao.RiBao; -import com.xyz.leeeyou.zhihuribao.data.model.ribao.Story; +import com.xyz.leeeyou.zhihuribao.data.model.ribao.ZhiHuDaily; +import com.xyz.leeeyou.zhihuribao.data.model.ribao.ZhiHuDailyItem; import com.xyz.leeeyou.zhihuribao.di.module.ZhiHuDailyRepositoryKt; import com.xyz.leeeyou.zhihuribao.utils.T; import com.xyz.leeeyou.zhihuribao.view.activity.IndexActivity; @@ -45,7 +45,7 @@ public class ZhiHuDailyFragment extends BaseFragment { private int mDatePosition = 0; private int mMostDate = 7; - Observable storyObservable; + Observable storyObservable; @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { @@ -85,9 +85,9 @@ public void onLoadMoreRequested() { private void fetchStoryData() { storyObservable .subscribeOn(Schedulers.newThread()) - .filter(new Func1() { + .filter(new Func1() { @Override - public Boolean call(RiBao riBao) { + public Boolean call(ZhiHuDaily riBao) { StringBuilder sb = new StringBuilder(); char[] chars = riBao.getDate().toCharArray(); for (int i = 0; i < chars.length; i++) { @@ -97,8 +97,8 @@ public Boolean call(RiBao riBao) { sb.append(chars[i]); } - List stories = riBao.getStories(); - for (Story story : stories) { + List stories = riBao.getStories(); + for (ZhiHuDailyItem story : stories) { story.setDate(sb.toString()); } @@ -106,7 +106,7 @@ public Boolean call(RiBao riBao) { } }) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Subscriber() { + .subscribe(new Subscriber() { @Override public void onCompleted() { mAdapter.loadMoreComplete(); @@ -120,14 +120,14 @@ public void onError(Throwable e) { } @Override - public void onNext(RiBao ribao) { + public void onNext(ZhiHuDaily ribao) { ((IndexActivity) getActivity()).refreshComplete(); setDataToAdapter(ribao.getStories()); } }); } - private void setDataToAdapter(@NonNull List stories) { + private void setDataToAdapter(@NonNull List stories) { if (mDatePosition == 0) { mAdapter.setNewData(stories); } else { From 5fed85e4021e075db9bc6e91612dcb02062106cc Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Fri, 21 Dec 2018 16:02:29 +0800 Subject: [PATCH 030/150] Change module structure --- app/build.gradle | 2 +- app/src/main/AndroidManifest.xml | 6 +++--- .../BaseCenterActivity.java | 4 ++-- .../view/fragment => leeeyou}/BaseFragment.kt | 2 +- .../BaseOriginalActivity.java | 4 ++-- .../activity => leeeyou}/IndexActivity.kt | 11 ++++------ .../KotlinApplication.kt | 2 +- .../service => leeeyou}/ServiceFactory.kt | 2 +- .../adapter => leeeyou}/ViewPagerAdapter.kt | 3 +-- .../utils => leeeyou/util}/HtmlUtils.java | 2 +- .../utils => leeeyou/util}/InflateUtil.kt | 2 +- .../zhihuribao/utils => leeeyou/util}/T.java | 2 +- .../utils => leeeyou/util}/ToolbarHelper.java | 2 +- .../wanandroid}/WanAndroidFragment.kt | 9 ++++---- .../wanandroid}/WanAndroidProjectFragment.kt | 7 ++++--- .../WanAndroidRecommendFragment.kt | 7 ++++--- .../wanandroid}/WanAndroidSystemFragment.kt | 7 ++++--- .../weather}/WeatherFragment.kt | 7 ++++--- .../zhihudaily/model/ZhiHuDailyRepository.kt | 21 +++++++++++++++++++ .../zhihudaily/model/bean}/ZhiHuDaily.kt | 2 +- .../model/bean}/ZhiHuDailyDetail.kt | 2 +- .../zhihudaily/model/bean}/ZhiHuDailyItem.kt | 2 +- .../zhihudaily/service/ZhiHuDailyService.kt} | 8 +++---- .../zhihudaily/view}/ZhiHuDailyAdapter.kt | 12 +++++------ .../view}/ZhiHuDailyDetailActivity.java | 9 ++++---- .../zhihudaily/view}/ZhiHuDailyFragment.java | 15 +++++++------ .../di/module/ZhiHuDailyRepository.kt | 21 ------------------- 27 files changed, 87 insertions(+), 86 deletions(-) rename app/src/main/java/com/{xyz/leeeyou/zhihuribao/view/activity => leeeyou}/BaseCenterActivity.java (95%) rename app/src/main/java/com/{xyz/leeeyou/zhihuribao/view/fragment => leeeyou}/BaseFragment.kt (84%) rename app/src/main/java/com/{xyz/leeeyou/zhihuribao/view/activity => leeeyou}/BaseOriginalActivity.java (92%) rename app/src/main/java/com/{xyz/leeeyou/zhihuribao/view/activity => leeeyou}/IndexActivity.kt (84%) rename app/src/main/java/com/{xyz/leeeyou/zhihuribao => leeeyou}/KotlinApplication.kt (94%) rename app/src/main/java/com/{xyz/leeeyou/zhihuribao/data/service => leeeyou}/ServiceFactory.kt (95%) rename app/src/main/java/com/{xyz/leeeyou/zhihuribao/adapter => leeeyou}/ViewPagerAdapter.kt (91%) rename app/src/main/java/com/{xyz/leeeyou/zhihuribao/utils => leeeyou/util}/HtmlUtils.java (94%) rename app/src/main/java/com/{xyz/leeeyou/zhihuribao/utils => leeeyou/util}/InflateUtil.kt (89%) rename app/src/main/java/com/{xyz/leeeyou/zhihuribao/utils => leeeyou/util}/T.java (97%) rename app/src/main/java/com/{xyz/leeeyou/zhihuribao/utils => leeeyou/util}/ToolbarHelper.java (97%) rename app/src/main/java/com/{xyz/leeeyou/zhihuribao/view/fragment => leeeyou/wanandroid}/WanAndroidFragment.kt (88%) rename app/src/main/java/com/{xyz/leeeyou/zhihuribao/view/fragment => leeeyou/wanandroid}/WanAndroidProjectFragment.kt (84%) rename app/src/main/java/com/{xyz/leeeyou/zhihuribao/view/fragment => leeeyou/wanandroid}/WanAndroidRecommendFragment.kt (84%) rename app/src/main/java/com/{xyz/leeeyou/zhihuribao/view/fragment => leeeyou/wanandroid}/WanAndroidSystemFragment.kt (84%) rename app/src/main/java/com/{xyz/leeeyou/zhihuribao/view/fragment => leeeyou/weather}/WeatherFragment.kt (83%) create mode 100644 app/src/main/java/com/leeeyou/zhihudaily/model/ZhiHuDailyRepository.kt rename app/src/main/java/com/{xyz/leeeyou/zhihuribao/data/model/ribao => leeeyou/zhihudaily/model/bean}/ZhiHuDaily.kt (90%) rename app/src/main/java/com/{xyz/leeeyou/zhihuribao/data/model/ribao => leeeyou/zhihudaily/model/bean}/ZhiHuDailyDetail.kt (91%) rename app/src/main/java/com/{xyz/leeeyou/zhihuribao/data/model/ribao => leeeyou/zhihudaily/model/bean}/ZhiHuDailyItem.kt (83%) rename app/src/main/java/com/{xyz/leeeyou/zhihuribao/data/service/ZhiHuRiBaoService.kt => leeeyou/zhihudaily/service/ZhiHuDailyService.kt} (69%) rename app/src/main/java/com/{xyz/leeeyou/zhihuribao/adapter => leeeyou/zhihudaily/view}/ZhiHuDailyAdapter.kt (73%) rename app/src/main/java/com/{xyz/leeeyou/zhihuribao/view/activity => leeeyou/zhihudaily/view}/ZhiHuDailyDetailActivity.java (90%) rename app/src/main/java/com/{xyz/leeeyou/zhihuribao/view/fragment => leeeyou/zhihudaily/view}/ZhiHuDailyFragment.java (91%) delete mode 100644 app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/ZhiHuDailyRepository.kt diff --git a/app/build.gradle b/app/build.gradle index 00edf54..68a4807 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -12,7 +12,7 @@ android { buildToolsVersion '28.0.3' defaultConfig { - applicationId "com.xyz.leeeyou.zhihuribao" + applicationId "com.leeeyou.readselection" minSdkVersion 15 targetSdkVersion 28 versionCode 115 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7934adc..10a623f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ + package="com.leeeyou"> @@ -16,7 +16,7 @@ android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> - + @@ -24,7 +24,7 @@ { + return ServiceFactory + .createRxRetrofitService(ZhiHuDailyService::class.java, endPoint) + .getLatestZhiHuDaily(date) +} + +fun fetchStoryDetailById(storyId: Int): Observable { + return ServiceFactory + .createRxRetrofitService(ZhiHuDailyService::class.java, endPoint) + .getZhiHuDailyDetailById(storyId) +} \ No newline at end of file diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/ZhiHuDaily.kt b/app/src/main/java/com/leeeyou/zhihudaily/model/bean/ZhiHuDaily.kt similarity index 90% rename from app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/ZhiHuDaily.kt rename to app/src/main/java/com/leeeyou/zhihudaily/model/bean/ZhiHuDaily.kt index b7edbc3..ffcf349 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/ZhiHuDaily.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/model/bean/ZhiHuDaily.kt @@ -1,4 +1,4 @@ -package com.xyz.leeeyou.zhihuribao.data.model.ribao +package com.leeeyou.zhihudaily.model.bean /** * ClassName: diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/ZhiHuDailyDetail.kt b/app/src/main/java/com/leeeyou/zhihudaily/model/bean/ZhiHuDailyDetail.kt similarity index 91% rename from app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/ZhiHuDailyDetail.kt rename to app/src/main/java/com/leeeyou/zhihudaily/model/bean/ZhiHuDailyDetail.kt index 41a5c3d..d11b3e4 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/ZhiHuDailyDetail.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/model/bean/ZhiHuDailyDetail.kt @@ -1,4 +1,4 @@ -package com.xyz.leeeyou.zhihuribao.data.model.ribao +package com.leeeyou.zhihudaily.model.bean data class ZhiHuDailyDetail(var body: String, var image_source: String, diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/ZhiHuDailyItem.kt b/app/src/main/java/com/leeeyou/zhihudaily/model/bean/ZhiHuDailyItem.kt similarity index 83% rename from app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/ZhiHuDailyItem.kt rename to app/src/main/java/com/leeeyou/zhihudaily/model/bean/ZhiHuDailyItem.kt index 9a68620..a983058 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/model/ribao/ZhiHuDailyItem.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/model/bean/ZhiHuDailyItem.kt @@ -1,4 +1,4 @@ -package com.xyz.leeeyou.zhihuribao.data.model.ribao +package com.leeeyou.zhihudaily.model.bean data class ZhiHuDailyItem(var images: List, var type: Int, diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/ZhiHuRiBaoService.kt b/app/src/main/java/com/leeeyou/zhihudaily/service/ZhiHuDailyService.kt similarity index 69% rename from app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/ZhiHuRiBaoService.kt rename to app/src/main/java/com/leeeyou/zhihudaily/service/ZhiHuDailyService.kt index 3903372..c025611 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/data/service/ZhiHuRiBaoService.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/service/ZhiHuDailyService.kt @@ -1,7 +1,7 @@ -package com.xyz.leeeyou.zhihuribao.data.service +package com.leeeyou.zhihudaily.service -import com.xyz.leeeyou.zhihuribao.data.model.ribao.ZhiHuDaily -import com.xyz.leeeyou.zhihuribao.data.model.ribao.ZhiHuDailyDetail +import com.leeeyou.zhihudaily.model.bean.ZhiHuDaily +import com.leeeyou.zhihudaily.model.bean.ZhiHuDailyDetail import retrofit.http.GET import retrofit.http.Path import rx.Observable @@ -13,7 +13,7 @@ import rx.Observable * Author: leeeyou * Date: 2018/4/24 15:14 */ -interface ZhiHuRiBaoService { +interface ZhiHuDailyService { @GET("/api/4/news/before/{dateTime}") fun getLatestZhiHuDaily(@Path("dateTime") dateTime: String): Observable diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/ZhiHuDailyAdapter.kt b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyAdapter.kt similarity index 73% rename from app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/ZhiHuDailyAdapter.kt rename to app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyAdapter.kt index 31223b8..d3758ea 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/adapter/ZhiHuDailyAdapter.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyAdapter.kt @@ -1,22 +1,22 @@ -package com.xyz.leeeyou.zhihuribao.adapter +package com.leeeyou.zhihudaily.view import android.content.Intent import com.bumptech.glide.Glide import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.BaseViewHolder -import com.xyz.leeeyou.zhihuribao.R -import com.xyz.leeeyou.zhihuribao.data.model.ribao.ZhiHuDailyItem -import com.xyz.leeeyou.zhihuribao.view.activity.ZhiHuDailyDetailActivity +import com.leeeyou.R +import com.leeeyou.zhihudaily.model.bean.ZhiHuDailyItem /** * ClassName: StoryAdapter * Author: leeeyou * Date: 2016/9/27 14:45 */ -class ZhiHuDailyAdapter(layoutResId: Int, data: List?) : BaseQuickAdapter(layoutResId, data) { +class ZhiHuDailyAdapter(layoutResId: Int, data: List?) + : BaseQuickAdapter(layoutResId, data) { override fun convert(vh: BaseViewHolder, story: ZhiHuDailyItem?) { - if(story == null) return + if (story == null) return vh.setText(R.id.tv_story_title, story.title) .setText(R.id.tv_story_time, story.date) diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/ZhiHuDailyDetailActivity.java b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.java similarity index 90% rename from app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/ZhiHuDailyDetailActivity.java rename to app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.java index 5d9f76e..688d964 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/activity/ZhiHuDailyDetailActivity.java +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.java @@ -1,12 +1,13 @@ -package com.xyz.leeeyou.zhihuribao.view.activity; +package com.leeeyou.zhihudaily.view; import android.os.Bundle; import android.webkit.WebView; +import com.leeeyou.BaseOriginalActivity; +import com.leeeyou.util.HtmlUtils; +import com.leeeyou.zhihudaily.model.ZhiHuDailyRepositoryKt; +import com.leeeyou.zhihudaily.model.bean.ZhiHuDailyDetail; import com.xyz.leeeyou.zhihuribao.R; -import com.xyz.leeeyou.zhihuribao.data.model.ribao.ZhiHuDailyDetail; -import com.xyz.leeeyou.zhihuribao.di.module.ZhiHuDailyRepositoryKt; -import com.xyz.leeeyou.zhihuribao.utils.HtmlUtils; import rx.Subscriber; import rx.android.schedulers.AndroidSchedulers; diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/ZhiHuDailyFragment.java b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.java similarity index 91% rename from app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/ZhiHuDailyFragment.java rename to app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.java index fb3fbaf..c91c9c5 100644 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/view/fragment/ZhiHuDailyFragment.java +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.java @@ -1,4 +1,4 @@ -package com.xyz.leeeyou.zhihuribao.view.fragment; +package com.leeeyou.zhihudaily.view; import android.os.Bundle; import android.support.annotation.NonNull; @@ -10,13 +10,12 @@ import android.view.ViewGroup; import com.chad.library.adapter.base.BaseQuickAdapter; +import com.leeeyou.BaseFragment; +import com.leeeyou.IndexActivity; +import com.leeeyou.zhihudaily.model.ZhiHuDailyRepositoryKt; +import com.leeeyou.zhihudaily.model.bean.ZhiHuDaily; +import com.leeeyou.zhihudaily.model.bean.ZhiHuDailyItem; import com.xyz.leeeyou.zhihuribao.R; -import com.xyz.leeeyou.zhihuribao.adapter.ZhiHuDailyAdapter; -import com.xyz.leeeyou.zhihuribao.data.model.ribao.ZhiHuDaily; -import com.xyz.leeeyou.zhihuribao.data.model.ribao.ZhiHuDailyItem; -import com.xyz.leeeyou.zhihuribao.di.module.ZhiHuDailyRepositoryKt; -import com.xyz.leeeyou.zhihuribao.utils.T; -import com.xyz.leeeyou.zhihuribao.view.activity.IndexActivity; import org.joda.time.DateTime; @@ -116,7 +115,7 @@ public void onCompleted() { public void onError(Throwable e) { ((IndexActivity) getActivity()).refreshComplete(); e.printStackTrace(); - T.showShort(getActivity(), "出错了:" + e.getMessage()); + com.leeeyou.util.T.showShort(getActivity(), "出错了:" + e.getMessage()); } @Override diff --git a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/ZhiHuDailyRepository.kt b/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/ZhiHuDailyRepository.kt deleted file mode 100644 index ab2aa62..0000000 --- a/app/src/main/java/com/xyz/leeeyou/zhihuribao/di/module/ZhiHuDailyRepository.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.xyz.leeeyou.zhihuribao.di.module - -import com.xyz.leeeyou.zhihuribao.data.model.ribao.ZhiHuDaily -import com.xyz.leeeyou.zhihuribao.data.model.ribao.ZhiHuDailyDetail -import com.xyz.leeeyou.zhihuribao.data.service.ServiceFactory -import com.xyz.leeeyou.zhihuribao.data.service.ZhiHuRiBaoService -import rx.Observable - -private const val endPoint = "http://news-at.zhihu.com/" - -fun fetchStoryListByDate(date: String): Observable { - return ServiceFactory - .createRxRetrofitService(ZhiHuRiBaoService::class.java, endPoint) - .getLatestZhiHuDaily(date) -} - -fun fetchStoryDetailById(storyId: Int): Observable { - return ServiceFactory - .createRxRetrofitService(ZhiHuRiBaoService::class.java, endPoint) - .getZhiHuDailyDetailById(storyId) -} \ No newline at end of file From c20092aea82d03f01337a0d2caca793b1c52e651 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Fri, 21 Dec 2018 17:51:46 +0800 Subject: [PATCH 031/150] =?UTF-8?q?Change=20Story=20module=20name=20to=20Z?= =?UTF-8?q?hiHuDaily=20module=EF=BC=8CDelete=20BaseFragment=20method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...riginalActivity.java => BaseActivity.java} | 3 +- .../java/com/leeeyou/BaseCenterActivity.java | 74 ----------------- app/src/main/java/com/leeeyou/BaseFragment.kt | 5 +- .../main/java/com/leeeyou/IndexActivity.kt | 23 +----- .../java/com/leeeyou/util/ToolbarHelper.java | 2 +- .../leeeyou/{ => util}/ViewPagerAdapter.kt | 19 +---- .../leeeyou/wanandroid/WanAndroidFragment.kt | 12 +-- .../wanandroid/WanAndroidProjectFragment.kt | 10 +-- .../wanandroid/WanAndroidRecommendFragment.kt | 10 +-- .../wanandroid/WanAndroidSystemFragment.kt | 10 +-- .../com/leeeyou/weather/WeatherFragment.kt | 8 -- .../zhihudaily/model/ZhiHuDailyRepository.kt | 4 +- .../view/ZhiHuDailyDetailActivity.java | 8 +- .../zhihudaily/view/ZhiHuDailyFragment.java | 82 ++++++++++--------- app/src/main/res/layout/activity_index.xml | 24 ++++-- app/src/main/res/layout/activity_story.xml | 5 -- .../main/res/layout/activity_zhihu_daily.xml | 13 +++ app/src/main/res/layout/fragment_one.xml | 2 +- .../main/res/layout/fragment_wan_android.xml | 2 +- .../layout/fragment_wan_android_project.xml | 2 +- .../layout/fragment_wan_android_recommend.xml | 2 +- .../layout/fragment_wan_android_system.xml | 2 +- app/src/main/res/layout/fragment_weather.xml | 2 +- ...item_lv_story.xml => item_zhihu_daily.xml} | 0 24 files changed, 97 insertions(+), 227 deletions(-) rename app/src/main/java/com/leeeyou/{BaseOriginalActivity.java => BaseActivity.java} (92%) delete mode 100644 app/src/main/java/com/leeeyou/BaseCenterActivity.java rename app/src/main/java/com/leeeyou/{ => util}/ViewPagerAdapter.kt (64%) delete mode 100644 app/src/main/res/layout/activity_story.xml create mode 100644 app/src/main/res/layout/activity_zhihu_daily.xml rename app/src/main/res/layout/{item_lv_story.xml => item_zhihu_daily.xml} (100%) diff --git a/app/src/main/java/com/leeeyou/BaseOriginalActivity.java b/app/src/main/java/com/leeeyou/BaseActivity.java similarity index 92% rename from app/src/main/java/com/leeeyou/BaseOriginalActivity.java rename to app/src/main/java/com/leeeyou/BaseActivity.java index b487dc7..17550bf 100644 --- a/app/src/main/java/com/leeeyou/BaseOriginalActivity.java +++ b/app/src/main/java/com/leeeyou/BaseActivity.java @@ -4,7 +4,6 @@ import android.support.v7.app.AppCompatActivity; import android.view.View; -import com.xyz.leeeyou.zhihuribao.R; import com.leeeyou.util.ToolbarHelper; /** @@ -14,7 +13,7 @@ * Author: leeeyou * Date: 2017/8/17 09:19 */ -public abstract class BaseOriginalActivity extends AppCompatActivity { +public abstract class BaseActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { diff --git a/app/src/main/java/com/leeeyou/BaseCenterActivity.java b/app/src/main/java/com/leeeyou/BaseCenterActivity.java deleted file mode 100644 index a5b8361..0000000 --- a/app/src/main/java/com/leeeyou/BaseCenterActivity.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.leeeyou; - -import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; -import android.view.View; -import android.widget.TextView; - -import com.xyz.leeeyou.zhihuribao.R; -import com.leeeyou.util.ToolbarHelper; - -/** - * ClassName: BaseCenterActivity - * Description: The title can be centered - * - * Author: leeeyou - * Date: 2017/8/17 09:19 - */ -public abstract class BaseCenterActivity extends AppCompatActivity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - super.setContentView(R.layout.activity_base_center); - ToolbarHelper.checkSdkVersionToTranslucentFlag(getWindow()); - } - - @Override - public void setContentView(int layoutResID) { - ToolbarHelper.setContentView(this, layoutResID); - } - - @Override - public void setContentView(View view) { - ToolbarHelper.setContentView(this, view); - } - - private void setCenterTitle(String title) { - TextView toolbar_center_title = switchCenterTextVisible(View.VISIBLE); - toolbar_center_title.setText(title); - } - - private TextView switchCenterTextVisible(int visible) { - TextView toolbar_center_title = (TextView) findViewById(R.id.toolbar_center_title); - if (toolbar_center_title != null) { - toolbar_center_title.setVisibility(visible); - } - return toolbar_center_title; - } - - public void setLeftTitleAndDoNotDisplayHomeAsUp(String title) { - ToolbarHelper.setLeftTitle(getSupportActionBar(), title); - ToolbarHelper.hideHomeAsUp(getSupportActionBar()); - } - - public void setLeftTitleAndDisplayHomeAsUp(String title) { - ToolbarHelper.setLeftTitle(getSupportActionBar(), title); - ToolbarHelper.showHomeAsUp(getSupportActionBar()); - } - - public void setLeftTitleAndHideCenterText(String title) { - ToolbarHelper.setLeftTitle(getSupportActionBar(), title); - ToolbarHelper.hideHomeAsUp(getSupportActionBar()); - - switchCenterTextVisible(View.GONE); - } - - public void setCenterTitleOnly(String title) { - ToolbarHelper.setLeftTitle(getSupportActionBar(), null); - ToolbarHelper.hideHomeAsUp(getSupportActionBar()); - - setCenterTitle(title); - } - -} diff --git a/app/src/main/java/com/leeeyou/BaseFragment.kt b/app/src/main/java/com/leeeyou/BaseFragment.kt index 7395176..073996f 100644 --- a/app/src/main/java/com/leeeyou/BaseFragment.kt +++ b/app/src/main/java/com/leeeyou/BaseFragment.kt @@ -7,7 +7,4 @@ import android.support.v4.app.Fragment * @description: fragment base class * @date: 2017/4/26 */ -abstract class BaseFragment : Fragment() { - abstract fun checkCanDoRefresh(): Boolean - abstract fun updateData() -} \ No newline at end of file +abstract class BaseFragment : Fragment() \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/IndexActivity.kt b/app/src/main/java/com/leeeyou/IndexActivity.kt index 194e96e..730fce6 100644 --- a/app/src/main/java/com/leeeyou/IndexActivity.kt +++ b/app/src/main/java/com/leeeyou/IndexActivity.kt @@ -1,17 +1,15 @@ package com.leeeyou -import `in`.srain.cube.views.ptr.PtrFrameLayout -import `in`.srain.cube.views.ptr.PtrHandler import android.os.Bundle import android.support.v4.view.ViewPager -import android.view.View +import com.leeeyou.util.ViewPagerAdapter import com.leeeyou.wanandroid.WanAndroidFragment import com.leeeyou.weather.WeatherFragment import kotlinx.android.synthetic.main.activity_index.* private const val FIRST_PAGE_INDEX: Int = 0 -class IndexActivity : BaseOriginalActivity() { +class IndexActivity : BaseActivity() { private lateinit var mViewPagerAdapter: ViewPagerAdapter @@ -20,7 +18,6 @@ class IndexActivity : BaseOriginalActivity() { setContentView(R.layout.activity_index) initAdapter() initViewPager() - initPtr() } private fun initViewPager() { @@ -49,20 +46,4 @@ class IndexActivity : BaseOriginalActivity() { mViewPagerAdapter.switchTo(FIRST_PAGE_INDEX) } - private fun initPtr() { - store_house_ptr_frame.disableWhenHorizontalMove(true) - store_house_ptr_frame.setPtrHandler(object : PtrHandler { - override fun onRefreshBegin(frame: PtrFrameLayout?) { - mViewPagerAdapter.updateData() - } - - override fun checkCanDoRefresh(frame: PtrFrameLayout?, content: View?, header: View?): - Boolean = mViewPagerAdapter.checkCanDoRefresh() - }) - } - - fun refreshComplete() { - store_house_ptr_frame.refreshComplete() - } - } diff --git a/app/src/main/java/com/leeeyou/util/ToolbarHelper.java b/app/src/main/java/com/leeeyou/util/ToolbarHelper.java index 287f9f6..95d1ad1 100644 --- a/app/src/main/java/com/leeeyou/util/ToolbarHelper.java +++ b/app/src/main/java/com/leeeyou/util/ToolbarHelper.java @@ -10,7 +10,7 @@ import android.view.WindowManager; import android.widget.LinearLayout; -import com.xyz.leeeyou.zhihuribao.R; +import com.leeeyou.R; /** * ClassName: ToolbarHelper diff --git a/app/src/main/java/com/leeeyou/ViewPagerAdapter.kt b/app/src/main/java/com/leeeyou/util/ViewPagerAdapter.kt similarity index 64% rename from app/src/main/java/com/leeeyou/ViewPagerAdapter.kt rename to app/src/main/java/com/leeeyou/util/ViewPagerAdapter.kt index f896066..9f94a4b 100644 --- a/app/src/main/java/com/leeeyou/ViewPagerAdapter.kt +++ b/app/src/main/java/com/leeeyou/util/ViewPagerAdapter.kt @@ -1,8 +1,9 @@ -package com.leeeyou +package com.leeeyou.util import android.support.v4.app.Fragment import android.support.v4.app.FragmentManager import android.support.v4.app.FragmentStatePagerAdapter +import com.leeeyou.BaseFragment /** * ClassName: ViewPagerAdapter @@ -13,7 +14,8 @@ import android.support.v4.app.FragmentStatePagerAdapter */ class ViewPagerAdapter(fm: FragmentManager, private val mFragmentList: Array, - private val titleList: Array) : FragmentStatePagerAdapter(fm) { + private val titleList: Array) + : FragmentStatePagerAdapter(fm) { private var mCurrentFragment: BaseFragment? = null @@ -21,19 +23,6 @@ class ViewPagerAdapter(fm: FragmentManager, override fun getCount(): Int = mFragmentList.size - fun updateData() { - if (mCurrentFragment == null) return - - return mCurrentFragment!!.updateData() - } - - fun checkCanDoRefresh(): Boolean { - if (mCurrentFragment == null) { - return true - } - return mCurrentFragment!!.checkCanDoRefresh() - } - fun switchTo(position: Int) { mCurrentFragment = mFragmentList[position] } diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidFragment.kt index 0000923..b5fac51 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidFragment.kt @@ -4,10 +4,10 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import com.leeeyou.ViewPagerAdapter -import com.leeeyou.util.inflate import com.leeeyou.BaseFragment import com.leeeyou.R +import com.leeeyou.util.ViewPagerAdapter +import com.leeeyou.util.inflate import kotlinx.android.synthetic.main.fragment_wan_android.* /** @@ -20,14 +20,6 @@ import kotlinx.android.synthetic.main.fragment_wan_android.* class WanAndroidFragment : BaseFragment() { private lateinit var mViewPagerAdapter: ViewPagerAdapter - override fun updateData() { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. - } - - override fun checkCanDoRefresh(): Boolean { - return false - } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return container?.inflate(R.layout.fragment_wan_android) } diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt index 8aea863..325d190 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt @@ -4,9 +4,9 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import com.leeeyou.util.inflate import com.leeeyou.BaseFragment import com.leeeyou.R +import com.leeeyou.util.inflate /** * ClassName: WeatherFragment @@ -16,14 +16,6 @@ import com.leeeyou.R * Date: 2017/4/24 13:46 */ class WanAndroidProjectFragment : BaseFragment() { - override fun updateData() { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. - } - - override fun checkCanDoRefresh(): Boolean { - return false - } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return container?.inflate(R.layout.fragment_wan_android_project) } diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt index d62d0e2..c644685 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt @@ -4,9 +4,9 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import com.leeeyou.util.inflate import com.leeeyou.BaseFragment import com.leeeyou.R +import com.leeeyou.util.inflate /** * ClassName: WeatherFragment @@ -16,14 +16,6 @@ import com.leeeyou.R * Date: 2017/4/24 13:46 */ class WanAndroidRecommendFragment : BaseFragment() { - override fun updateData() { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. - } - - override fun checkCanDoRefresh(): Boolean { - return true - } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return container?.inflate(R.layout.fragment_wan_android_recommend) } diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt index 8ed8297..a028c7e 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt @@ -4,9 +4,9 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import com.leeeyou.util.inflate import com.leeeyou.BaseFragment import com.leeeyou.R +import com.leeeyou.util.inflate /** * ClassName: WeatherFragment @@ -16,14 +16,6 @@ import com.leeeyou.R * Date: 2017/4/24 13:46 */ class WanAndroidSystemFragment : BaseFragment() { - override fun updateData() { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. - } - - override fun checkCanDoRefresh(): Boolean { - return false - } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return container?.inflate(R.layout.fragment_wan_android_system) } diff --git a/app/src/main/java/com/leeeyou/weather/WeatherFragment.kt b/app/src/main/java/com/leeeyou/weather/WeatherFragment.kt index 0fdc593..f0ed0eb 100644 --- a/app/src/main/java/com/leeeyou/weather/WeatherFragment.kt +++ b/app/src/main/java/com/leeeyou/weather/WeatherFragment.kt @@ -16,14 +16,6 @@ import com.leeeyou.util.inflate * Date: 2017/4/24 13:46 */ class WeatherFragment : BaseFragment() { - override fun updateData() { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. - } - - override fun checkCanDoRefresh(): Boolean { - return false - } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return container?.inflate(R.layout.fragment_weather) } diff --git a/app/src/main/java/com/leeeyou/zhihudaily/model/ZhiHuDailyRepository.kt b/app/src/main/java/com/leeeyou/zhihudaily/model/ZhiHuDailyRepository.kt index 34f9972..5929cbf 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/model/ZhiHuDailyRepository.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/model/ZhiHuDailyRepository.kt @@ -8,13 +8,13 @@ import rx.Observable private const val endPoint = "http://news-at.zhihu.com/" -fun fetchStoryListByDate(date: String): Observable { +fun fetchZhiHuDailyListByDate(date: String): Observable { return ServiceFactory .createRxRetrofitService(ZhiHuDailyService::class.java, endPoint) .getLatestZhiHuDaily(date) } -fun fetchStoryDetailById(storyId: Int): Observable { +fun fetchZhiHuDailyDetailById(storyId: Int): Observable { return ServiceFactory .createRxRetrofitService(ZhiHuDailyService::class.java, endPoint) .getZhiHuDailyDetailById(storyId) diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.java b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.java index 688d964..2f2e3be 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.java +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.java @@ -3,18 +3,18 @@ import android.os.Bundle; import android.webkit.WebView; -import com.leeeyou.BaseOriginalActivity; +import com.leeeyou.BaseActivity; +import com.leeeyou.R; import com.leeeyou.util.HtmlUtils; import com.leeeyou.zhihudaily.model.ZhiHuDailyRepositoryKt; import com.leeeyou.zhihudaily.model.bean.ZhiHuDailyDetail; -import com.xyz.leeeyou.zhihuribao.R; import rx.Subscriber; import rx.android.schedulers.AndroidSchedulers; import rx.functions.Action0; import rx.schedulers.Schedulers; -public class ZhiHuDailyDetailActivity extends BaseOriginalActivity { +public class ZhiHuDailyDetailActivity extends BaseActivity { private int storyId; @@ -43,7 +43,7 @@ private void initWebView() { public void getStoryDetail() { ZhiHuDailyRepositoryKt - .fetchStoryDetailById(storyId) + .fetchZhiHuDailyDetailById(storyId) .subscribeOn(Schedulers.newThread()) .doOnSubscribe(new Action0() { @Override diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.java b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.java index c91c9c5..382fcf4 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.java +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.java @@ -11,25 +11,26 @@ import com.chad.library.adapter.base.BaseQuickAdapter; import com.leeeyou.BaseFragment; -import com.leeeyou.IndexActivity; +import com.leeeyou.R; import com.leeeyou.zhihudaily.model.ZhiHuDailyRepositoryKt; import com.leeeyou.zhihudaily.model.bean.ZhiHuDaily; import com.leeeyou.zhihudaily.model.bean.ZhiHuDailyItem; -import com.xyz.leeeyou.zhihuribao.R; import org.joda.time.DateTime; import java.util.List; -import rx.Observable; +import in.srain.cube.views.ptr.PtrClassicFrameLayout; +import in.srain.cube.views.ptr.PtrDefaultHandler; +import in.srain.cube.views.ptr.PtrFrameLayout; import rx.Subscriber; import rx.android.schedulers.AndroidSchedulers; import rx.functions.Func1; import rx.schedulers.Schedulers; /** - * ClassName: StoryFragment - * Description: 【知乎日报】fragment , Java style + * ClassName: ZhiHuDailyFragment + * Description: ZhiHuDailyFragment *

* Author: leeeyou * Date: 2017/4/24 13:46 @@ -37,6 +38,7 @@ public class ZhiHuDailyFragment extends BaseFragment { private RecyclerView mRecyclerView; + private PtrClassicFrameLayout mPtrFrame; private ZhiHuDailyAdapter mAdapter; //when loading more, up to the date of the data can be loaded @@ -44,26 +46,42 @@ public class ZhiHuDailyFragment extends BaseFragment { private int mDatePosition = 0; private int mMostDate = 7; - Observable storyObservable; - @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - View inflate = inflater.inflate(R.layout.activity_story, container, false); - mRecyclerView = (RecyclerView) inflate.findViewById(R.id.recyclerViewRiBao); + View inflate = inflater.inflate(R.layout.activity_zhihu_daily, container, false); + mRecyclerView = inflate.findViewById(R.id.recyclerViewRiBao); + mPtrFrame = inflate.findViewById(R.id.ptrFrame); return inflate; } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - initDateList(); + initView(); + fetchZhiHuDailyList(); + } + + private void initView() { + mPtrFrame.disableWhenHorizontalMove(true); + mPtrFrame.setPtrHandler(new PtrDefaultHandler() { + @Override + public void onRefreshBegin(PtrFrameLayout frame) { + mDatePosition = 0; + fetchZhiHuDailyList(); + } + + @Override + public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) { + return !mRecyclerView.canScrollVertically(-1); + } + }); + initAdapter(); - updateData(); } private void initAdapter() { - mAdapter = new ZhiHuDailyAdapter(R.layout.item_lv_story, null); + mAdapter = new ZhiHuDailyAdapter(R.layout.item_zhihu_daily, null); mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false)); mRecyclerView.setAdapter(mAdapter); @@ -72,8 +90,7 @@ private void initAdapter() { @Override public void onLoadMoreRequested() { if (mDatePosition < mMostDate - 1) { - storyObservable = ZhiHuDailyRepositoryKt.fetchStoryListByDate(dateList[++mDatePosition]); - fetchStoryData(); + fetchZhiHuDailyList(); } else { mAdapter.loadMoreEnd(); } @@ -81,8 +98,9 @@ public void onLoadMoreRequested() { }, mRecyclerView); } - private void fetchStoryData() { - storyObservable + private void fetchZhiHuDailyList() { + ZhiHuDailyRepositoryKt + .fetchZhiHuDailyListByDate(dateList[++mDatePosition]) .subscribeOn(Schedulers.newThread()) .filter(new Func1() { @Override @@ -97,8 +115,8 @@ public Boolean call(ZhiHuDaily riBao) { } List stories = riBao.getStories(); - for (ZhiHuDailyItem story : stories) { - story.setDate(sb.toString()); + for (ZhiHuDailyItem item : stories) { + item.setDate(sb.toString()); } return true; @@ -113,24 +131,24 @@ public void onCompleted() { @Override public void onError(Throwable e) { - ((IndexActivity) getActivity()).refreshComplete(); + mPtrFrame.refreshComplete(); e.printStackTrace(); com.leeeyou.util.T.showShort(getActivity(), "出错了:" + e.getMessage()); } @Override - public void onNext(ZhiHuDaily ribao) { - ((IndexActivity) getActivity()).refreshComplete(); - setDataToAdapter(ribao.getStories()); + public void onNext(ZhiHuDaily zhiHuDaily) { + mPtrFrame.refreshComplete(); + setDataToAdapter(zhiHuDaily.getStories()); } }); } - private void setDataToAdapter(@NonNull List stories) { + private void setDataToAdapter(@NonNull List zhiHuDailyItemList) { if (mDatePosition == 0) { - mAdapter.setNewData(stories); + mAdapter.setNewData(zhiHuDailyItemList); } else { - mAdapter.addData(stories); + mAdapter.addData(zhiHuDailyItemList); } } @@ -143,18 +161,4 @@ private void initDateList() { (tempDateTime.getDayOfMonth() < 10 ? "0" + tempDateTime.getDayOfMonth() : tempDateTime.getDayOfMonth()); } } - - @Override - public boolean checkCanDoRefresh() { - return !mRecyclerView.canScrollVertically(-1); - } - - @Override - public void updateData() { - mAdapter.removeAllFooterView(); - mDatePosition = 0; - storyObservable = ZhiHuDailyRepositoryKt.fetchStoryListByDate(dateList[mDatePosition]); - fetchStoryData(); - } - } diff --git a/app/src/main/res/layout/activity_index.xml b/app/src/main/res/layout/activity_index.xml index 8934d0e..e3aa48c 100644 --- a/app/src/main/res/layout/activity_index.xml +++ b/app/src/main/res/layout/activity_index.xml @@ -15,17 +15,23 @@ app:tabTextAppearance="@android:style/TextAppearance.Widget.TabWidget" app:tabTextColor="#000000"/> - + android:layout_height="match_parent" + android:layout_below="@id/smartTabLayout"/> - - + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_story.xml b/app/src/main/res/layout/activity_story.xml deleted file mode 100644 index 895ff5f..0000000 --- a/app/src/main/res/layout/activity_story.xml +++ /dev/null @@ -1,5 +0,0 @@ - - diff --git a/app/src/main/res/layout/activity_zhihu_daily.xml b/app/src/main/res/layout/activity_zhihu_daily.xml new file mode 100644 index 0000000..cb8c760 --- /dev/null +++ b/app/src/main/res/layout/activity_zhihu_daily.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_one.xml b/app/src/main/res/layout/fragment_one.xml index 5c0922c..950b00f 100755 --- a/app/src/main/res/layout/fragment_one.xml +++ b/app/src/main/res/layout/fragment_one.xml @@ -1,5 +1,5 @@ diff --git a/app/src/main/res/layout/fragment_wan_android.xml b/app/src/main/res/layout/fragment_wan_android.xml index a0332dc..a432d0e 100644 --- a/app/src/main/res/layout/fragment_wan_android.xml +++ b/app/src/main/res/layout/fragment_wan_android.xml @@ -17,7 +17,7 @@ app:tabTextColor="#000000"/> diff --git a/app/src/main/res/layout/fragment_wan_android_project.xml b/app/src/main/res/layout/fragment_wan_android_project.xml index 822e843..fe69edd 100644 --- a/app/src/main/res/layout/fragment_wan_android_project.xml +++ b/app/src/main/res/layout/fragment_wan_android_project.xml @@ -1,5 +1,5 @@ diff --git a/app/src/main/res/layout/fragment_wan_android_recommend.xml b/app/src/main/res/layout/fragment_wan_android_recommend.xml index 9469e4a..0dfed88 100644 --- a/app/src/main/res/layout/fragment_wan_android_recommend.xml +++ b/app/src/main/res/layout/fragment_wan_android_recommend.xml @@ -1,5 +1,5 @@ diff --git a/app/src/main/res/layout/fragment_wan_android_system.xml b/app/src/main/res/layout/fragment_wan_android_system.xml index e938bbe..4fa09c6 100644 --- a/app/src/main/res/layout/fragment_wan_android_system.xml +++ b/app/src/main/res/layout/fragment_wan_android_system.xml @@ -1,5 +1,5 @@ diff --git a/app/src/main/res/layout/fragment_weather.xml b/app/src/main/res/layout/fragment_weather.xml index 2a507ee..5918f1c 100644 --- a/app/src/main/res/layout/fragment_weather.xml +++ b/app/src/main/res/layout/fragment_weather.xml @@ -1,5 +1,5 @@ diff --git a/app/src/main/res/layout/item_lv_story.xml b/app/src/main/res/layout/item_zhihu_daily.xml similarity index 100% rename from app/src/main/res/layout/item_lv_story.xml rename to app/src/main/res/layout/item_zhihu_daily.xml From cef070a1544d323b1b4f4a583950ae394682daac Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Fri, 21 Dec 2018 18:04:59 +0800 Subject: [PATCH 032/150] Add Comment --- app/src/main/java/com/leeeyou/BaseFragment.kt | 10 ---------- app/src/main/java/com/leeeyou/IndexActivity.kt | 7 +++++++ .../java/com/leeeyou/{ => factory}/ServiceFactory.kt | 4 ++-- .../java/com/leeeyou/{ => manager}/BaseActivity.java | 5 +++-- .../main/java/com/leeeyou/manager/BaseFragment.kt | 12 ++++++++++++ .../main/java/com/leeeyou/util/ViewPagerAdapter.kt | 2 +- .../com/leeeyou/wanandroid/WanAndroidFragment.kt | 4 ++-- .../leeeyou/wanandroid/WanAndroidProjectFragment.kt | 4 ++-- .../wanandroid/WanAndroidRecommendFragment.kt | 4 ++-- .../leeeyou/wanandroid/WanAndroidSystemFragment.kt | 4 ++-- .../main/java/com/leeeyou/weather/WeatherFragment.kt | 6 +++--- .../leeeyou/zhihudaily/model/ZhiHuDailyRepository.kt | 2 +- .../com/leeeyou/zhihudaily/model/bean/ZhiHuDaily.kt | 2 +- .../leeeyou/zhihudaily/service/ZhiHuDailyService.kt | 3 +-- .../com/leeeyou/zhihudaily/view/ZhiHuDailyAdapter.kt | 2 +- .../zhihudaily/view/ZhiHuDailyDetailActivity.java | 9 ++++++++- .../leeeyou/zhihudaily/view/ZhiHuDailyFragment.java | 3 +-- 17 files changed, 49 insertions(+), 34 deletions(-) delete mode 100644 app/src/main/java/com/leeeyou/BaseFragment.kt rename app/src/main/java/com/leeeyou/{ => factory}/ServiceFactory.kt (94%) rename app/src/main/java/com/leeeyou/{ => manager}/BaseActivity.java (94%) create mode 100644 app/src/main/java/com/leeeyou/manager/BaseFragment.kt diff --git a/app/src/main/java/com/leeeyou/BaseFragment.kt b/app/src/main/java/com/leeeyou/BaseFragment.kt deleted file mode 100644 index 073996f..0000000 --- a/app/src/main/java/com/leeeyou/BaseFragment.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.leeeyou - -import android.support.v4.app.Fragment - -/** - * @author: leeeyou - * @description: fragment base class - * @date: 2017/4/26 - */ -abstract class BaseFragment : Fragment() \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/IndexActivity.kt b/app/src/main/java/com/leeeyou/IndexActivity.kt index 730fce6..a740297 100644 --- a/app/src/main/java/com/leeeyou/IndexActivity.kt +++ b/app/src/main/java/com/leeeyou/IndexActivity.kt @@ -2,6 +2,7 @@ package com.leeeyou import android.os.Bundle import android.support.v4.view.ViewPager +import com.leeeyou.manager.BaseActivity import com.leeeyou.util.ViewPagerAdapter import com.leeeyou.wanandroid.WanAndroidFragment import com.leeeyou.weather.WeatherFragment @@ -9,6 +10,12 @@ import kotlinx.android.synthetic.main.activity_index.* private const val FIRST_PAGE_INDEX: Int = 0 +/** + * ClassName: IndexActivity + * + * Author: leeeyou + * Date: 2018/12/21 18:02 + */ class IndexActivity : BaseActivity() { private lateinit var mViewPagerAdapter: ViewPagerAdapter diff --git a/app/src/main/java/com/leeeyou/ServiceFactory.kt b/app/src/main/java/com/leeeyou/factory/ServiceFactory.kt similarity index 94% rename from app/src/main/java/com/leeeyou/ServiceFactory.kt rename to app/src/main/java/com/leeeyou/factory/ServiceFactory.kt index f170d77..ced94cc 100644 --- a/app/src/main/java/com/leeeyou/ServiceFactory.kt +++ b/app/src/main/java/com/leeeyou/factory/ServiceFactory.kt @@ -1,11 +1,11 @@ -package com.leeeyou +package com.leeeyou.factory import retrofit.GsonConverterFactory import retrofit.Retrofit import retrofit.RxJavaCallAdapterFactory /** - * ClassName: ServiceFactory + * ClassName: ServiceFactory * Description: The factory class mainly offers two kinds of Retrofit services, Rx mode and normal mode * * Author: leeeyou diff --git a/app/src/main/java/com/leeeyou/BaseActivity.java b/app/src/main/java/com/leeeyou/manager/BaseActivity.java similarity index 94% rename from app/src/main/java/com/leeeyou/BaseActivity.java rename to app/src/main/java/com/leeeyou/manager/BaseActivity.java index 17550bf..58247e5 100644 --- a/app/src/main/java/com/leeeyou/BaseActivity.java +++ b/app/src/main/java/com/leeeyou/manager/BaseActivity.java @@ -1,13 +1,14 @@ -package com.leeeyou; +package com.leeeyou.manager; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; +import com.leeeyou.R; import com.leeeyou.util.ToolbarHelper; /** - * ClassName: BaseOriginalActivity + * ClassName: BaseActivity * Description: Toolbar native style * * Author: leeeyou diff --git a/app/src/main/java/com/leeeyou/manager/BaseFragment.kt b/app/src/main/java/com/leeeyou/manager/BaseFragment.kt new file mode 100644 index 0000000..10d61a7 --- /dev/null +++ b/app/src/main/java/com/leeeyou/manager/BaseFragment.kt @@ -0,0 +1,12 @@ +package com.leeeyou.manager + +import android.support.v4.app.Fragment + +/** + * ClassName: BaseFragment + * Description: fragment base class + * + * Author: leeeyou + * Date: 2018/12/21 17:58 + */ +abstract class BaseFragment : Fragment() \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/util/ViewPagerAdapter.kt b/app/src/main/java/com/leeeyou/util/ViewPagerAdapter.kt index 9f94a4b..51eb061 100644 --- a/app/src/main/java/com/leeeyou/util/ViewPagerAdapter.kt +++ b/app/src/main/java/com/leeeyou/util/ViewPagerAdapter.kt @@ -3,7 +3,7 @@ package com.leeeyou.util import android.support.v4.app.Fragment import android.support.v4.app.FragmentManager import android.support.v4.app.FragmentStatePagerAdapter -import com.leeeyou.BaseFragment +import com.leeeyou.manager.BaseFragment /** * ClassName: ViewPagerAdapter diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidFragment.kt index b5fac51..21a8b7e 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidFragment.kt @@ -4,15 +4,15 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import com.leeeyou.BaseFragment import com.leeeyou.R +import com.leeeyou.manager.BaseFragment import com.leeeyou.util.ViewPagerAdapter import com.leeeyou.util.inflate import kotlinx.android.synthetic.main.fragment_wan_android.* /** * ClassName: WanAndroidFragment - * Description: 玩Android + * Description: Play Android * * Author: leeeyou * Date: 2017/4/24 13:46 diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt index 325d190..12c6f6f 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt @@ -4,13 +4,13 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import com.leeeyou.BaseFragment import com.leeeyou.R +import com.leeeyou.manager.BaseFragment import com.leeeyou.util.inflate /** * ClassName: WeatherFragment - * Description: 项目展示 + * Description: Play Android - Project * * Author: leeeyou * Date: 2017/4/24 13:46 diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt index c644685..921f841 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt @@ -4,13 +4,13 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import com.leeeyou.BaseFragment import com.leeeyou.R +import com.leeeyou.manager.BaseFragment import com.leeeyou.util.inflate /** * ClassName: WeatherFragment - * Description: 推荐展示 + * Description: Play Android - Recommend * * Author: leeeyou * Date: 2017/4/24 13:46 diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt index a028c7e..76c8b9e 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt @@ -4,13 +4,13 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import com.leeeyou.BaseFragment import com.leeeyou.R +import com.leeeyou.manager.BaseFragment import com.leeeyou.util.inflate /** * ClassName: WeatherFragment - * Description: 体系展示 + * Description: Play Android - System * * Author: leeeyou * Date: 2017/4/24 13:46 diff --git a/app/src/main/java/com/leeeyou/weather/WeatherFragment.kt b/app/src/main/java/com/leeeyou/weather/WeatherFragment.kt index f0ed0eb..e06073e 100644 --- a/app/src/main/java/com/leeeyou/weather/WeatherFragment.kt +++ b/app/src/main/java/com/leeeyou/weather/WeatherFragment.kt @@ -4,13 +4,13 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import com.leeeyou.BaseFragment import com.leeeyou.R +import com.leeeyou.manager.BaseFragment import com.leeeyou.util.inflate /** - * ClassName: WeatherFragment - * Description: 天气展示 + * ClassName: WeatherFragment + * Description: Show Weather * * Author: leeeyou * Date: 2017/4/24 13:46 diff --git a/app/src/main/java/com/leeeyou/zhihudaily/model/ZhiHuDailyRepository.kt b/app/src/main/java/com/leeeyou/zhihudaily/model/ZhiHuDailyRepository.kt index 5929cbf..1934166 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/model/ZhiHuDailyRepository.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/model/ZhiHuDailyRepository.kt @@ -1,6 +1,6 @@ package com.leeeyou.zhihudaily.model -import com.leeeyou.ServiceFactory +import com.leeeyou.factory.ServiceFactory import com.leeeyou.zhihudaily.model.bean.ZhiHuDaily import com.leeeyou.zhihudaily.model.bean.ZhiHuDailyDetail import com.leeeyou.zhihudaily.service.ZhiHuDailyService diff --git a/app/src/main/java/com/leeeyou/zhihudaily/model/bean/ZhiHuDaily.kt b/app/src/main/java/com/leeeyou/zhihudaily/model/bean/ZhiHuDaily.kt index ffcf349..bda1aca 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/model/bean/ZhiHuDaily.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/model/bean/ZhiHuDaily.kt @@ -1,7 +1,7 @@ package com.leeeyou.zhihudaily.model.bean /** - * ClassName: + * ClassName: ZhiHuDaily * Description: The data class is a very powerful class that * lets you avoid creating boilerplate code in Java * that holds POJOs that are state-controlled but have a very simple operation. diff --git a/app/src/main/java/com/leeeyou/zhihudaily/service/ZhiHuDailyService.kt b/app/src/main/java/com/leeeyou/zhihudaily/service/ZhiHuDailyService.kt index c025611..ec50efa 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/service/ZhiHuDailyService.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/service/ZhiHuDailyService.kt @@ -7,8 +7,7 @@ import retrofit.http.Path import rx.Observable /** - * ClassName: ZhiHuRiBaoService - * Description: [ ZhiHuRiBao ] module service + * ClassName: ZhiHuRiBaoService * * Author: leeeyou * Date: 2018/4/24 15:14 diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyAdapter.kt b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyAdapter.kt index d3758ea..54c46c3 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyAdapter.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyAdapter.kt @@ -8,7 +8,7 @@ import com.leeeyou.R import com.leeeyou.zhihudaily.model.bean.ZhiHuDailyItem /** - * ClassName: StoryAdapter + * ClassName: ZhiHuDailyAdapter * Author: leeeyou * Date: 2016/9/27 14:45 */ diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.java b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.java index 2f2e3be..25ab33a 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.java +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.java @@ -3,7 +3,7 @@ import android.os.Bundle; import android.webkit.WebView; -import com.leeeyou.BaseActivity; +import com.leeeyou.manager.BaseActivity; import com.leeeyou.R; import com.leeeyou.util.HtmlUtils; import com.leeeyou.zhihudaily.model.ZhiHuDailyRepositoryKt; @@ -14,6 +14,13 @@ import rx.functions.Action0; import rx.schedulers.Schedulers; +/** + * ClassName: ZhiHuDailyDetailActivity + * Description: + * + * Author: leeeyou + * Date: 2018/12/21 18:02 + */ public class ZhiHuDailyDetailActivity extends BaseActivity { private int storyId; diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.java b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.java index 382fcf4..c2903d5 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.java +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.java @@ -10,7 +10,7 @@ import android.view.ViewGroup; import com.chad.library.adapter.base.BaseQuickAdapter; -import com.leeeyou.BaseFragment; +import com.leeeyou.manager.BaseFragment; import com.leeeyou.R; import com.leeeyou.zhihudaily.model.ZhiHuDailyRepositoryKt; import com.leeeyou.zhihudaily.model.bean.ZhiHuDaily; @@ -30,7 +30,6 @@ /** * ClassName: ZhiHuDailyFragment - * Description: ZhiHuDailyFragment *

* Author: leeeyou * Date: 2017/4/24 13:46 From 2da431836ca3fa815aefa29c5c6798833a1188c3 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Sun, 23 Dec 2018 10:34:01 +0800 Subject: [PATCH 033/150] fixbug : Program type already present: android.support.v13. --- app/build.gradle | 5 ++++- .../zhihudaily/view/ZhiHuDailyFragment.java | 4 ++-- app/src/main/res/layout/activity_index.xml | 15 +-------------- app/src/main/res/layout/activity_zhihu_daily.xml | 2 +- 4 files changed, 8 insertions(+), 18 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 68a4807..2eeaa5f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -55,6 +55,9 @@ android { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') + configurations { + all*.exclude group: 'com.android.support', module: 'support-v13' + } testImplementation 'junit:junit:4.12' //noinspection GradleCompatible implementation 'com.android.support:appcompat-v7:28.0.0' @@ -78,7 +81,7 @@ dependencies { implementation 'com.github.bumptech.glide:glide:4.6.1' implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.44' implementation 'net.danlew:android.joda:2.9.9.4' - implementation 'com.afollestad.material-dialogs:core:0.9.0.2' + implementation 'com.afollestad.material-dialogs:core:0.9.4.7' implementation 'in.srain.cube:ultra-ptr:1.0.11' } \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.java b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.java index c2903d5..88b17c8 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.java +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.java @@ -10,8 +10,8 @@ import android.view.ViewGroup; import com.chad.library.adapter.base.BaseQuickAdapter; -import com.leeeyou.manager.BaseFragment; import com.leeeyou.R; +import com.leeeyou.manager.BaseFragment; import com.leeeyou.zhihudaily.model.ZhiHuDailyRepositoryKt; import com.leeeyou.zhihudaily.model.bean.ZhiHuDaily; import com.leeeyou.zhihudaily.model.bean.ZhiHuDailyItem; @@ -49,7 +49,7 @@ public class ZhiHuDailyFragment extends BaseFragment { public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View inflate = inflater.inflate(R.layout.activity_zhihu_daily, container, false); mRecyclerView = inflate.findViewById(R.id.recyclerViewRiBao); - mPtrFrame = inflate.findViewById(R.id.ptrFrame); + mPtrFrame = inflate.findViewById(R.id.ptrFrameOfZhiHuDaily); return inflate; } diff --git a/app/src/main/res/layout/activity_index.xml b/app/src/main/res/layout/activity_index.xml index e3aa48c..6ceddc1 100644 --- a/app/src/main/res/layout/activity_index.xml +++ b/app/src/main/res/layout/activity_index.xml @@ -18,20 +18,7 @@ - - - - - - - - - - - - + android:layout_height="match_parent"/> diff --git a/app/src/main/res/layout/activity_zhihu_daily.xml b/app/src/main/res/layout/activity_zhihu_daily.xml index cb8c760..00d7798 100644 --- a/app/src/main/res/layout/activity_zhihu_daily.xml +++ b/app/src/main/res/layout/activity_zhihu_daily.xml @@ -1,7 +1,7 @@ From 4613f487839590a1a484c2e79e51b50eef84ceba Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Sun, 23 Dec 2018 10:54:58 +0800 Subject: [PATCH 034/150] Kotlin rewriting ZhiHuDailyDetailActivity.java --- app/src/main/AndroidManifest.xml | 2 +- .../zhihudaily/view/ZhiHuDailyAdapter.kt | 2 +- .../view/ZhiHuDailyDetailActivity.java | 85 ------------------- .../view/ZhiHuDailyDetailActivity.kt | 58 +++++++++++++ .../main/res/layout/activity_story_detail.xml | 12 ++- 5 files changed, 65 insertions(+), 94 deletions(-) delete mode 100644 app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.java create mode 100644 app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 10a623f..6d69dab 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -24,7 +24,7 @@ ?) vh.setText(R.id.tv_story_title, story.title) .setText(R.id.tv_story_time, story.date) .setOnClickListener(R.id.rl_item_recommend) { - mContext.startActivity(Intent(mContext, ZhiHuDailyDetailActivity::class.java) + mContext.startActivity(Intent(mContext, ZhiHuDailyDetailActivity2::class.java) .putExtra("storyId", story.id) .putExtra("storyTitle", story.title)) } diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.java b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.java deleted file mode 100644 index 25ab33a..0000000 --- a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.leeeyou.zhihudaily.view; - -import android.os.Bundle; -import android.webkit.WebView; - -import com.leeeyou.manager.BaseActivity; -import com.leeeyou.R; -import com.leeeyou.util.HtmlUtils; -import com.leeeyou.zhihudaily.model.ZhiHuDailyRepositoryKt; -import com.leeeyou.zhihudaily.model.bean.ZhiHuDailyDetail; - -import rx.Subscriber; -import rx.android.schedulers.AndroidSchedulers; -import rx.functions.Action0; -import rx.schedulers.Schedulers; - -/** - * ClassName: ZhiHuDailyDetailActivity - * Description: - * - * Author: leeeyou - * Date: 2018/12/21 18:02 - */ -public class ZhiHuDailyDetailActivity extends BaseActivity { - - private int storyId; - - WebView story_web; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_story_detail); - - story_web = findViewById(R.id.story_web); - - storyId = getIntent().getIntExtra("storyId", -1); - String storyTitle = getIntent().getStringExtra("storyTitle"); - - setLeftTitleAndDisplayHomeAsUp(storyTitle); - initWebView(); - getStoryDetail(); - } - - private void initWebView() { - story_web.setVerticalScrollBarEnabled(false); - story_web.getSettings().setDefaultTextEncodingName("UTF-8"); - } - - - public void getStoryDetail() { - ZhiHuDailyRepositoryKt - .fetchZhiHuDailyDetailById(storyId) - .subscribeOn(Schedulers.newThread()) - .doOnSubscribe(new Action0() { - @Override - public void call() { -// mMaterialDialog = new MaterialDialog.Builder(StoryDetailActivity.this) -// .content("Loading ...") -// .progress(true, 0) -// .show(); - } - }) - .subscribeOn(AndroidSchedulers.mainThread()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Subscriber() { - @Override - public void onCompleted() { -// mMaterialDialog.dismiss(); - } - - @Override - public void onError(Throwable e) { -// mMaterialDialog.dismiss(); - e.printStackTrace(); - } - - @Override - public void onNext(ZhiHuDailyDetail storyDetail) { - story_web.loadData(HtmlUtils.structHtml(storyDetail.getBody(), storyDetail.getCss()), "text/html; charset=UTF-8", null); - } - }); - } - -} diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.kt b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.kt new file mode 100644 index 0000000..210f4e9 --- /dev/null +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.kt @@ -0,0 +1,58 @@ +package com.leeeyou.zhihudaily.view + +import android.os.Bundle +import com.afollestad.materialdialogs.MaterialDialog +import com.leeeyou.R +import com.leeeyou.manager.BaseActivity +import com.leeeyou.util.HtmlUtils +import com.leeeyou.zhihudaily.model.bean.ZhiHuDailyDetail +import com.leeeyou.zhihudaily.model.fetchZhiHuDailyDetailById +import kotlinx.android.synthetic.main.activity_story_detail.* +import rx.Subscriber +import rx.android.schedulers.AndroidSchedulers +import rx.schedulers.Schedulers + +class ZhiHuDailyDetailActivity2 : BaseActivity() { + internal lateinit var mMaterialDialog: MaterialDialog + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_story_detail) + setLeftTitleAndDisplayHomeAsUp(intent.getStringExtra("storyTitle")) + initWebView() + fetchZhiHuDetail() + } + + private fun fetchZhiHuDetail() { + fetchZhiHuDailyDetailById(intent.getIntExtra("storyId", -1)) + .subscribeOn(Schedulers.newThread()) + .doOnSubscribe { + mMaterialDialog = MaterialDialog.Builder(this@ZhiHuDailyDetailActivity2) + .content("Loading...") + .progress(true, 0) + .show() + } + .subscribeOn(AndroidSchedulers.mainThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : Subscriber() { + override fun onCompleted() { + mMaterialDialog.dismiss() + } + + override fun onError(e: Throwable) { + mMaterialDialog.dismiss() + e.printStackTrace() + } + + override fun onNext(storyDetail: ZhiHuDailyDetail) { + zhiHuDailyWebview.loadData(HtmlUtils.structHtml(storyDetail.body, storyDetail.css), "text/html; charset=UTF-8", null) + } + }) + } + + private fun initWebView() { + zhiHuDailyWebview.isVerticalScrollBarEnabled = false + zhiHuDailyWebview.settings.defaultTextEncodingName = "UTF-8" + } + +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_story_detail.xml b/app/src/main/res/layout/activity_story_detail.xml index f562a7b..4f2837a 100644 --- a/app/src/main/res/layout/activity_story_detail.xml +++ b/app/src/main/res/layout/activity_story_detail.xml @@ -1,15 +1,13 @@ + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> - - + android:scrollbars="vertical"/> \ No newline at end of file From 51693e86833466cddeffffc60f62684a5afb36b6 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Sun, 23 Dec 2018 10:57:17 +0800 Subject: [PATCH 035/150] Kotlin rewriting ZhiHuDailyDetailActivity.java --- app/src/main/AndroidManifest.xml | 2 +- .../java/com/leeeyou/zhihudaily/view/ZhiHuDailyAdapter.kt | 2 +- .../com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.kt | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6d69dab..10a623f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -24,7 +24,7 @@ ?) vh.setText(R.id.tv_story_title, story.title) .setText(R.id.tv_story_time, story.date) .setOnClickListener(R.id.rl_item_recommend) { - mContext.startActivity(Intent(mContext, ZhiHuDailyDetailActivity2::class.java) + mContext.startActivity(Intent(mContext, ZhiHuDailyDetailActivity::class.java) .putExtra("storyId", story.id) .putExtra("storyTitle", story.title)) } diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.kt b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.kt index 210f4e9..cda7705 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.kt @@ -12,7 +12,7 @@ import rx.Subscriber import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers -class ZhiHuDailyDetailActivity2 : BaseActivity() { +class ZhiHuDailyDetailActivity : BaseActivity() { internal lateinit var mMaterialDialog: MaterialDialog override fun onCreate(savedInstanceState: Bundle?) { @@ -27,7 +27,7 @@ class ZhiHuDailyDetailActivity2 : BaseActivity() { fetchZhiHuDailyDetailById(intent.getIntExtra("storyId", -1)) .subscribeOn(Schedulers.newThread()) .doOnSubscribe { - mMaterialDialog = MaterialDialog.Builder(this@ZhiHuDailyDetailActivity2) + mMaterialDialog = MaterialDialog.Builder(this@ZhiHuDailyDetailActivity) .content("Loading...") .progress(true, 0) .show() From 3f3ec4f8911304606a12862da7b2c283704766f4 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Sun, 23 Dec 2018 12:11:59 +0800 Subject: [PATCH 036/150] Kotlin rewriting ZhiHuDailyFragment2.kt --- .../main/java/com/leeeyou/IndexActivity.kt | 7 +- .../zhihudaily/view/ZhiHuDailyFragment2.kt | 132 ++++++++++++++++++ 2 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment2.kt diff --git a/app/src/main/java/com/leeeyou/IndexActivity.kt b/app/src/main/java/com/leeeyou/IndexActivity.kt index a740297..1defcc4 100644 --- a/app/src/main/java/com/leeeyou/IndexActivity.kt +++ b/app/src/main/java/com/leeeyou/IndexActivity.kt @@ -6,6 +6,7 @@ import com.leeeyou.manager.BaseActivity import com.leeeyou.util.ViewPagerAdapter import com.leeeyou.wanandroid.WanAndroidFragment import com.leeeyou.weather.WeatherFragment +import com.leeeyou.zhihudaily.view.ZhiHuDailyFragment2 import kotlinx.android.synthetic.main.activity_index.* private const val FIRST_PAGE_INDEX: Int = 0 @@ -13,8 +14,8 @@ private const val FIRST_PAGE_INDEX: Int = 0 /** * ClassName: IndexActivity * - * Author: leeeyou - * Date: 2018/12/21 18:02 + * Author: leeeyou + * Date: 2018/12/21 18:02 */ class IndexActivity : BaseActivity() { @@ -46,7 +47,7 @@ class IndexActivity : BaseActivity() { private fun initAdapter() { //create a collection object using arrayOf - val fragmentList = arrayOf(WeatherFragment(), WanAndroidFragment(), com.leeeyou.zhihudaily.view.ZhiHuDailyFragment()) + val fragmentList = arrayOf(WeatherFragment(), WanAndroidFragment(), ZhiHuDailyFragment2()) val titleList = arrayOf("天气", "WanAndroid", "知乎日报") mViewPagerAdapter = ViewPagerAdapter(supportFragmentManager, fragmentList, titleList) diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment2.kt b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment2.kt new file mode 100644 index 0000000..cc74db6 --- /dev/null +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment2.kt @@ -0,0 +1,132 @@ +package com.leeeyou.zhihudaily.view + +import `in`.srain.cube.views.ptr.PtrDefaultHandler +import `in`.srain.cube.views.ptr.PtrFrameLayout +import android.os.Bundle +import android.support.v7.widget.LinearLayoutManager +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.chad.library.adapter.base.BaseQuickAdapter +import com.leeeyou.R +import com.leeeyou.manager.BaseFragment +import com.leeeyou.util.T.showShort +import com.leeeyou.zhihudaily.model.bean.ZhiHuDaily +import com.leeeyou.zhihudaily.model.bean.ZhiHuDailyItem +import com.leeeyou.zhihudaily.model.fetchZhiHuDailyListByDate +import kotlinx.android.synthetic.main.activity_zhihu_daily.* +import org.joda.time.DateTime +import rx.Subscriber +import rx.android.schedulers.AndroidSchedulers +import rx.schedulers.Schedulers +import java.util.* + +class ZhiHuDailyFragment2 : BaseFragment() { + private val mMostDate = 7 + private val mDateList = Array(7) { "" } + private var mDatePosition = 0 + + private lateinit var mAdapter: ZhiHuDailyAdapter + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.activity_zhihu_daily, container, false) + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + initDataList() + initView() + fetchZhiHuDailyList(mDateList[0]) + } + + private fun fetchZhiHuDailyList(date: String) { + fetchZhiHuDailyListByDate(date) + .subscribeOn(Schedulers.newThread()) + .filter { zhiHuDaily -> + for (item in zhiHuDaily.stories) { + item.date = StringBuilder(zhiHuDaily.date) + .insert(4, "-") + .insert(7, "-") + .toString() + } + + true + } + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : Subscriber() { + override fun onNext(item: ZhiHuDaily?) { + ptrFrameOfZhiHuDaily.refreshComplete() + if (item != null) { + setDataToAdapter(item.stories) + } + } + + override fun onCompleted() { + mAdapter.loadMoreComplete() + } + + override fun onError(e: Throwable?) { + ptrFrameOfZhiHuDaily.refreshComplete() + e?.printStackTrace() + showShort(activity, "出错了:" + e?.message) + } + }) + } + + private fun setDataToAdapter(zhiHuDailyItemList: List) { + if (mDatePosition == 0) { + mAdapter.setNewData(zhiHuDailyItemList) + } else { + mAdapter.addData(zhiHuDailyItemList) + } + } + + private fun initView() { + ptrFrameOfZhiHuDaily.disableWhenHorizontalMove(true) + ptrFrameOfZhiHuDaily.setPtrHandler(object : PtrDefaultHandler() { + override fun onRefreshBegin(frame: PtrFrameLayout?) { + mDatePosition = 0 + fetchZhiHuDailyList(mDateList[mDatePosition]) + } + + override fun checkCanDoRefresh(frame: PtrFrameLayout?, content: View?, header: View?): Boolean { + return !recyclerViewRiBao.canScrollVertically(-1) + } + }) + + initAdapter() + } + + private fun initAdapter() { + mAdapter = ZhiHuDailyAdapter(R.layout.item_zhihu_daily, null) + recyclerViewRiBao.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) + recyclerViewRiBao.adapter = mAdapter + mAdapter.openLoadAnimation(BaseQuickAdapter.SCALEIN) + mAdapter.setOnLoadMoreListener({ + if (mDatePosition < mMostDate - 1) { + fetchZhiHuDailyList(mDateList[++mDatePosition]) + } else { + mAdapter.loadMoreEnd() + } + }, recyclerViewRiBao) + + } + + private fun initDataList() { + val now = DateTime.now().plusDays(1) + Log.e("xxx", now.toString()) + + for (i in 0 until mMostDate) { + val tempDateTime = now.minusDays(i) + Log.e("xxx", i.toString() + " - " + tempDateTime.toString()) + mDateList[i] = tempDateTime.year.toString() + + (if (tempDateTime.monthOfYear < 10) "0" + tempDateTime.monthOfYear else tempDateTime.monthOfYear) + + if (tempDateTime.dayOfMonth < 10) "0" + tempDateTime.dayOfMonth else tempDateTime.dayOfMonth + + } + Log.e("xxx", Arrays.toString(mDateList)) + } + + +} \ No newline at end of file From 7d374aefc81df9cd5d2a1eb3a50ef8427607b096 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Sun, 23 Dec 2018 15:18:24 +0800 Subject: [PATCH 037/150] Kotlin rewriting ZhiHuDailyFragment.kt --- .../zhihudaily/view/ZhiHuDailyFragment.java | 163 ------------------ .../zhihudaily/view/ZhiHuDailyFragment2.kt | 14 +- 2 files changed, 4 insertions(+), 173 deletions(-) delete mode 100644 app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.java diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.java b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.java deleted file mode 100644 index 88b17c8..0000000 --- a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.java +++ /dev/null @@ -1,163 +0,0 @@ -package com.leeeyou.zhihudaily.view; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.chad.library.adapter.base.BaseQuickAdapter; -import com.leeeyou.R; -import com.leeeyou.manager.BaseFragment; -import com.leeeyou.zhihudaily.model.ZhiHuDailyRepositoryKt; -import com.leeeyou.zhihudaily.model.bean.ZhiHuDaily; -import com.leeeyou.zhihudaily.model.bean.ZhiHuDailyItem; - -import org.joda.time.DateTime; - -import java.util.List; - -import in.srain.cube.views.ptr.PtrClassicFrameLayout; -import in.srain.cube.views.ptr.PtrDefaultHandler; -import in.srain.cube.views.ptr.PtrFrameLayout; -import rx.Subscriber; -import rx.android.schedulers.AndroidSchedulers; -import rx.functions.Func1; -import rx.schedulers.Schedulers; - -/** - * ClassName: ZhiHuDailyFragment - *

- * Author: leeeyou - * Date: 2017/4/24 13:46 - */ -public class ZhiHuDailyFragment extends BaseFragment { - - private RecyclerView mRecyclerView; - private PtrClassicFrameLayout mPtrFrame; - private ZhiHuDailyAdapter mAdapter; - - //when loading more, up to the date of the data can be loaded - private String[] dateList = new String[7]; - private int mDatePosition = 0; - private int mMostDate = 7; - - @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - View inflate = inflater.inflate(R.layout.activity_zhihu_daily, container, false); - mRecyclerView = inflate.findViewById(R.id.recyclerViewRiBao); - mPtrFrame = inflate.findViewById(R.id.ptrFrameOfZhiHuDaily); - return inflate; - } - - @Override - public void onActivityCreated(@Nullable Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - initDateList(); - initView(); - fetchZhiHuDailyList(); - } - - private void initView() { - mPtrFrame.disableWhenHorizontalMove(true); - mPtrFrame.setPtrHandler(new PtrDefaultHandler() { - @Override - public void onRefreshBegin(PtrFrameLayout frame) { - mDatePosition = 0; - fetchZhiHuDailyList(); - } - - @Override - public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) { - return !mRecyclerView.canScrollVertically(-1); - } - }); - - initAdapter(); - } - - private void initAdapter() { - mAdapter = new ZhiHuDailyAdapter(R.layout.item_zhihu_daily, null); - mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false)); - mRecyclerView.setAdapter(mAdapter); - - mAdapter.openLoadAnimation(BaseQuickAdapter.SCALEIN); - mAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() { - @Override - public void onLoadMoreRequested() { - if (mDatePosition < mMostDate - 1) { - fetchZhiHuDailyList(); - } else { - mAdapter.loadMoreEnd(); - } - } - }, mRecyclerView); - } - - private void fetchZhiHuDailyList() { - ZhiHuDailyRepositoryKt - .fetchZhiHuDailyListByDate(dateList[++mDatePosition]) - .subscribeOn(Schedulers.newThread()) - .filter(new Func1() { - @Override - public Boolean call(ZhiHuDaily riBao) { - StringBuilder sb = new StringBuilder(); - char[] chars = riBao.getDate().toCharArray(); - for (int i = 0; i < chars.length; i++) { - if (i == 4 || i == 6) { - sb.append("-"); - } - sb.append(chars[i]); - } - - List stories = riBao.getStories(); - for (ZhiHuDailyItem item : stories) { - item.setDate(sb.toString()); - } - - return true; - } - }) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Subscriber() { - @Override - public void onCompleted() { - mAdapter.loadMoreComplete(); - } - - @Override - public void onError(Throwable e) { - mPtrFrame.refreshComplete(); - e.printStackTrace(); - com.leeeyou.util.T.showShort(getActivity(), "出错了:" + e.getMessage()); - } - - @Override - public void onNext(ZhiHuDaily zhiHuDaily) { - mPtrFrame.refreshComplete(); - setDataToAdapter(zhiHuDaily.getStories()); - } - }); - } - - private void setDataToAdapter(@NonNull List zhiHuDailyItemList) { - if (mDatePosition == 0) { - mAdapter.setNewData(zhiHuDailyItemList); - } else { - mAdapter.addData(zhiHuDailyItemList); - } - } - - private void initDateList() { - DateTime mDateTime = DateTime.now(); - for (int i = 0; i < mMostDate; i++) { - DateTime tempDateTime = mDateTime.minusDays(i); - dateList[i] = String.valueOf(tempDateTime.getYear()) + - (tempDateTime.getMonthOfYear() < 10 ? "0" + tempDateTime.getMonthOfYear() : tempDateTime.getMonthOfYear()) + - (tempDateTime.getDayOfMonth() < 10 ? "0" + tempDateTime.getDayOfMonth() : tempDateTime.getDayOfMonth()); - } - } -} diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment2.kt b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment2.kt index cc74db6..4f48ac7 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment2.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment2.kt @@ -4,7 +4,6 @@ import `in`.srain.cube.views.ptr.PtrDefaultHandler import `in`.srain.cube.views.ptr.PtrFrameLayout import android.os.Bundle import android.support.v7.widget.LinearLayoutManager -import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -20,7 +19,6 @@ import org.joda.time.DateTime import rx.Subscriber import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers -import java.util.* class ZhiHuDailyFragment2 : BaseFragment() { private val mMostDate = 7 @@ -110,22 +108,18 @@ class ZhiHuDailyFragment2 : BaseFragment() { mAdapter.loadMoreEnd() } }, recyclerViewRiBao) - } private fun initDataList() { val now = DateTime.now().plusDays(1) - Log.e("xxx", now.toString()) - for (i in 0 until mMostDate) { val tempDateTime = now.minusDays(i) - Log.e("xxx", i.toString() + " - " + tempDateTime.toString()) - mDateList[i] = tempDateTime.year.toString() + - (if (tempDateTime.monthOfYear < 10) "0" + tempDateTime.monthOfYear else tempDateTime.monthOfYear) + - if (tempDateTime.dayOfMonth < 10) "0" + tempDateTime.dayOfMonth else tempDateTime.dayOfMonth + val year = tempDateTime.year.toString() + val month = if (tempDateTime.monthOfYear < 10) "0" + tempDateTime.monthOfYear else tempDateTime.monthOfYear.toString() + val day = if (tempDateTime.dayOfMonth < 10) "0" + tempDateTime.dayOfMonth else tempDateTime.dayOfMonth.toString() + mDateList[i] = year + month + day } - Log.e("xxx", Arrays.toString(mDateList)) } From f32d37c68c482d2ec418fc88251a621994e8682f Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Sun, 23 Dec 2018 15:18:47 +0800 Subject: [PATCH 038/150] Kotlin rewriting ZhiHuDailyFragment.kt --- app/src/main/java/com/leeeyou/IndexActivity.kt | 4 ++-- .../view/{ZhiHuDailyFragment2.kt => ZhiHuDailyFragment.kt} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename app/src/main/java/com/leeeyou/zhihudaily/view/{ZhiHuDailyFragment2.kt => ZhiHuDailyFragment.kt} (99%) diff --git a/app/src/main/java/com/leeeyou/IndexActivity.kt b/app/src/main/java/com/leeeyou/IndexActivity.kt index 1defcc4..99f7e53 100644 --- a/app/src/main/java/com/leeeyou/IndexActivity.kt +++ b/app/src/main/java/com/leeeyou/IndexActivity.kt @@ -6,7 +6,7 @@ import com.leeeyou.manager.BaseActivity import com.leeeyou.util.ViewPagerAdapter import com.leeeyou.wanandroid.WanAndroidFragment import com.leeeyou.weather.WeatherFragment -import com.leeeyou.zhihudaily.view.ZhiHuDailyFragment2 +import com.leeeyou.zhihudaily.view.ZhiHuDailyFragment import kotlinx.android.synthetic.main.activity_index.* private const val FIRST_PAGE_INDEX: Int = 0 @@ -47,7 +47,7 @@ class IndexActivity : BaseActivity() { private fun initAdapter() { //create a collection object using arrayOf - val fragmentList = arrayOf(WeatherFragment(), WanAndroidFragment(), ZhiHuDailyFragment2()) + val fragmentList = arrayOf(WeatherFragment(), WanAndroidFragment(), ZhiHuDailyFragment()) val titleList = arrayOf("天气", "WanAndroid", "知乎日报") mViewPagerAdapter = ViewPagerAdapter(supportFragmentManager, fragmentList, titleList) diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment2.kt b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt similarity index 99% rename from app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment2.kt rename to app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt index 4f48ac7..807d73e 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment2.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt @@ -20,7 +20,7 @@ import rx.Subscriber import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers -class ZhiHuDailyFragment2 : BaseFragment() { +class ZhiHuDailyFragment : BaseFragment() { private val mMostDate = 7 private val mDateList = Array(7) { "" } private var mDatePosition = 0 From e45d72c744c5c667e536987cd048c40d03bd5bd7 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Sun, 23 Dec 2018 16:00:34 +0800 Subject: [PATCH 039/150] Full Kotlin rewriting --- .../zhihudaily/view/ZhiHuDailyFragment.kt | 76 +++++++++---------- 1 file changed, 37 insertions(+), 39 deletions(-) diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt index 807d73e..ea1d29d 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt @@ -24,7 +24,6 @@ class ZhiHuDailyFragment : BaseFragment() { private val mMostDate = 7 private val mDateList = Array(7) { "" } private var mDatePosition = 0 - private lateinit var mAdapter: ZhiHuDailyAdapter override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { @@ -38,41 +37,7 @@ class ZhiHuDailyFragment : BaseFragment() { fetchZhiHuDailyList(mDateList[0]) } - private fun fetchZhiHuDailyList(date: String) { - fetchZhiHuDailyListByDate(date) - .subscribeOn(Schedulers.newThread()) - .filter { zhiHuDaily -> - for (item in zhiHuDaily.stories) { - item.date = StringBuilder(zhiHuDaily.date) - .insert(4, "-") - .insert(7, "-") - .toString() - } - - true - } - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(object : Subscriber() { - override fun onNext(item: ZhiHuDaily?) { - ptrFrameOfZhiHuDaily.refreshComplete() - if (item != null) { - setDataToAdapter(item.stories) - } - } - - override fun onCompleted() { - mAdapter.loadMoreComplete() - } - - override fun onError(e: Throwable?) { - ptrFrameOfZhiHuDaily.refreshComplete() - e?.printStackTrace() - showShort(activity, "出错了:" + e?.message) - } - }) - } - - private fun setDataToAdapter(zhiHuDailyItemList: List) { + private fun updateAdapter(zhiHuDailyItemList: List) { if (mDatePosition == 0) { mAdapter.setNewData(zhiHuDailyItemList) } else { @@ -81,6 +46,11 @@ class ZhiHuDailyFragment : BaseFragment() { } private fun initView() { + initPtr() + initAdapter() + } + + private fun initPtr() { ptrFrameOfZhiHuDaily.disableWhenHorizontalMove(true) ptrFrameOfZhiHuDaily.setPtrHandler(object : PtrDefaultHandler() { override fun onRefreshBegin(frame: PtrFrameLayout?) { @@ -92,8 +62,6 @@ class ZhiHuDailyFragment : BaseFragment() { return !recyclerViewRiBao.canScrollVertically(-1) } }) - - initAdapter() } private fun initAdapter() { @@ -118,9 +86,39 @@ class ZhiHuDailyFragment : BaseFragment() { val month = if (tempDateTime.monthOfYear < 10) "0" + tempDateTime.monthOfYear else tempDateTime.monthOfYear.toString() val day = if (tempDateTime.dayOfMonth < 10) "0" + tempDateTime.dayOfMonth else tempDateTime.dayOfMonth.toString() mDateList[i] = year + month + day - } } + private fun fetchZhiHuDailyList(date: String) { + fetchZhiHuDailyListByDate(date) + .subscribeOn(Schedulers.newThread()) + .filter { zhiHuDaily -> + for (item in zhiHuDaily.stories) { + item.date = StringBuilder(zhiHuDaily.date) + .insert(4, "-") + .insert(7, "-") + .toString() + } + true + } + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : Subscriber() { + override fun onNext(item: ZhiHuDaily?) { + ptrFrameOfZhiHuDaily.refreshComplete() + if (item != null) { + updateAdapter(item.stories) + } + } + override fun onCompleted() { + mAdapter.loadMoreComplete() + } + + override fun onError(e: Throwable?) { + ptrFrameOfZhiHuDaily.refreshComplete() + e?.printStackTrace() + showShort(activity, "出错了:" + e?.message) + } + }) + } } \ No newline at end of file From 35a166818ea616b2ed0c88133df30b5a9e941c9a Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Sun, 23 Dec 2018 19:03:35 +0800 Subject: [PATCH 040/150] WanAndroid - Recommend Banner --- app/build.gradle | 5 +- app/proguard-rules.pro | 5 ++ app/src/main/AndroidManifest.xml | 2 +- .../wanandroid/WanAndroidRecommendFragment.kt | 75 +++++++++++++++++++ .../wanandroid/model/WanAndroidRepository.kt | 14 ++++ .../leeeyou/wanandroid/model/bean/Banner.kt | 10 +++ .../wanandroid/model/bean/ResponseBanner.kt | 5 ++ .../wanandroid/service/WanAndroidService.kt | 12 +++ app/src/main/res/layout/activity_index.xml | 2 +- .../main/res/layout/fragment_wan_android.xml | 2 +- .../layout/fragment_wan_android_recommend.xml | 12 ++- 11 files changed, 138 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt create mode 100644 app/src/main/java/com/leeeyou/wanandroid/model/bean/Banner.kt create mode 100644 app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseBanner.kt create mode 100644 app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt diff --git a/app/build.gradle b/app/build.gradle index 2eeaa5f..52d3dd3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,11 +77,14 @@ dependencies { implementation 'com.tencent.bugly:crashreport_upgrade:1.3.6' implementation 'com.tencent.bugly:nativecrashreport:3.6.0' + //glide + implementation 'com.github.bumptech.glide:glide:4.8.0' + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation 'com.github.bumptech.glide:glide:4.6.1' implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.44' implementation 'net.danlew:android.joda:2.9.9.4' implementation 'com.afollestad.material-dialogs:core:0.9.4.7' implementation 'in.srain.cube:ultra-ptr:1.0.11' + implementation 'com.youth.banner:banner:1.4.10' } \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 71d0186..9365f96 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -90,3 +90,8 @@ -keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef { rx.internal.util.atomic.LinkedQueueNode consumerNode; } + +# banner 的混淆代码 +-keep class com.youth.banner.** { + *; + } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 10a623f..1b0e7db 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,8 +6,8 @@ - + () { + override fun onNext(t: ResponseBanner) { + println("fetchBannerList onNext") + println(t) + + t.takeIf { + it.errorCode >= 0 + }?.also { + renderBanner(it.data) + } ?: onError(IllegalArgumentException("接口返回异常")) + } + + override fun onCompleted() { + println("fetchBannerList onCompleted") + } + + override fun onError(e: Throwable?) { + println("fetchBannerList onError") + } + }) + } + + private fun renderBanner(bannerList: List) { + bannerList.map { it.imagePath }.run { + banner.setImages(this) + banner.setBannerAnimation(Transformer.Default) + banner.start() + } + } + + override fun onStart() { + super.onStart() + banner.startAutoPlay() + } + + override fun onStop() { + super.onStop() + banner.stopAutoPlay() + } + } \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt b/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt new file mode 100644 index 0000000..0c33419 --- /dev/null +++ b/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt @@ -0,0 +1,14 @@ +package com.leeeyou.wanandroid.model + +import com.leeeyou.factory.ServiceFactory +import com.leeeyou.wanandroid.model.bean.ResponseBanner +import com.leeeyou.wanandroid.service.WanAndroidService +import rx.Observable + +private const val endPoint = "http://www.wanandroid.com/" + +fun fetchBannerList(): Observable { + return ServiceFactory + .createRxRetrofitService(WanAndroidService::class.java, endPoint) + .getBannerList() +} \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/bean/Banner.kt b/app/src/main/java/com/leeeyou/wanandroid/model/bean/Banner.kt new file mode 100644 index 0000000..3ef9337 --- /dev/null +++ b/app/src/main/java/com/leeeyou/wanandroid/model/bean/Banner.kt @@ -0,0 +1,10 @@ +package com.leeeyou.wanandroid.model.bean + +data class Banner(val desc: String, + val id: Int, + val imagePath: String, + val isVisible: Int, + val order: Int, + val title: String, + val type: Int, + val url: String) \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseBanner.kt b/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseBanner.kt new file mode 100644 index 0000000..37163d7 --- /dev/null +++ b/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseBanner.kt @@ -0,0 +1,5 @@ +package com.leeeyou.wanandroid.model.bean + +data class ResponseBanner(val data: List, + val errorCode: Int = 0, + var errorMsg: String = "") \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt b/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt new file mode 100644 index 0000000..22133c1 --- /dev/null +++ b/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt @@ -0,0 +1,12 @@ +package com.leeeyou.wanandroid.service + +import com.leeeyou.wanandroid.model.bean.ResponseBanner +import retrofit.http.GET +import rx.Observable + +interface WanAndroidService { + + @GET("banner/json") + fun getBannerList(): Observable + +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_index.xml b/app/src/main/res/layout/activity_index.xml index 6ceddc1..ce8dc23 100644 --- a/app/src/main/res/layout/activity_index.xml +++ b/app/src/main/res/layout/activity_index.xml @@ -9,7 +9,7 @@ + android:layout_height="match_parent"> + + \ No newline at end of file From 298f9c983737909f0d5cb50c584eb807218a9632 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Wed, 26 Dec 2018 18:44:10 +0800 Subject: [PATCH 041/150] Sonic --- app/build.gradle | 2 + app/src/main/AndroidManifest.xml | 6 +- .../java/com/leeeyou/KotlinApplication.kt | 27 ++- .../com/leeeyou/manager/BrowserActivity.kt | 205 ++++++++++++++++++ .../leeeyou/manager/sonic/HostSonicRuntime.kt | 82 +++++++ .../leeeyou/manager/sonic/MySonicConfig.kt | 8 + .../sonic/SonicJavaScriptInterface.java | 143 ++++++++++++ .../manager/sonic/SonicSessionClientImpl.kt | 35 +++ .../manager/timber/CrashReportingTree.kt | 28 +++ .../manager/timber/FakeCrashLibrary.java | 16 ++ .../wanandroid/WanAndroidRecommendFragment.kt | 35 +-- .../view/ZhiHuDailyDetailActivity.kt | 15 ++ app/src/main/res/layout/activity_browser.xml | 20 ++ 13 files changed, 606 insertions(+), 16 deletions(-) create mode 100644 app/src/main/java/com/leeeyou/manager/BrowserActivity.kt create mode 100644 app/src/main/java/com/leeeyou/manager/sonic/HostSonicRuntime.kt create mode 100644 app/src/main/java/com/leeeyou/manager/sonic/MySonicConfig.kt create mode 100644 app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.java create mode 100644 app/src/main/java/com/leeeyou/manager/sonic/SonicSessionClientImpl.kt create mode 100644 app/src/main/java/com/leeeyou/manager/timber/CrashReportingTree.kt create mode 100644 app/src/main/java/com/leeeyou/manager/timber/FakeCrashLibrary.java create mode 100644 app/src/main/res/layout/activity_browser.xml diff --git a/app/build.gradle b/app/build.gradle index 52d3dd3..26cf99e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -86,5 +86,7 @@ dependencies { implementation 'com.afollestad.material-dialogs:core:0.9.4.7' implementation 'in.srain.cube:ultra-ptr:1.0.11' implementation 'com.youth.banner:banner:1.4.10' + implementation 'com.jakewharton.timber:timber:4.7.1' + implementation 'com.tencent.sonic:sdk:3.1.0' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1b0e7db..2f8ff65 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -7,7 +7,7 @@ - + + + \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/KotlinApplication.kt b/app/src/main/java/com/leeeyou/KotlinApplication.kt index 811202d..9b13a02 100644 --- a/app/src/main/java/com/leeeyou/KotlinApplication.kt +++ b/app/src/main/java/com/leeeyou/KotlinApplication.kt @@ -3,8 +3,12 @@ package com.leeeyou import android.app.Application import android.content.Context import android.support.multidex.MultiDex +import com.leeeyou.manager.timber.CrashReportingTree import com.tencent.bugly.Bugly import net.danlew.android.joda.JodaTimeAndroid +import timber.log.Timber +import timber.log.Timber.DebugTree + /** * ClassName: App @@ -12,15 +16,34 @@ import net.danlew.android.joda.JodaTimeAndroid * Author: leeeyou * Date: 2018/2/24 14:27 */ -class KotlinApplication : Application(){ +class KotlinApplication : Application() { override fun onCreate() { super.onCreate() - JodaTimeAndroid.init(this) + initJoda() + initBugly() + initTimber() + } + + private fun initTimber() { + if (BuildConfig.DEBUG) { + Timber.plant(DebugTree()) + } else { + Timber.plant(CrashReportingTree()) + } + } + + private fun initBugly() { Bugly.init(this, "8f4e37e626", false) } + private fun initJoda() { + JodaTimeAndroid.init(this) + } + override fun attachBaseContext(base: Context?) { super.attachBaseContext(base) MultiDex.install(base) } + + } \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/manager/BrowserActivity.kt b/app/src/main/java/com/leeeyou/manager/BrowserActivity.kt new file mode 100644 index 0000000..8386aa8 --- /dev/null +++ b/app/src/main/java/com/leeeyou/manager/BrowserActivity.kt @@ -0,0 +1,205 @@ +package com.leeeyou.manager + +import android.annotation.SuppressLint +import android.annotation.TargetApi +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.support.design.widget.FloatingActionButton +import android.support.v7.app.AppCompatActivity +import android.text.TextUtils +import android.view.View +import android.view.WindowManager +import android.webkit.WebResourceRequest +import android.webkit.WebResourceResponse +import android.webkit.WebView +import android.webkit.WebViewClient +import com.leeeyou.R +import com.leeeyou.manager.sonic.* +import com.leeeyou.util.T +import com.tencent.sonic.sdk.* +import timber.log.Timber +import java.io.BufferedInputStream +import java.io.IOException +import java.lang.ref.WeakReference + +const val PARAM_MODE = "param_mode" +const val PARAM_URL = "param_url" + +class BrowserActivity : AppCompatActivity() { + private var sonicSession: SonicSession? = null + + @SuppressLint("SetJavaScriptEnabled", "AddJavascriptInterface") + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val url = intent.getStringExtra(PARAM_URL) + val mode = intent.getIntExtra(PARAM_MODE, -1) + + Timber.e(url) + Timber.e("mode is %s", mode) + + if (TextUtils.isEmpty(url) || -1 == mode) { + finish() + return + } + + window.addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) + + if (!SonicEngine.isGetInstanceAllowed()) { + SonicEngine.createInstance(HostSonicRuntime(application), SonicConfig.Builder().build()) + } + + var sonicSessionClient: SonicSessionClientImpl? = null + + // if it's sonic mode , startup sonic session at first time + if (MODE_SONIC == mode) { + val builder = SonicSessionConfig.Builder() + builder.setSupportLocalServer(true) + + // if it's offline pkg mode, we need to intercept the session connection + if (MODE_SONIC_WITH_OFFLINE_CACHE == mode) { + builder.setCacheInterceptor(object : SonicCacheInterceptor(null) { + override fun getCacheData(session: SonicSession?): String? { + return null// offline pkg does not need cache + } + + }) + + builder.setConnectionInterceptor(object : SonicSessionConnectionInterceptor() { + override fun getConnection(session: SonicSession, intent: Intent): SonicSessionConnection { + return OfflinePkgSessionConnection(this@BrowserActivity, session, intent) + } + + }) + } + + // create sonic session and run sonic flow + sonicSession = SonicEngine.getInstance().createSession(url, builder.build()) + if (null != sonicSession) { + sonicSessionClient = SonicSessionClientImpl() + sonicSession!!.bindClient(sonicSessionClient) + } else { + // this only happen when a same sonic session is already running, + // u can comment following codes to feedback as a default mode. + // throw new UnknownError("create session fail!"); + T.showShort(this, "create sonic session fail!") + } + + // start init flow ... + // in the real world, the init flow may cost a long time as startup + // runtime、init configs.... + setContentView(R.layout.activity_browser) + + val btnFab = findViewById(R.id.btn_refresh) + btnFab.setOnClickListener { + sonicSession?.refresh() + } + + // init webView + val webView = findViewById(R.id.webview) as WebView + webView.webViewClient = (object : WebViewClient() { + override fun onPageFinished(view: WebView?, url: String?) { + super.onPageFinished(view, url) + sonicSession?.sessionClient?.pageFinish(url) + } + + @TargetApi(21) + override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest?): WebResourceResponse? { + return shouldInterceptRequest(view, request) + } + + override fun shouldInterceptRequest(view: WebView, url: String): WebResourceResponse? { + return if (sonicSession != null) { + sonicSession?.sessionClient?.requestResource(url) as WebResourceResponse + } else null + } + }) + + val webSettings = webView.settings + + // add java script interface + // note:if api level lower than 17(android 4.2), addJavascriptInterface has security + // issue, please use x5 or see https://developer.android.com/reference/android/webkit/ + // WebView.html#addJavascriptInterface(java.lang.Object, java.lang.String) + webSettings.javaScriptEnabled = true + webView.removeJavascriptInterface("searchBoxJavaBridge_") + intent.putExtra(SonicJavaScriptInterface.PARAM_LOAD_URL_TIME, System.currentTimeMillis()) + webView.addJavascriptInterface(SonicJavaScriptInterface(sonicSessionClient, intent), "sonic") + + // init webView settings + webSettings.allowContentAccess = true + webSettings.databaseEnabled = true + webSettings.domStorageEnabled = true + webSettings.setAppCacheEnabled(true) + webSettings.savePassword = false + webSettings.saveFormData = false + webSettings.useWideViewPort = true + webSettings.loadWithOverviewMode = true + + // webView is ready now, just tell session client to bind + if (sonicSessionClient != null) { + sonicSessionClient.bindWebView(webView) + sonicSessionClient.clientReady() + } else { // default mode + webView.loadUrl(url) + } + } + } + + override fun onDestroy() { + sonicSession?.destroy() + sonicSession = null + super.onDestroy() + } + + private class OfflinePkgSessionConnection(context: Context, session: SonicSession, intent: Intent) + : SonicSessionConnection(session, intent) { + + private val context: WeakReference = WeakReference(context) + + override fun internalConnect(): Int { + val ctx = context.get() + ctx?.let { + try { + val offlineHtmlInputStream = ctx.assets.open("sonic-demo-index.html") + responseStream = BufferedInputStream(offlineHtmlInputStream) + return SonicConstants.ERROR_CODE_SUCCESS + } catch (e: Throwable) { + e.printStackTrace() + } + } + return SonicConstants.ERROR_CODE_UNKNOWN + } + + override fun internalGetResponseStream(): BufferedInputStream { + return responseStream + } + + override fun internalGetCustomHeadFieldEtag(): String { + return SonicSessionConnection.CUSTOM_HEAD_FILED_ETAG + } + + override fun disconnect() { + if (null != responseStream) { + try { + responseStream.close() + } catch (e: IOException) { + e.printStackTrace() + } + + } + } + + override fun getResponseCode(): Int { + return 200 + } + + override fun getResponseHeaderFields(): Map> { + return HashMap(0) + } + + override fun getResponseHeaderField(key: String): String { + return "" + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/manager/sonic/HostSonicRuntime.kt b/app/src/main/java/com/leeeyou/manager/sonic/HostSonicRuntime.kt new file mode 100644 index 0000000..faf704d --- /dev/null +++ b/app/src/main/java/com/leeeyou/manager/sonic/HostSonicRuntime.kt @@ -0,0 +1,82 @@ +package com.leeeyou.manager.sonic + +import android.content.Context +import android.os.Build +import android.text.TextUtils +import android.util.Log +import android.webkit.CookieManager +import android.webkit.WebResourceResponse +import com.leeeyou.util.T +import com.tencent.sonic.sdk.SonicRuntime +import com.tencent.sonic.sdk.SonicSessionClient +import timber.log.Timber +import java.io.InputStream + + +class HostSonicRuntime(context: Context) : SonicRuntime(context) { + override fun showToast(text: CharSequence?, duration: Int) { + T.show(context, text, duration) + } + + override fun log(tag: String?, level: Int, message: String?) { + Timber.tag(tag) + when (level) { + Log.ERROR -> Timber.e(message) + Log.INFO -> Timber.i(message) + else -> Timber.d(message) + } + } + + override fun getUserAgent(): String { + return "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Mobile Safari/537.36" + } + + override fun isNetworkValid(): Boolean { + return true + } + + override fun postTaskToThread(task: Runnable?, delayMillis: Long) { + Thread(task, "SonicThread").start() + } + + override fun isSonicUrl(url: String?): Boolean { + return true + } + + override fun setCookie(url: String?, cookies: MutableList?): Boolean { + if (TextUtils.isEmpty(url) && cookies != null && cookies.size > 0) { + val cookieManager = android.webkit.CookieManager.getInstance() + for (item in cookies) { + cookieManager.setCookie(url, item) + } + return true + } + return false + } + + override fun getCookie(url: String): String { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + val instance = CookieManager.getInstance() + return instance.getCookie(url) + } + + return "" + } + + override fun createWebResourceResponse(mimeType: String?, encoding: String?, data: InputStream?, headers: MutableMap?): Any { + val webResourceResponse = WebResourceResponse(mimeType, encoding, data) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + webResourceResponse.responseHeaders = headers + } + return webResourceResponse + } + + override fun getCurrentUserAccount(): String { + return "ReadSelectionSonic" + } + + override fun notifyError(client: SonicSessionClient?, url: String?, errorCode: Int) { + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/manager/sonic/MySonicConfig.kt b/app/src/main/java/com/leeeyou/manager/sonic/MySonicConfig.kt new file mode 100644 index 0000000..8173277 --- /dev/null +++ b/app/src/main/java/com/leeeyou/manager/sonic/MySonicConfig.kt @@ -0,0 +1,8 @@ +package com.leeeyou.manager.sonic + + +const val MODE_DEFAULT: Int = 0 +const val MODE_SONIC: Int = 1 + +const val MODE_SONIC_WITH_OFFLINE_CACHE = 2 +const val PERMISSION_REQUEST_CODE_STORAGE = 1 \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.java b/app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.java new file mode 100644 index 0000000..a18bfea --- /dev/null +++ b/app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.java @@ -0,0 +1,143 @@ +/* + * Tencent is pleased to support the open source community by making VasSonic available. + * + * Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + * + * + */ + +package com.leeeyou.manager.sonic; + + +import android.content.Intent; +import android.os.Handler; +import android.os.Looper; +import android.webkit.JavascriptInterface; + +import com.tencent.sonic.sdk.SonicDiffDataCallback; + +import org.json.JSONObject; + +/** + * Sonic javaScript Interface (Android API Level >= 17) + */ + +public class SonicJavaScriptInterface { + + private final SonicSessionClientImpl sessionClient; + + private final Intent intent; + + public static final String PARAM_CLICK_TIME = "clickTime"; + + public static final String PARAM_LOAD_URL_TIME = "loadUrlTime"; + + public SonicJavaScriptInterface(SonicSessionClientImpl sessionClient, Intent intent) { + this.sessionClient = sessionClient; + this.intent = intent; + } + + @JavascriptInterface + public void getDiffData() { + // the callback function of demo page is hardcode as 'getDiffDataCallback' + getDiffData2("getDiffDataCallback"); + } + + @JavascriptInterface + public void getDiffData2(final String jsCallbackFunc) { + if (null != sessionClient) { + sessionClient.getDiffData(new SonicDiffDataCallback() { + @Override + public void callback(final String resultData) { + Runnable callbackRunnable = new Runnable() { + @Override + public void run() { + String jsCode = "javascript:" + jsCallbackFunc + "('" + toJsString(resultData) + "')"; + sessionClient.getWebView().loadUrl(jsCode); + } + }; + if (Looper.getMainLooper() == Looper.myLooper()) { + callbackRunnable.run(); + } else { + new Handler(Looper.getMainLooper()).post(callbackRunnable); + } + } + }); + } + } + + @JavascriptInterface + public String getPerformance() { + long clickTime = intent.getLongExtra(PARAM_CLICK_TIME, -1); + long loadUrlTime = intent.getLongExtra(PARAM_LOAD_URL_TIME, -1); + try { + JSONObject result = new JSONObject(); + result.put(PARAM_CLICK_TIME, clickTime); + result.put(PARAM_LOAD_URL_TIME, loadUrlTime); + return result.toString(); + } catch (Exception e) { + + } + + return ""; + } + + /* + * * From RFC 4627, "All Unicode characters may be placed within the quotation marks except + * for the characters that must be escaped: quotation mark, + * reverse solidus, and the control characters (U+0000 through U+001F)." + */ + private static String toJsString(String value) { + if (value == null) { + return "null"; + } + StringBuilder out = new StringBuilder(1024); + for (int i = 0, length = value.length(); i < length; i++) { + char c = value.charAt(i); + + + switch (c) { + case '"': + case '\\': + case '/': + out.append('\\').append(c); + break; + + case '\t': + out.append("\\t"); + break; + + case '\b': + out.append("\\b"); + break; + + case '\n': + out.append("\\n"); + break; + + case '\r': + out.append("\\r"); + break; + + case '\f': + out.append("\\f"); + break; + + default: + if (c <= 0x1F) { + out.append(String.format("\\u%04x", (int) c)); + } else { + out.append(c); + } + break; + } + + } + return out.toString(); + } +} diff --git a/app/src/main/java/com/leeeyou/manager/sonic/SonicSessionClientImpl.kt b/app/src/main/java/com/leeeyou/manager/sonic/SonicSessionClientImpl.kt new file mode 100644 index 0000000..2685dbd --- /dev/null +++ b/app/src/main/java/com/leeeyou/manager/sonic/SonicSessionClientImpl.kt @@ -0,0 +1,35 @@ +package com.leeeyou.manager.sonic + +import android.os.Bundle +import android.webkit.WebView +import com.tencent.sonic.sdk.SonicSessionClient +import java.util.* + +class SonicSessionClientImpl : SonicSessionClient() { + private var webView: WebView? = null + + fun bindWebView(webView: WebView) { + this.webView = webView + } + + fun getWebView(): WebView? { + return webView + } + + override fun loadDataWithBaseUrlAndHeader(baseUrl: String?, data: String?, mimeType: String?, encoding: String?, historyUrl: String?, headers: HashMap?) { + loadDataWithBaseUrl(baseUrl, data, mimeType, encoding, historyUrl) + } + + override fun loadUrl(url: String?, extraData: Bundle?) { + webView?.loadUrl(url) + } + + override fun loadDataWithBaseUrl(baseUrl: String?, data: String?, mimeType: String?, encoding: String?, historyUrl: String?) { + webView?.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl) + } + + fun destroy() { + webView?.destroy() + webView = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/manager/timber/CrashReportingTree.kt b/app/src/main/java/com/leeeyou/manager/timber/CrashReportingTree.kt new file mode 100644 index 0000000..ad03dc2 --- /dev/null +++ b/app/src/main/java/com/leeeyou/manager/timber/CrashReportingTree.kt @@ -0,0 +1,28 @@ +package com.leeeyou.manager.timber + +import android.support.annotation.Nullable +import android.util.Log +import android.util.Log.INFO +import timber.log.Timber + +class CrashReportingTree : Timber.Tree() { + override fun log(priority: Int, tag: String?, message: String, t: Throwable?) { + if (priority == Log.VERBOSE || priority == Log.DEBUG) { + return + } + + FakeCrashLibrary.log(priority, tag, message) + + if (t != null) { + if (priority == Log.ERROR) { + FakeCrashLibrary.logError(t) + } else if (priority == Log.WARN) { + FakeCrashLibrary.logWarning(t) + } + } + } + + fun isLoggable(priority: Int, @Nullable tag: String): Boolean { + return priority >= INFO + } +} \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/manager/timber/FakeCrashLibrary.java b/app/src/main/java/com/leeeyou/manager/timber/FakeCrashLibrary.java new file mode 100644 index 0000000..5e6060b --- /dev/null +++ b/app/src/main/java/com/leeeyou/manager/timber/FakeCrashLibrary.java @@ -0,0 +1,16 @@ +package com.leeeyou.manager.timber; + +public final class FakeCrashLibrary { + public static void log(int priority, String tag, String message) { + } + + public static void logWarning(Throwable t) { + } + + public static void logError(Throwable t) { + } + + private FakeCrashLibrary() { + throw new AssertionError("No instances."); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt index fd2ed97..18d2bd8 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt @@ -22,6 +22,7 @@ import kotlinx.android.synthetic.main.fragment_wan_android_recommend.* import rx.Subscriber import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers +import timber.log.Timber /** @@ -38,19 +39,7 @@ class WanAndroidRecommendFragment : BaseFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - banner.setImageLoader(object : ImageLoader() { - override fun displayImage(context: Context?, path: Any?, imageView: ImageView?) { - if (context != null && imageView != null) { - Glide.with(context) - .load(path) - .apply(RequestOptions() - .override(banner.width, banner.height) - .fitCenter() - .transforms(CenterCrop(), RoundedCorners(30))) - .into(imageView) - } - } - }) + initBanner() fetchBannerList() .subscribeOn(Schedulers.newThread()) @@ -77,6 +66,26 @@ class WanAndroidRecommendFragment : BaseFragment() { }) } + private fun initBanner() { + banner.setImageLoader(object : ImageLoader() { + override fun displayImage(context: Context?, path: Any?, imageView: ImageView?) { + if (context != null && imageView != null) { + Glide.with(context) + .load(path) + .apply(RequestOptions() + .override(banner.width, banner.height) + .fitCenter() + .transforms(CenterCrop(), RoundedCorners(30))) + .into(imageView) + } + } + }) + banner.setDelayTime(3000) + banner.setOnBannerListener { + Timber.d("click position is %s", it.toString()) + } + } + private fun renderBanner(bannerList: List) { bannerList.map { it.imagePath }.run { banner.setImages(this) diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.kt b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.kt index cda7705..aba8fbe 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.kt @@ -1,9 +1,14 @@ package com.leeeyou.zhihudaily.view +import android.content.Intent import android.os.Bundle import com.afollestad.materialdialogs.MaterialDialog import com.leeeyou.R import com.leeeyou.manager.BaseActivity +import com.leeeyou.manager.BrowserActivity +import com.leeeyou.manager.PARAM_MODE +import com.leeeyou.manager.PARAM_URL +import com.leeeyou.manager.sonic.SonicJavaScriptInterface import com.leeeyou.util.HtmlUtils import com.leeeyou.zhihudaily.model.bean.ZhiHuDailyDetail import com.leeeyou.zhihudaily.model.fetchZhiHuDailyDetailById @@ -12,6 +17,7 @@ import rx.Subscriber import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers + class ZhiHuDailyDetailActivity : BaseActivity() { internal lateinit var mMaterialDialog: MaterialDialog @@ -46,10 +52,19 @@ class ZhiHuDailyDetailActivity : BaseActivity() { override fun onNext(storyDetail: ZhiHuDailyDetail) { zhiHuDailyWebview.loadData(HtmlUtils.structHtml(storyDetail.body, storyDetail.css), "text/html; charset=UTF-8", null) +// startBrowserActivity(MODE_SONIC, storyDetail.share_url) } }) } + private fun startBrowserActivity(mode: Int, url: String) { + val intent = Intent(this, BrowserActivity::class.java) + intent.putExtra(PARAM_URL, url) + intent.putExtra(PARAM_MODE, mode) + intent.putExtra(SonicJavaScriptInterface.PARAM_CLICK_TIME, System.currentTimeMillis()) + startActivity(intent) + } + private fun initWebView() { zhiHuDailyWebview.isVerticalScrollBarEnabled = false zhiHuDailyWebview.settings.defaultTextEncodingName = "UTF-8" diff --git a/app/src/main/res/layout/activity_browser.xml b/app/src/main/res/layout/activity_browser.xml new file mode 100644 index 0000000..c8c357f --- /dev/null +++ b/app/src/main/res/layout/activity_browser.xml @@ -0,0 +1,20 @@ + + + + + + + \ No newline at end of file From 87d7c2186bb6f65f26d82ee7ad99e80c7db5dbeb Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Thu, 27 Dec 2018 10:57:51 +0800 Subject: [PATCH 042/150] Integrated Sonic --- app/src/main/AndroidManifest.xml | 5 +- .../com/leeeyou/manager/BrowserActivity.kt | 205 ------------- .../manager/sonic/BrowserActivity.java | 273 ++++++++++++++++++ .../leeeyou/manager/sonic/HostSonicRuntime.kt | 82 ------ .../sonic/SonicJavaScriptInterface.java | 10 +- .../manager/sonic/SonicRuntimeImpl.java | 145 ++++++++++ .../manager/sonic/SonicSessionClientImpl.java | 62 ++++ .../manager/sonic/SonicSessionClientImpl.kt | 35 --- .../zhihudaily/view/ZhiHuDailyAdapter.kt | 8 +- .../view/ZhiHuDailyDetailActivity.kt | 73 ----- .../zhihudaily/view/ZhiHuDailyFragment.kt | 44 ++- 11 files changed, 529 insertions(+), 413 deletions(-) delete mode 100644 app/src/main/java/com/leeeyou/manager/BrowserActivity.kt create mode 100644 app/src/main/java/com/leeeyou/manager/sonic/BrowserActivity.java delete mode 100644 app/src/main/java/com/leeeyou/manager/sonic/HostSonicRuntime.kt create mode 100644 app/src/main/java/com/leeeyou/manager/sonic/SonicRuntimeImpl.java create mode 100644 app/src/main/java/com/leeeyou/manager/sonic/SonicSessionClientImpl.java delete mode 100644 app/src/main/java/com/leeeyou/manager/sonic/SonicSessionClientImpl.kt delete mode 100644 app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2f8ff65..ea52557 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -23,9 +23,6 @@ - diff --git a/app/src/main/java/com/leeeyou/manager/BrowserActivity.kt b/app/src/main/java/com/leeeyou/manager/BrowserActivity.kt deleted file mode 100644 index 8386aa8..0000000 --- a/app/src/main/java/com/leeeyou/manager/BrowserActivity.kt +++ /dev/null @@ -1,205 +0,0 @@ -package com.leeeyou.manager - -import android.annotation.SuppressLint -import android.annotation.TargetApi -import android.content.Context -import android.content.Intent -import android.os.Bundle -import android.support.design.widget.FloatingActionButton -import android.support.v7.app.AppCompatActivity -import android.text.TextUtils -import android.view.View -import android.view.WindowManager -import android.webkit.WebResourceRequest -import android.webkit.WebResourceResponse -import android.webkit.WebView -import android.webkit.WebViewClient -import com.leeeyou.R -import com.leeeyou.manager.sonic.* -import com.leeeyou.util.T -import com.tencent.sonic.sdk.* -import timber.log.Timber -import java.io.BufferedInputStream -import java.io.IOException -import java.lang.ref.WeakReference - -const val PARAM_MODE = "param_mode" -const val PARAM_URL = "param_url" - -class BrowserActivity : AppCompatActivity() { - private var sonicSession: SonicSession? = null - - @SuppressLint("SetJavaScriptEnabled", "AddJavascriptInterface") - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - val url = intent.getStringExtra(PARAM_URL) - val mode = intent.getIntExtra(PARAM_MODE, -1) - - Timber.e(url) - Timber.e("mode is %s", mode) - - if (TextUtils.isEmpty(url) || -1 == mode) { - finish() - return - } - - window.addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) - - if (!SonicEngine.isGetInstanceAllowed()) { - SonicEngine.createInstance(HostSonicRuntime(application), SonicConfig.Builder().build()) - } - - var sonicSessionClient: SonicSessionClientImpl? = null - - // if it's sonic mode , startup sonic session at first time - if (MODE_SONIC == mode) { - val builder = SonicSessionConfig.Builder() - builder.setSupportLocalServer(true) - - // if it's offline pkg mode, we need to intercept the session connection - if (MODE_SONIC_WITH_OFFLINE_CACHE == mode) { - builder.setCacheInterceptor(object : SonicCacheInterceptor(null) { - override fun getCacheData(session: SonicSession?): String? { - return null// offline pkg does not need cache - } - - }) - - builder.setConnectionInterceptor(object : SonicSessionConnectionInterceptor() { - override fun getConnection(session: SonicSession, intent: Intent): SonicSessionConnection { - return OfflinePkgSessionConnection(this@BrowserActivity, session, intent) - } - - }) - } - - // create sonic session and run sonic flow - sonicSession = SonicEngine.getInstance().createSession(url, builder.build()) - if (null != sonicSession) { - sonicSessionClient = SonicSessionClientImpl() - sonicSession!!.bindClient(sonicSessionClient) - } else { - // this only happen when a same sonic session is already running, - // u can comment following codes to feedback as a default mode. - // throw new UnknownError("create session fail!"); - T.showShort(this, "create sonic session fail!") - } - - // start init flow ... - // in the real world, the init flow may cost a long time as startup - // runtime、init configs.... - setContentView(R.layout.activity_browser) - - val btnFab = findViewById(R.id.btn_refresh) - btnFab.setOnClickListener { - sonicSession?.refresh() - } - - // init webView - val webView = findViewById(R.id.webview) as WebView - webView.webViewClient = (object : WebViewClient() { - override fun onPageFinished(view: WebView?, url: String?) { - super.onPageFinished(view, url) - sonicSession?.sessionClient?.pageFinish(url) - } - - @TargetApi(21) - override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest?): WebResourceResponse? { - return shouldInterceptRequest(view, request) - } - - override fun shouldInterceptRequest(view: WebView, url: String): WebResourceResponse? { - return if (sonicSession != null) { - sonicSession?.sessionClient?.requestResource(url) as WebResourceResponse - } else null - } - }) - - val webSettings = webView.settings - - // add java script interface - // note:if api level lower than 17(android 4.2), addJavascriptInterface has security - // issue, please use x5 or see https://developer.android.com/reference/android/webkit/ - // WebView.html#addJavascriptInterface(java.lang.Object, java.lang.String) - webSettings.javaScriptEnabled = true - webView.removeJavascriptInterface("searchBoxJavaBridge_") - intent.putExtra(SonicJavaScriptInterface.PARAM_LOAD_URL_TIME, System.currentTimeMillis()) - webView.addJavascriptInterface(SonicJavaScriptInterface(sonicSessionClient, intent), "sonic") - - // init webView settings - webSettings.allowContentAccess = true - webSettings.databaseEnabled = true - webSettings.domStorageEnabled = true - webSettings.setAppCacheEnabled(true) - webSettings.savePassword = false - webSettings.saveFormData = false - webSettings.useWideViewPort = true - webSettings.loadWithOverviewMode = true - - // webView is ready now, just tell session client to bind - if (sonicSessionClient != null) { - sonicSessionClient.bindWebView(webView) - sonicSessionClient.clientReady() - } else { // default mode - webView.loadUrl(url) - } - } - } - - override fun onDestroy() { - sonicSession?.destroy() - sonicSession = null - super.onDestroy() - } - - private class OfflinePkgSessionConnection(context: Context, session: SonicSession, intent: Intent) - : SonicSessionConnection(session, intent) { - - private val context: WeakReference = WeakReference(context) - - override fun internalConnect(): Int { - val ctx = context.get() - ctx?.let { - try { - val offlineHtmlInputStream = ctx.assets.open("sonic-demo-index.html") - responseStream = BufferedInputStream(offlineHtmlInputStream) - return SonicConstants.ERROR_CODE_SUCCESS - } catch (e: Throwable) { - e.printStackTrace() - } - } - return SonicConstants.ERROR_CODE_UNKNOWN - } - - override fun internalGetResponseStream(): BufferedInputStream { - return responseStream - } - - override fun internalGetCustomHeadFieldEtag(): String { - return SonicSessionConnection.CUSTOM_HEAD_FILED_ETAG - } - - override fun disconnect() { - if (null != responseStream) { - try { - responseStream.close() - } catch (e: IOException) { - e.printStackTrace() - } - - } - } - - override fun getResponseCode(): Int { - return 200 - } - - override fun getResponseHeaderFields(): Map> { - return HashMap(0) - } - - override fun getResponseHeaderField(key: String): String { - return "" - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/manager/sonic/BrowserActivity.java b/app/src/main/java/com/leeeyou/manager/sonic/BrowserActivity.java new file mode 100644 index 0000000..f3a97ca --- /dev/null +++ b/app/src/main/java/com/leeeyou/manager/sonic/BrowserActivity.java @@ -0,0 +1,273 @@ +/* + * Tencent is pleased to support the open source community by making VasSonic available. + * + * Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + * + * + */ + +package com.leeeyou.manager.sonic; + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.design.widget.FloatingActionButton; +import android.text.TextUtils; +import android.view.View; +import android.view.WindowManager; +import android.webkit.WebResourceRequest; +import android.webkit.WebResourceResponse; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.Toast; + +import com.leeeyou.R; +import com.leeeyou.manager.BaseActivity; +import com.tencent.sonic.sdk.SonicCacheInterceptor; +import com.tencent.sonic.sdk.SonicConfig; +import com.tencent.sonic.sdk.SonicConstants; +import com.tencent.sonic.sdk.SonicEngine; +import com.tencent.sonic.sdk.SonicSession; +import com.tencent.sonic.sdk.SonicSessionConfig; +import com.tencent.sonic.sdk.SonicSessionConnection; +import com.tencent.sonic.sdk.SonicSessionConnectionInterceptor; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.leeeyou.manager.sonic.MySonicConfigKt.MODE_DEFAULT; +import static com.leeeyou.manager.sonic.MySonicConfigKt.MODE_SONIC_WITH_OFFLINE_CACHE; + +/** + * A demo browser activity + * In this demo there are three modes, + * sonic mode: sonic mode means webview loads html by sonic, + * offline mode: offline mode means webview loads html from local offline packages, + * default mode: default mode means webview loads html in the normal way. + */ + +public class BrowserActivity extends BaseActivity { + + + public final static String PARAM_URL = "param_url"; + public final static String PARAM_MODE = "param_mode"; + public final static String PARAM_TITLE = "param_title"; + + private SonicSession sonicSession; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Intent intent = getIntent(); + String url = intent.getStringExtra(PARAM_URL); + int mode = intent.getIntExtra(PARAM_MODE, -1); + if (TextUtils.isEmpty(url) || -1 == mode) { + finish(); + return; + } + + + getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); + + // init sonic engine if necessary, or maybe u can do this when application created + if (!SonicEngine.isGetInstanceAllowed()) { + SonicEngine.createInstance(new SonicRuntimeImpl(getApplication()), new SonicConfig.Builder().build()); + } + + SonicSessionClientImpl sonicSessionClient = null; + + // if it's sonic mode , startup sonic session at first time + if (MODE_DEFAULT != mode) { // sonic mode + SonicSessionConfig.Builder sessionConfigBuilder = new SonicSessionConfig.Builder(); + sessionConfigBuilder.setSupportLocalServer(true); + + // if it's offline pkg mode, we need to intercept the session connection + if (MODE_SONIC_WITH_OFFLINE_CACHE == mode) { + sessionConfigBuilder.setCacheInterceptor(new SonicCacheInterceptor(null) { + @Override + public String getCacheData(SonicSession session) { + return null; // offline pkg does not need cache + } + }); + + sessionConfigBuilder.setConnectionInterceptor(new SonicSessionConnectionInterceptor() { + @Override + public SonicSessionConnection getConnection(SonicSession session, Intent intent) { + return new OfflinePkgSessionConnection(BrowserActivity.this, session, intent); + } + }); + } + + // create sonic session and run sonic flow + sonicSession = SonicEngine.getInstance().createSession(url, sessionConfigBuilder.build()); + if (null != sonicSession) { + sonicSession.bindClient(sonicSessionClient = new SonicSessionClientImpl()); + } else { + // this only happen when a same sonic session is already running, + // u can comment following codes to feedback as a default mode. + // throw new UnknownError("create session fail!"); + Toast.makeText(this, "create sonic session fail!", Toast.LENGTH_LONG).show(); + } + } + + // start init flow ... + // in the real world, the init flow may cost a long time as startup + // runtime、init configs.... + setContentView(R.layout.activity_browser); + setLeftTitleAndDisplayHomeAsUp(intent.getStringExtra(PARAM_TITLE)); + + FloatingActionButton btnFab = findViewById(R.id.btn_refresh); + btnFab.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (sonicSession != null) { + sonicSession.refresh(); + } + } + }); + + // init webview + WebView webView = (WebView) findViewById(R.id.webview); + webView.setWebViewClient(new WebViewClient() { + @Override + public void onPageFinished(WebView view, String url) { + super.onPageFinished(view, url); + if (sonicSession != null) { + sonicSession.getSessionClient().pageFinish(url); + } + } + + @TargetApi(21) + @Override + public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { + return shouldInterceptRequest(view, request.getUrl().toString()); + } + + @Override + public WebResourceResponse shouldInterceptRequest(WebView view, String url) { + if (sonicSession != null) { + return (WebResourceResponse) sonicSession.getSessionClient().requestResource(url); + } + return null; + } + }); + + WebSettings webSettings = webView.getSettings(); + + // add java script interface + // note:if api level lower than 17(android 4.2), addJavascriptInterface has security + // issue, please use x5 or see https://developer.android.com/reference/android/webkit/ + // WebView.html#addJavascriptInterface(java.lang.Object, java.lang.String) + webSettings.setJavaScriptEnabled(true); + webView.removeJavascriptInterface("searchBoxJavaBridge_"); + intent.putExtra(SonicJavaScriptInterface.PARAM_LOAD_URL_TIME, System.currentTimeMillis()); + webView.addJavascriptInterface(new SonicJavaScriptInterface(sonicSessionClient, intent), "sonic"); + + // init webview settings + webSettings.setAllowContentAccess(true); + webSettings.setDatabaseEnabled(true); + webSettings.setDomStorageEnabled(true); + webSettings.setAppCacheEnabled(true); + webSettings.setSavePassword(false); + webSettings.setSaveFormData(false); + webSettings.setUseWideViewPort(true); + webSettings.setLoadWithOverviewMode(true); + + + // webview is ready now, just tell session client to bind + if (sonicSessionClient != null) { + sonicSessionClient.bindWebView(webView); + sonicSessionClient.clientReady(); + } else { // default mode + webView.loadUrl(url); + } + } + + @Override + public void onBackPressed() { + super.onBackPressed(); + } + + @Override + protected void onDestroy() { + if (null != sonicSession) { + sonicSession.destroy(); + sonicSession = null; + } + super.onDestroy(); + } + + + private static class OfflinePkgSessionConnection extends SonicSessionConnection { + + private final WeakReference context; + + public OfflinePkgSessionConnection(Context context, SonicSession session, Intent intent) { + super(session, intent); + this.context = new WeakReference(context); + } + + @Override + protected int internalConnect() { + Context ctx = context.get(); + if (null != ctx) { + try { + InputStream offlineHtmlInputStream = ctx.getAssets().open("sonic-demo-index.html"); + responseStream = new BufferedInputStream(offlineHtmlInputStream); + return SonicConstants.ERROR_CODE_SUCCESS; + } catch (Throwable e) { + e.printStackTrace(); + } + } + return SonicConstants.ERROR_CODE_UNKNOWN; + } + + @Override + protected BufferedInputStream internalGetResponseStream() { + return responseStream; + } + + @Override + protected String internalGetCustomHeadFieldEtag() { + return SonicSessionConnection.CUSTOM_HEAD_FILED_ETAG; + } + + @Override + public void disconnect() { + if (null != responseStream) { + try { + responseStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + @Override + public int getResponseCode() { + return 200; + } + + @Override + public Map> getResponseHeaderFields() { + return new HashMap<>(0); + } + + @Override + public String getResponseHeaderField(String key) { + return ""; + } + } +} diff --git a/app/src/main/java/com/leeeyou/manager/sonic/HostSonicRuntime.kt b/app/src/main/java/com/leeeyou/manager/sonic/HostSonicRuntime.kt deleted file mode 100644 index faf704d..0000000 --- a/app/src/main/java/com/leeeyou/manager/sonic/HostSonicRuntime.kt +++ /dev/null @@ -1,82 +0,0 @@ -package com.leeeyou.manager.sonic - -import android.content.Context -import android.os.Build -import android.text.TextUtils -import android.util.Log -import android.webkit.CookieManager -import android.webkit.WebResourceResponse -import com.leeeyou.util.T -import com.tencent.sonic.sdk.SonicRuntime -import com.tencent.sonic.sdk.SonicSessionClient -import timber.log.Timber -import java.io.InputStream - - -class HostSonicRuntime(context: Context) : SonicRuntime(context) { - override fun showToast(text: CharSequence?, duration: Int) { - T.show(context, text, duration) - } - - override fun log(tag: String?, level: Int, message: String?) { - Timber.tag(tag) - when (level) { - Log.ERROR -> Timber.e(message) - Log.INFO -> Timber.i(message) - else -> Timber.d(message) - } - } - - override fun getUserAgent(): String { - return "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Mobile Safari/537.36" - } - - override fun isNetworkValid(): Boolean { - return true - } - - override fun postTaskToThread(task: Runnable?, delayMillis: Long) { - Thread(task, "SonicThread").start() - } - - override fun isSonicUrl(url: String?): Boolean { - return true - } - - override fun setCookie(url: String?, cookies: MutableList?): Boolean { - if (TextUtils.isEmpty(url) && cookies != null && cookies.size > 0) { - val cookieManager = android.webkit.CookieManager.getInstance() - for (item in cookies) { - cookieManager.setCookie(url, item) - } - return true - } - return false - } - - override fun getCookie(url: String): String { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - val instance = CookieManager.getInstance() - return instance.getCookie(url) - } - - return "" - } - - override fun createWebResourceResponse(mimeType: String?, encoding: String?, data: InputStream?, headers: MutableMap?): Any { - val webResourceResponse = WebResourceResponse(mimeType, encoding, data) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - webResourceResponse.responseHeaders = headers - } - return webResourceResponse - } - - override fun getCurrentUserAccount(): String { - return "ReadSelectionSonic" - } - - override fun notifyError(client: SonicSessionClient?, url: String?, errorCode: Int) { - } - - -} \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.java b/app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.java index a18bfea..dc28585 100644 --- a/app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.java +++ b/app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.java @@ -57,7 +57,7 @@ public void callback(final String resultData) { Runnable callbackRunnable = new Runnable() { @Override public void run() { - String jsCode = "javascript:" + jsCallbackFunc + "('" + toJsString(resultData) + "')"; + String jsCode = "javascript:" + jsCallbackFunc + "('"+ toJsString(resultData) + "')"; sessionClient.getWebView().loadUrl(jsCode); } }; @@ -88,10 +88,10 @@ public String getPerformance() { } /* - * * From RFC 4627, "All Unicode characters may be placed within the quotation marks except - * for the characters that must be escaped: quotation mark, - * reverse solidus, and the control characters (U+0000 through U+001F)." - */ + * * From RFC 4627, "All Unicode characters may be placed within the quotation marks except + * for the characters that must be escaped: quotation mark, + * reverse solidus, and the control characters (U+0000 through U+001F)." + */ private static String toJsString(String value) { if (value == null) { return "null"; diff --git a/app/src/main/java/com/leeeyou/manager/sonic/SonicRuntimeImpl.java b/app/src/main/java/com/leeeyou/manager/sonic/SonicRuntimeImpl.java new file mode 100644 index 0000000..8bac226 --- /dev/null +++ b/app/src/main/java/com/leeeyou/manager/sonic/SonicRuntimeImpl.java @@ -0,0 +1,145 @@ +/* + * Tencent is pleased to support the open source community by making VasSonic available. + * + * Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + * + * + */ + +package com.leeeyou.manager.sonic; + +import android.content.Context; +import android.os.Build; +import android.os.Environment; +import android.text.TextUtils; +import android.util.Log; +import android.webkit.CookieManager; +import android.webkit.WebResourceResponse; + +import com.leeeyou.BuildConfig; +import com.tencent.sonic.sdk.SonicRuntime; +import com.tencent.sonic.sdk.SonicSessionClient; + +import java.io.File; +import java.io.InputStream; +import java.util.List; +import java.util.Map; + +/** + * the sonic host application must implement SonicRuntime to do right things. + */ + +public class SonicRuntimeImpl extends SonicRuntime { + + public SonicRuntimeImpl(Context context) { + super(context); + } + + /** + * 获取用户UA信息 + * @return + */ + @Override + public String getUserAgent() { + return "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Mobile Safari/537.36"; + } + + /** + * 获取用户ID信息 + * @return + */ + @Override + public String getCurrentUserAccount() { + return "sonic-demo-master"; + } + + @Override + public String getCookie(String url) { + CookieManager cookieManager = CookieManager.getInstance(); + return cookieManager.getCookie(url); + } + + @Override + public void log(String tag, int level, String message) { + switch (level) { + case Log.ERROR: + Log.e(tag, message); + break; + case Log.INFO: + Log.i(tag, message); + break; + default: + Log.d(tag, message); + } + } + + @Override + public Object createWebResourceResponse(String mimeType, String encoding, InputStream data, Map headers) { + WebResourceResponse resourceResponse = new WebResourceResponse(mimeType, encoding, data); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + resourceResponse.setResponseHeaders(headers); + } + return resourceResponse; + } + + @Override + public void showToast(CharSequence text, int duration) { + + } + + @Override + public void notifyError(SonicSessionClient client, String url, int errorCode) { + + } + + @Override + public boolean isSonicUrl(String url) { + return true; + } + + @Override + public boolean setCookie(String url, List cookies) { + if (!TextUtils.isEmpty(url) && cookies != null && cookies.size() > 0) { + CookieManager cookieManager = CookieManager.getInstance(); + for (String cookie : cookies) { + cookieManager.setCookie(url, cookie); + } + return true; + } + return false; + } + + @Override + public boolean isNetworkValid() { + return true; + } + + @Override + public void postTaskToThread(Runnable task, long delayMillis) { + Thread thread = new Thread(task, "SonicThread"); + thread.start(); + } + + @Override + public File getSonicCacheDir() { + if (BuildConfig.DEBUG) { + String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "sonic/"; + File file = new File(path.trim()); + if(!file.exists()){ + file.mkdir(); + } + return file; + } + return super.getSonicCacheDir(); + } + + @Override + public String getHostDirectAddress(String url) { + return null; + } +} diff --git a/app/src/main/java/com/leeeyou/manager/sonic/SonicSessionClientImpl.java b/app/src/main/java/com/leeeyou/manager/sonic/SonicSessionClientImpl.java new file mode 100644 index 0000000..3db2bb4 --- /dev/null +++ b/app/src/main/java/com/leeeyou/manager/sonic/SonicSessionClientImpl.java @@ -0,0 +1,62 @@ +/* + * Tencent is pleased to support the open source community by making VasSonic available. + * + * Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + * + * + */ + +package com.leeeyou.manager.sonic; + +import android.os.Bundle; +import android.webkit.WebView; + +import com.tencent.sonic.sdk.SonicSessionClient; + +import java.util.HashMap; + +/** + * a implement of SonicSessionClient which need to connect webview and content data. + */ + +public class SonicSessionClientImpl extends SonicSessionClient { + + private WebView webView; + + public void bindWebView(WebView webView) { + this.webView = webView; + } + + public WebView getWebView() { + return webView; + } + + @Override + public void loadUrl(String url, Bundle extraData) { + webView.loadUrl(url); + } + + @Override + public void loadDataWithBaseUrl(String baseUrl, String data, String mimeType, String encoding, String historyUrl) { + webView.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl); + } + + + @Override + public void loadDataWithBaseUrlAndHeader(String baseUrl, String data, String mimeType, String encoding, String historyUrl, HashMap headers) { + loadDataWithBaseUrl(baseUrl, data, mimeType, encoding, historyUrl); + } + + public void destroy() { + if (null != webView) { + webView.destroy(); + webView = null; + } + } + +} diff --git a/app/src/main/java/com/leeeyou/manager/sonic/SonicSessionClientImpl.kt b/app/src/main/java/com/leeeyou/manager/sonic/SonicSessionClientImpl.kt deleted file mode 100644 index 2685dbd..0000000 --- a/app/src/main/java/com/leeeyou/manager/sonic/SonicSessionClientImpl.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.leeeyou.manager.sonic - -import android.os.Bundle -import android.webkit.WebView -import com.tencent.sonic.sdk.SonicSessionClient -import java.util.* - -class SonicSessionClientImpl : SonicSessionClient() { - private var webView: WebView? = null - - fun bindWebView(webView: WebView) { - this.webView = webView - } - - fun getWebView(): WebView? { - return webView - } - - override fun loadDataWithBaseUrlAndHeader(baseUrl: String?, data: String?, mimeType: String?, encoding: String?, historyUrl: String?, headers: HashMap?) { - loadDataWithBaseUrl(baseUrl, data, mimeType, encoding, historyUrl) - } - - override fun loadUrl(url: String?, extraData: Bundle?) { - webView?.loadUrl(url) - } - - override fun loadDataWithBaseUrl(baseUrl: String?, data: String?, mimeType: String?, encoding: String?, historyUrl: String?) { - webView?.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl) - } - - fun destroy() { - webView?.destroy() - webView = null - } -} \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyAdapter.kt b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyAdapter.kt index 54c46c3..45cdafc 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyAdapter.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyAdapter.kt @@ -1,6 +1,5 @@ package com.leeeyou.zhihudaily.view -import android.content.Intent import com.bumptech.glide.Glide import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.BaseViewHolder @@ -20,12 +19,7 @@ class ZhiHuDailyAdapter(layoutResId: Int, data: List?) vh.setText(R.id.tv_story_title, story.title) .setText(R.id.tv_story_time, story.date) - .setOnClickListener(R.id.rl_item_recommend) { - mContext.startActivity(Intent(mContext, ZhiHuDailyDetailActivity::class.java) - .putExtra("storyId", story.id) - .putExtra("storyTitle", story.title)) - } - + .addOnClickListener(R.id.rl_item_recommend) Glide.with(mContext).load(story.images[0]).into(vh.getView(R.id.iv_story_image)) } diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.kt b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.kt deleted file mode 100644 index aba8fbe..0000000 --- a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyDetailActivity.kt +++ /dev/null @@ -1,73 +0,0 @@ -package com.leeeyou.zhihudaily.view - -import android.content.Intent -import android.os.Bundle -import com.afollestad.materialdialogs.MaterialDialog -import com.leeeyou.R -import com.leeeyou.manager.BaseActivity -import com.leeeyou.manager.BrowserActivity -import com.leeeyou.manager.PARAM_MODE -import com.leeeyou.manager.PARAM_URL -import com.leeeyou.manager.sonic.SonicJavaScriptInterface -import com.leeeyou.util.HtmlUtils -import com.leeeyou.zhihudaily.model.bean.ZhiHuDailyDetail -import com.leeeyou.zhihudaily.model.fetchZhiHuDailyDetailById -import kotlinx.android.synthetic.main.activity_story_detail.* -import rx.Subscriber -import rx.android.schedulers.AndroidSchedulers -import rx.schedulers.Schedulers - - -class ZhiHuDailyDetailActivity : BaseActivity() { - internal lateinit var mMaterialDialog: MaterialDialog - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_story_detail) - setLeftTitleAndDisplayHomeAsUp(intent.getStringExtra("storyTitle")) - initWebView() - fetchZhiHuDetail() - } - - private fun fetchZhiHuDetail() { - fetchZhiHuDailyDetailById(intent.getIntExtra("storyId", -1)) - .subscribeOn(Schedulers.newThread()) - .doOnSubscribe { - mMaterialDialog = MaterialDialog.Builder(this@ZhiHuDailyDetailActivity) - .content("Loading...") - .progress(true, 0) - .show() - } - .subscribeOn(AndroidSchedulers.mainThread()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(object : Subscriber() { - override fun onCompleted() { - mMaterialDialog.dismiss() - } - - override fun onError(e: Throwable) { - mMaterialDialog.dismiss() - e.printStackTrace() - } - - override fun onNext(storyDetail: ZhiHuDailyDetail) { - zhiHuDailyWebview.loadData(HtmlUtils.structHtml(storyDetail.body, storyDetail.css), "text/html; charset=UTF-8", null) -// startBrowserActivity(MODE_SONIC, storyDetail.share_url) - } - }) - } - - private fun startBrowserActivity(mode: Int, url: String) { - val intent = Intent(this, BrowserActivity::class.java) - intent.putExtra(PARAM_URL, url) - intent.putExtra(PARAM_MODE, mode) - intent.putExtra(SonicJavaScriptInterface.PARAM_CLICK_TIME, System.currentTimeMillis()) - startActivity(intent) - } - - private fun initWebView() { - zhiHuDailyWebview.isVerticalScrollBarEnabled = false - zhiHuDailyWebview.settings.defaultTextEncodingName = "UTF-8" - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt index ea1d29d..03b0b94 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt @@ -2,6 +2,7 @@ package com.leeeyou.zhihudaily.view import `in`.srain.cube.views.ptr.PtrDefaultHandler import `in`.srain.cube.views.ptr.PtrFrameLayout +import android.content.Intent import android.os.Bundle import android.support.v7.widget.LinearLayoutManager import android.view.LayoutInflater @@ -10,15 +11,22 @@ import android.view.ViewGroup import com.chad.library.adapter.base.BaseQuickAdapter import com.leeeyou.R import com.leeeyou.manager.BaseFragment +import com.leeeyou.manager.sonic.BrowserActivity +import com.leeeyou.manager.sonic.BrowserActivity.* +import com.leeeyou.manager.sonic.MODE_SONIC +import com.leeeyou.manager.sonic.SonicJavaScriptInterface import com.leeeyou.util.T.showShort import com.leeeyou.zhihudaily.model.bean.ZhiHuDaily +import com.leeeyou.zhihudaily.model.bean.ZhiHuDailyDetail import com.leeeyou.zhihudaily.model.bean.ZhiHuDailyItem +import com.leeeyou.zhihudaily.model.fetchZhiHuDailyDetailById import com.leeeyou.zhihudaily.model.fetchZhiHuDailyListByDate import kotlinx.android.synthetic.main.activity_zhihu_daily.* import org.joda.time.DateTime import rx.Subscriber import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers +import timber.log.Timber class ZhiHuDailyFragment : BaseFragment() { private val mMostDate = 7 @@ -66,9 +74,29 @@ class ZhiHuDailyFragment : BaseFragment() { private fun initAdapter() { mAdapter = ZhiHuDailyAdapter(R.layout.item_zhihu_daily, null) - recyclerViewRiBao.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) - recyclerViewRiBao.adapter = mAdapter mAdapter.openLoadAnimation(BaseQuickAdapter.SCALEIN) + mAdapter.setOnItemChildClickListener { adapter, _, position -> + val item: ZhiHuDailyItem? = adapter.getItem(position) as ZhiHuDailyItem + item?.let { + fetchZhiHuDailyDetailById(it.id) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : Subscriber() { + override fun onCompleted() { + Timber.i("fetchZhiHuDailyDetailById onCompleted") + } + + override fun onError(e: Throwable) { + Timber.e(e) + } + + override fun onNext(storyDetail: ZhiHuDailyDetail) { + Timber.i("fetchZhiHuDailyDetailById onNext") + startBrowserActivity(MODE_SONIC, storyDetail.share_url, it.title) + } + }) + } + } mAdapter.setOnLoadMoreListener({ if (mDatePosition < mMostDate - 1) { fetchZhiHuDailyList(mDateList[++mDatePosition]) @@ -76,6 +104,18 @@ class ZhiHuDailyFragment : BaseFragment() { mAdapter.loadMoreEnd() } }, recyclerViewRiBao) + + recyclerViewRiBao.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) + recyclerViewRiBao.adapter = mAdapter + } + + private fun startBrowserActivity(mode: Int, url: String, title: String) { + val intent = Intent(activity, BrowserActivity::class.java) + intent.putExtra(PARAM_URL, url) + intent.putExtra(PARAM_MODE, mode) + intent.putExtra(PARAM_TITLE, title) + intent.putExtra(SonicJavaScriptInterface.PARAM_CLICK_TIME, System.currentTimeMillis()) + startActivity(intent) } private fun initDataList() { From 90774d0c84b21fd6a6a5aacc7a4be0b3de750849 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Thu, 27 Dec 2018 11:27:51 +0800 Subject: [PATCH 043/150] Kotlin Rewrite Sonic --- .../sonic/SonicJavaScriptInterface.java | 143 ----------------- .../manager/sonic/SonicJavaScriptInterface.kt | 114 ++++++++++++++ .../manager/sonic/SonicRuntimeImpl.java | 145 ------------------ .../leeeyou/manager/sonic/SonicRuntimeImpl.kt | 121 +++++++++++++++ 4 files changed, 235 insertions(+), 288 deletions(-) delete mode 100644 app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.java create mode 100644 app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.kt delete mode 100644 app/src/main/java/com/leeeyou/manager/sonic/SonicRuntimeImpl.java create mode 100644 app/src/main/java/com/leeeyou/manager/sonic/SonicRuntimeImpl.kt diff --git a/app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.java b/app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.java deleted file mode 100644 index dc28585..0000000 --- a/app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making VasSonic available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. - * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - * - * - */ - -package com.leeeyou.manager.sonic; - - -import android.content.Intent; -import android.os.Handler; -import android.os.Looper; -import android.webkit.JavascriptInterface; - -import com.tencent.sonic.sdk.SonicDiffDataCallback; - -import org.json.JSONObject; - -/** - * Sonic javaScript Interface (Android API Level >= 17) - */ - -public class SonicJavaScriptInterface { - - private final SonicSessionClientImpl sessionClient; - - private final Intent intent; - - public static final String PARAM_CLICK_TIME = "clickTime"; - - public static final String PARAM_LOAD_URL_TIME = "loadUrlTime"; - - public SonicJavaScriptInterface(SonicSessionClientImpl sessionClient, Intent intent) { - this.sessionClient = sessionClient; - this.intent = intent; - } - - @JavascriptInterface - public void getDiffData() { - // the callback function of demo page is hardcode as 'getDiffDataCallback' - getDiffData2("getDiffDataCallback"); - } - - @JavascriptInterface - public void getDiffData2(final String jsCallbackFunc) { - if (null != sessionClient) { - sessionClient.getDiffData(new SonicDiffDataCallback() { - @Override - public void callback(final String resultData) { - Runnable callbackRunnable = new Runnable() { - @Override - public void run() { - String jsCode = "javascript:" + jsCallbackFunc + "('"+ toJsString(resultData) + "')"; - sessionClient.getWebView().loadUrl(jsCode); - } - }; - if (Looper.getMainLooper() == Looper.myLooper()) { - callbackRunnable.run(); - } else { - new Handler(Looper.getMainLooper()).post(callbackRunnable); - } - } - }); - } - } - - @JavascriptInterface - public String getPerformance() { - long clickTime = intent.getLongExtra(PARAM_CLICK_TIME, -1); - long loadUrlTime = intent.getLongExtra(PARAM_LOAD_URL_TIME, -1); - try { - JSONObject result = new JSONObject(); - result.put(PARAM_CLICK_TIME, clickTime); - result.put(PARAM_LOAD_URL_TIME, loadUrlTime); - return result.toString(); - } catch (Exception e) { - - } - - return ""; - } - - /* - * * From RFC 4627, "All Unicode characters may be placed within the quotation marks except - * for the characters that must be escaped: quotation mark, - * reverse solidus, and the control characters (U+0000 through U+001F)." - */ - private static String toJsString(String value) { - if (value == null) { - return "null"; - } - StringBuilder out = new StringBuilder(1024); - for (int i = 0, length = value.length(); i < length; i++) { - char c = value.charAt(i); - - - switch (c) { - case '"': - case '\\': - case '/': - out.append('\\').append(c); - break; - - case '\t': - out.append("\\t"); - break; - - case '\b': - out.append("\\b"); - break; - - case '\n': - out.append("\\n"); - break; - - case '\r': - out.append("\\r"); - break; - - case '\f': - out.append("\\f"); - break; - - default: - if (c <= 0x1F) { - out.append(String.format("\\u%04x", (int) c)); - } else { - out.append(c); - } - break; - } - - } - return out.toString(); - } -} diff --git a/app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.kt b/app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.kt new file mode 100644 index 0000000..14306b3 --- /dev/null +++ b/app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.kt @@ -0,0 +1,114 @@ +/* + * Tencent is pleased to support the open source community by making VasSonic available. + * + * Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + * + * + */ + +package com.leeeyou.manager.sonic + + +import android.content.Intent +import android.os.Handler +import android.os.Looper +import android.webkit.JavascriptInterface +import org.json.JSONObject + +/** + * Sonic javaScript Interface (Android API Level >= 17) + */ + +class SonicJavaScriptInterface(private val sessionClient: SonicSessionClientImpl?, private val intent: Intent) { + + val performance: String + @JavascriptInterface + get() { + val clickTime = intent.getLongExtra(PARAM_CLICK_TIME, -1) + val loadUrlTime = intent.getLongExtra(PARAM_LOAD_URL_TIME, -1) + try { + val result = JSONObject() + result.put(PARAM_CLICK_TIME, clickTime) + result.put(PARAM_LOAD_URL_TIME, loadUrlTime) + return result.toString() + } catch (e: Exception) { + + } + + return "" + } + + @JavascriptInterface + fun getDiffData() { + // the callback function of demo page is hardcode as 'getDiffDataCallback' + getDiffData2("getDiffDataCallback") + } + + @JavascriptInterface + fun getDiffData2(jsCallbackFunc: String) { + sessionClient?.getDiffData { resultData -> + val callbackRunnable = Runnable { + val jsCode = "javascript:" + jsCallbackFunc + "('" + toJsString(resultData) + "')" + sessionClient.webView?.loadUrl(jsCode) + } + if (Looper.getMainLooper() == Looper.myLooper()) { + callbackRunnable.run() + } else { + Handler(Looper.getMainLooper()).post(callbackRunnable) + } + } + } + + companion object { + + const val PARAM_CLICK_TIME = "clickTime" + + const val PARAM_LOAD_URL_TIME = "loadUrlTime" + + /* + * * From RFC 4627, "All Unicode characters may be placed within the quotation marks except + * for the characters that must be escaped: quotation mark, + * reverse solidus, and the control characters (U+0000 through U+001F)." + */ + private fun toJsString(value: String?): String { + if (value == null) { + return "null" + } + val out = StringBuilder(1024) + var i = 0 + val length = value.length + while (i < length) { + val c = value[i] + + + when (c) { + '"', '\\', '/' -> out.append('\\').append(c) + + '\t' -> out.append("\\t") + + '\b' -> out.append("\\b") + + '\n' -> out.append("\\n") + + '\r' -> out.append("\\r") + +// '\f' -> out.append("\\f") + + else -> if (c.toInt() <= 0x1F) { + out.append(String.format("\\u%04x", c.toInt())) + } else { + out.append(c) + } + } + i++ + + } + return out.toString() + } + } +} diff --git a/app/src/main/java/com/leeeyou/manager/sonic/SonicRuntimeImpl.java b/app/src/main/java/com/leeeyou/manager/sonic/SonicRuntimeImpl.java deleted file mode 100644 index 8bac226..0000000 --- a/app/src/main/java/com/leeeyou/manager/sonic/SonicRuntimeImpl.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making VasSonic available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. - * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - * - * - */ - -package com.leeeyou.manager.sonic; - -import android.content.Context; -import android.os.Build; -import android.os.Environment; -import android.text.TextUtils; -import android.util.Log; -import android.webkit.CookieManager; -import android.webkit.WebResourceResponse; - -import com.leeeyou.BuildConfig; -import com.tencent.sonic.sdk.SonicRuntime; -import com.tencent.sonic.sdk.SonicSessionClient; - -import java.io.File; -import java.io.InputStream; -import java.util.List; -import java.util.Map; - -/** - * the sonic host application must implement SonicRuntime to do right things. - */ - -public class SonicRuntimeImpl extends SonicRuntime { - - public SonicRuntimeImpl(Context context) { - super(context); - } - - /** - * 获取用户UA信息 - * @return - */ - @Override - public String getUserAgent() { - return "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Mobile Safari/537.36"; - } - - /** - * 获取用户ID信息 - * @return - */ - @Override - public String getCurrentUserAccount() { - return "sonic-demo-master"; - } - - @Override - public String getCookie(String url) { - CookieManager cookieManager = CookieManager.getInstance(); - return cookieManager.getCookie(url); - } - - @Override - public void log(String tag, int level, String message) { - switch (level) { - case Log.ERROR: - Log.e(tag, message); - break; - case Log.INFO: - Log.i(tag, message); - break; - default: - Log.d(tag, message); - } - } - - @Override - public Object createWebResourceResponse(String mimeType, String encoding, InputStream data, Map headers) { - WebResourceResponse resourceResponse = new WebResourceResponse(mimeType, encoding, data); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - resourceResponse.setResponseHeaders(headers); - } - return resourceResponse; - } - - @Override - public void showToast(CharSequence text, int duration) { - - } - - @Override - public void notifyError(SonicSessionClient client, String url, int errorCode) { - - } - - @Override - public boolean isSonicUrl(String url) { - return true; - } - - @Override - public boolean setCookie(String url, List cookies) { - if (!TextUtils.isEmpty(url) && cookies != null && cookies.size() > 0) { - CookieManager cookieManager = CookieManager.getInstance(); - for (String cookie : cookies) { - cookieManager.setCookie(url, cookie); - } - return true; - } - return false; - } - - @Override - public boolean isNetworkValid() { - return true; - } - - @Override - public void postTaskToThread(Runnable task, long delayMillis) { - Thread thread = new Thread(task, "SonicThread"); - thread.start(); - } - - @Override - public File getSonicCacheDir() { - if (BuildConfig.DEBUG) { - String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "sonic/"; - File file = new File(path.trim()); - if(!file.exists()){ - file.mkdir(); - } - return file; - } - return super.getSonicCacheDir(); - } - - @Override - public String getHostDirectAddress(String url) { - return null; - } -} diff --git a/app/src/main/java/com/leeeyou/manager/sonic/SonicRuntimeImpl.kt b/app/src/main/java/com/leeeyou/manager/sonic/SonicRuntimeImpl.kt new file mode 100644 index 0000000..efa1585 --- /dev/null +++ b/app/src/main/java/com/leeeyou/manager/sonic/SonicRuntimeImpl.kt @@ -0,0 +1,121 @@ +/* + * Tencent is pleased to support the open source community by making VasSonic available. + * + * Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + * + * + */ + +package com.leeeyou.manager.sonic + +import android.content.Context +import android.os.Build +import android.os.Environment +import android.text.TextUtils +import android.util.Log +import android.webkit.CookieManager +import android.webkit.WebResourceResponse + +import com.leeeyou.BuildConfig +import com.tencent.sonic.sdk.SonicRuntime +import com.tencent.sonic.sdk.SonicSessionClient + +import java.io.File +import java.io.InputStream + +/** + * the sonic host application must implement SonicRuntime to do right things. + */ + +class SonicRuntimeImpl(context: Context) : SonicRuntime(context) { + + /** + * 获取用户UA信息 + * @return + */ + override fun getUserAgent(): String { + return "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Mobile Safari/537.36" + } + + /** + * 获取用户ID信息 + * @return + */ + override fun getCurrentUserAccount(): String { + return "sonic-demo-master" + } + + override fun getCookie(url: String): String { + val cookieManager = CookieManager.getInstance() + return cookieManager.getCookie(url) + } + + override fun log(tag: String, level: Int, message: String) { + when (level) { + Log.ERROR -> Log.e(tag, message) + Log.INFO -> Log.i(tag, message) + else -> Log.d(tag, message) + } + } + + override fun createWebResourceResponse(mimeType: String, encoding: String, data: InputStream, headers: Map): Any { + val resourceResponse = WebResourceResponse(mimeType, encoding, data) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + resourceResponse.responseHeaders = headers + } + return resourceResponse + } + + override fun showToast(text: CharSequence, duration: Int) { + + } + + override fun notifyError(client: SonicSessionClient, url: String, errorCode: Int) { + + } + + override fun isSonicUrl(url: String): Boolean { + return true + } + + override fun setCookie(url: String, cookies: List?): Boolean { + if (!TextUtils.isEmpty(url) && cookies != null && cookies.isNotEmpty()) { + val cookieManager = CookieManager.getInstance() + for (cookie in cookies) { + cookieManager.setCookie(url, cookie) + } + return true + } + return false + } + + override fun isNetworkValid(): Boolean { + return true + } + + override fun postTaskToThread(task: Runnable, delayMillis: Long) { + val thread = Thread(task, "SonicThread") + thread.start() + } + + override fun getSonicCacheDir(): File { + if (BuildConfig.DEBUG) { + val path = Environment.getExternalStorageDirectory().absolutePath + File.separator + "sonic/" + val file = File(path.trim { it <= ' ' }) + if (!file.exists()) { + file.mkdir() + } + return file + } + return super.getSonicCacheDir() + } + + override fun getHostDirectAddress(url: String?): String? { + return null + } +} From aef44bc7e2fbe090c09537bc7f95b357bd967819 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Fri, 28 Dec 2018 11:07:39 +0800 Subject: [PATCH 044/150] Extract BrowserUtil.kt and complete banner click event --- .../sonic/SonicJavaScriptInterface.java | 143 +++++++++++++++++ .../manager/sonic/SonicJavaScriptInterface.kt | 114 -------------- .../manager/sonic/SonicRuntimeImpl.java | 145 ++++++++++++++++++ .../leeeyou/manager/sonic/SonicRuntimeImpl.kt | 121 --------------- .../main/java/com/leeeyou/util/BrowserUtil.kt | 27 ++++ .../wanandroid/WanAndroidRecommendFragment.kt | 17 +- .../zhihudaily/view/ZhiHuDailyFragment.kt | 19 +-- 7 files changed, 328 insertions(+), 258 deletions(-) create mode 100644 app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.java delete mode 100644 app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.kt create mode 100644 app/src/main/java/com/leeeyou/manager/sonic/SonicRuntimeImpl.java delete mode 100644 app/src/main/java/com/leeeyou/manager/sonic/SonicRuntimeImpl.kt create mode 100644 app/src/main/java/com/leeeyou/util/BrowserUtil.kt diff --git a/app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.java b/app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.java new file mode 100644 index 0000000..dc28585 --- /dev/null +++ b/app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.java @@ -0,0 +1,143 @@ +/* + * Tencent is pleased to support the open source community by making VasSonic available. + * + * Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + * + * + */ + +package com.leeeyou.manager.sonic; + + +import android.content.Intent; +import android.os.Handler; +import android.os.Looper; +import android.webkit.JavascriptInterface; + +import com.tencent.sonic.sdk.SonicDiffDataCallback; + +import org.json.JSONObject; + +/** + * Sonic javaScript Interface (Android API Level >= 17) + */ + +public class SonicJavaScriptInterface { + + private final SonicSessionClientImpl sessionClient; + + private final Intent intent; + + public static final String PARAM_CLICK_TIME = "clickTime"; + + public static final String PARAM_LOAD_URL_TIME = "loadUrlTime"; + + public SonicJavaScriptInterface(SonicSessionClientImpl sessionClient, Intent intent) { + this.sessionClient = sessionClient; + this.intent = intent; + } + + @JavascriptInterface + public void getDiffData() { + // the callback function of demo page is hardcode as 'getDiffDataCallback' + getDiffData2("getDiffDataCallback"); + } + + @JavascriptInterface + public void getDiffData2(final String jsCallbackFunc) { + if (null != sessionClient) { + sessionClient.getDiffData(new SonicDiffDataCallback() { + @Override + public void callback(final String resultData) { + Runnable callbackRunnable = new Runnable() { + @Override + public void run() { + String jsCode = "javascript:" + jsCallbackFunc + "('"+ toJsString(resultData) + "')"; + sessionClient.getWebView().loadUrl(jsCode); + } + }; + if (Looper.getMainLooper() == Looper.myLooper()) { + callbackRunnable.run(); + } else { + new Handler(Looper.getMainLooper()).post(callbackRunnable); + } + } + }); + } + } + + @JavascriptInterface + public String getPerformance() { + long clickTime = intent.getLongExtra(PARAM_CLICK_TIME, -1); + long loadUrlTime = intent.getLongExtra(PARAM_LOAD_URL_TIME, -1); + try { + JSONObject result = new JSONObject(); + result.put(PARAM_CLICK_TIME, clickTime); + result.put(PARAM_LOAD_URL_TIME, loadUrlTime); + return result.toString(); + } catch (Exception e) { + + } + + return ""; + } + + /* + * * From RFC 4627, "All Unicode characters may be placed within the quotation marks except + * for the characters that must be escaped: quotation mark, + * reverse solidus, and the control characters (U+0000 through U+001F)." + */ + private static String toJsString(String value) { + if (value == null) { + return "null"; + } + StringBuilder out = new StringBuilder(1024); + for (int i = 0, length = value.length(); i < length; i++) { + char c = value.charAt(i); + + + switch (c) { + case '"': + case '\\': + case '/': + out.append('\\').append(c); + break; + + case '\t': + out.append("\\t"); + break; + + case '\b': + out.append("\\b"); + break; + + case '\n': + out.append("\\n"); + break; + + case '\r': + out.append("\\r"); + break; + + case '\f': + out.append("\\f"); + break; + + default: + if (c <= 0x1F) { + out.append(String.format("\\u%04x", (int) c)); + } else { + out.append(c); + } + break; + } + + } + return out.toString(); + } +} diff --git a/app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.kt b/app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.kt deleted file mode 100644 index 14306b3..0000000 --- a/app/src/main/java/com/leeeyou/manager/sonic/SonicJavaScriptInterface.kt +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making VasSonic available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. - * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - * - * - */ - -package com.leeeyou.manager.sonic - - -import android.content.Intent -import android.os.Handler -import android.os.Looper -import android.webkit.JavascriptInterface -import org.json.JSONObject - -/** - * Sonic javaScript Interface (Android API Level >= 17) - */ - -class SonicJavaScriptInterface(private val sessionClient: SonicSessionClientImpl?, private val intent: Intent) { - - val performance: String - @JavascriptInterface - get() { - val clickTime = intent.getLongExtra(PARAM_CLICK_TIME, -1) - val loadUrlTime = intent.getLongExtra(PARAM_LOAD_URL_TIME, -1) - try { - val result = JSONObject() - result.put(PARAM_CLICK_TIME, clickTime) - result.put(PARAM_LOAD_URL_TIME, loadUrlTime) - return result.toString() - } catch (e: Exception) { - - } - - return "" - } - - @JavascriptInterface - fun getDiffData() { - // the callback function of demo page is hardcode as 'getDiffDataCallback' - getDiffData2("getDiffDataCallback") - } - - @JavascriptInterface - fun getDiffData2(jsCallbackFunc: String) { - sessionClient?.getDiffData { resultData -> - val callbackRunnable = Runnable { - val jsCode = "javascript:" + jsCallbackFunc + "('" + toJsString(resultData) + "')" - sessionClient.webView?.loadUrl(jsCode) - } - if (Looper.getMainLooper() == Looper.myLooper()) { - callbackRunnable.run() - } else { - Handler(Looper.getMainLooper()).post(callbackRunnable) - } - } - } - - companion object { - - const val PARAM_CLICK_TIME = "clickTime" - - const val PARAM_LOAD_URL_TIME = "loadUrlTime" - - /* - * * From RFC 4627, "All Unicode characters may be placed within the quotation marks except - * for the characters that must be escaped: quotation mark, - * reverse solidus, and the control characters (U+0000 through U+001F)." - */ - private fun toJsString(value: String?): String { - if (value == null) { - return "null" - } - val out = StringBuilder(1024) - var i = 0 - val length = value.length - while (i < length) { - val c = value[i] - - - when (c) { - '"', '\\', '/' -> out.append('\\').append(c) - - '\t' -> out.append("\\t") - - '\b' -> out.append("\\b") - - '\n' -> out.append("\\n") - - '\r' -> out.append("\\r") - -// '\f' -> out.append("\\f") - - else -> if (c.toInt() <= 0x1F) { - out.append(String.format("\\u%04x", c.toInt())) - } else { - out.append(c) - } - } - i++ - - } - return out.toString() - } - } -} diff --git a/app/src/main/java/com/leeeyou/manager/sonic/SonicRuntimeImpl.java b/app/src/main/java/com/leeeyou/manager/sonic/SonicRuntimeImpl.java new file mode 100644 index 0000000..8bac226 --- /dev/null +++ b/app/src/main/java/com/leeeyou/manager/sonic/SonicRuntimeImpl.java @@ -0,0 +1,145 @@ +/* + * Tencent is pleased to support the open source community by making VasSonic available. + * + * Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + * + * + */ + +package com.leeeyou.manager.sonic; + +import android.content.Context; +import android.os.Build; +import android.os.Environment; +import android.text.TextUtils; +import android.util.Log; +import android.webkit.CookieManager; +import android.webkit.WebResourceResponse; + +import com.leeeyou.BuildConfig; +import com.tencent.sonic.sdk.SonicRuntime; +import com.tencent.sonic.sdk.SonicSessionClient; + +import java.io.File; +import java.io.InputStream; +import java.util.List; +import java.util.Map; + +/** + * the sonic host application must implement SonicRuntime to do right things. + */ + +public class SonicRuntimeImpl extends SonicRuntime { + + public SonicRuntimeImpl(Context context) { + super(context); + } + + /** + * 获取用户UA信息 + * @return + */ + @Override + public String getUserAgent() { + return "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Mobile Safari/537.36"; + } + + /** + * 获取用户ID信息 + * @return + */ + @Override + public String getCurrentUserAccount() { + return "sonic-demo-master"; + } + + @Override + public String getCookie(String url) { + CookieManager cookieManager = CookieManager.getInstance(); + return cookieManager.getCookie(url); + } + + @Override + public void log(String tag, int level, String message) { + switch (level) { + case Log.ERROR: + Log.e(tag, message); + break; + case Log.INFO: + Log.i(tag, message); + break; + default: + Log.d(tag, message); + } + } + + @Override + public Object createWebResourceResponse(String mimeType, String encoding, InputStream data, Map headers) { + WebResourceResponse resourceResponse = new WebResourceResponse(mimeType, encoding, data); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + resourceResponse.setResponseHeaders(headers); + } + return resourceResponse; + } + + @Override + public void showToast(CharSequence text, int duration) { + + } + + @Override + public void notifyError(SonicSessionClient client, String url, int errorCode) { + + } + + @Override + public boolean isSonicUrl(String url) { + return true; + } + + @Override + public boolean setCookie(String url, List cookies) { + if (!TextUtils.isEmpty(url) && cookies != null && cookies.size() > 0) { + CookieManager cookieManager = CookieManager.getInstance(); + for (String cookie : cookies) { + cookieManager.setCookie(url, cookie); + } + return true; + } + return false; + } + + @Override + public boolean isNetworkValid() { + return true; + } + + @Override + public void postTaskToThread(Runnable task, long delayMillis) { + Thread thread = new Thread(task, "SonicThread"); + thread.start(); + } + + @Override + public File getSonicCacheDir() { + if (BuildConfig.DEBUG) { + String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "sonic/"; + File file = new File(path.trim()); + if(!file.exists()){ + file.mkdir(); + } + return file; + } + return super.getSonicCacheDir(); + } + + @Override + public String getHostDirectAddress(String url) { + return null; + } +} diff --git a/app/src/main/java/com/leeeyou/manager/sonic/SonicRuntimeImpl.kt b/app/src/main/java/com/leeeyou/manager/sonic/SonicRuntimeImpl.kt deleted file mode 100644 index efa1585..0000000 --- a/app/src/main/java/com/leeeyou/manager/sonic/SonicRuntimeImpl.kt +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Tencent is pleased to support the open source community by making VasSonic available. - * - * Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. - * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - * - * https://opensource.org/licenses/BSD-3-Clause - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - * - * - */ - -package com.leeeyou.manager.sonic - -import android.content.Context -import android.os.Build -import android.os.Environment -import android.text.TextUtils -import android.util.Log -import android.webkit.CookieManager -import android.webkit.WebResourceResponse - -import com.leeeyou.BuildConfig -import com.tencent.sonic.sdk.SonicRuntime -import com.tencent.sonic.sdk.SonicSessionClient - -import java.io.File -import java.io.InputStream - -/** - * the sonic host application must implement SonicRuntime to do right things. - */ - -class SonicRuntimeImpl(context: Context) : SonicRuntime(context) { - - /** - * 获取用户UA信息 - * @return - */ - override fun getUserAgent(): String { - return "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Mobile Safari/537.36" - } - - /** - * 获取用户ID信息 - * @return - */ - override fun getCurrentUserAccount(): String { - return "sonic-demo-master" - } - - override fun getCookie(url: String): String { - val cookieManager = CookieManager.getInstance() - return cookieManager.getCookie(url) - } - - override fun log(tag: String, level: Int, message: String) { - when (level) { - Log.ERROR -> Log.e(tag, message) - Log.INFO -> Log.i(tag, message) - else -> Log.d(tag, message) - } - } - - override fun createWebResourceResponse(mimeType: String, encoding: String, data: InputStream, headers: Map): Any { - val resourceResponse = WebResourceResponse(mimeType, encoding, data) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - resourceResponse.responseHeaders = headers - } - return resourceResponse - } - - override fun showToast(text: CharSequence, duration: Int) { - - } - - override fun notifyError(client: SonicSessionClient, url: String, errorCode: Int) { - - } - - override fun isSonicUrl(url: String): Boolean { - return true - } - - override fun setCookie(url: String, cookies: List?): Boolean { - if (!TextUtils.isEmpty(url) && cookies != null && cookies.isNotEmpty()) { - val cookieManager = CookieManager.getInstance() - for (cookie in cookies) { - cookieManager.setCookie(url, cookie) - } - return true - } - return false - } - - override fun isNetworkValid(): Boolean { - return true - } - - override fun postTaskToThread(task: Runnable, delayMillis: Long) { - val thread = Thread(task, "SonicThread") - thread.start() - } - - override fun getSonicCacheDir(): File { - if (BuildConfig.DEBUG) { - val path = Environment.getExternalStorageDirectory().absolutePath + File.separator + "sonic/" - val file = File(path.trim { it <= ' ' }) - if (!file.exists()) { - file.mkdir() - } - return file - } - return super.getSonicCacheDir() - } - - override fun getHostDirectAddress(url: String?): String? { - return null - } -} diff --git a/app/src/main/java/com/leeeyou/util/BrowserUtil.kt b/app/src/main/java/com/leeeyou/util/BrowserUtil.kt new file mode 100644 index 0000000..e6b8387 --- /dev/null +++ b/app/src/main/java/com/leeeyou/util/BrowserUtil.kt @@ -0,0 +1,27 @@ +package com.leeeyou.util + +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.support.v4.app.Fragment +import com.leeeyou.manager.sonic.BrowserActivity +import com.leeeyou.manager.sonic.BrowserActivity.* +import com.leeeyou.manager.sonic.MODE_SONIC +import com.leeeyou.manager.sonic.SonicJavaScriptInterface + +fun Activity.startBrowserActivity(context: Context, url: String, title: String) { + gotoBrowserActivity(context, url, title) +} + +fun Fragment.startBrowserActivity(context: Context, url: String, title: String) { + gotoBrowserActivity(context, url, title) +} + +private fun gotoBrowserActivity(context: Context, url: String, title: String) { + val intent = Intent(context, BrowserActivity::class.java) + intent.putExtra(PARAM_URL, url) + intent.putExtra(PARAM_MODE, MODE_SONIC) + intent.putExtra(PARAM_TITLE, title) + intent.putExtra(SonicJavaScriptInterface.PARAM_CLICK_TIME, System.currentTimeMillis()) + context.startActivity(intent) +} \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt index 18d2bd8..acaf6b7 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt @@ -13,6 +13,7 @@ import com.bumptech.glide.request.RequestOptions import com.leeeyou.R import com.leeeyou.manager.BaseFragment import com.leeeyou.util.inflate +import com.leeeyou.util.startBrowserActivity import com.leeeyou.wanandroid.model.bean.Banner import com.leeeyou.wanandroid.model.bean.ResponseBanner import com.leeeyou.wanandroid.model.fetchBannerList @@ -45,15 +46,15 @@ class WanAndroidRecommendFragment : BaseFragment() { .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(object : Subscriber() { - override fun onNext(t: ResponseBanner) { + override fun onNext(responseBanner: ResponseBanner) { println("fetchBannerList onNext") - println(t) + println(responseBanner) - t.takeIf { + responseBanner.takeIf { it.errorCode >= 0 }?.also { renderBanner(it.data) - } ?: onError(IllegalArgumentException("接口返回异常")) + } ?: onError(IllegalArgumentException("Banner接口返回异常")) } override fun onCompleted() { @@ -81,15 +82,17 @@ class WanAndroidRecommendFragment : BaseFragment() { } }) banner.setDelayTime(3000) - banner.setOnBannerListener { - Timber.d("click position is %s", it.toString()) - } } private fun renderBanner(bannerList: List) { bannerList.map { it.imagePath }.run { banner.setImages(this) banner.setBannerAnimation(Transformer.Default) + banner.setOnBannerListener { it -> + val banner = bannerList[it] + Timber.d("click banner position is %s , the url is %s", it, banner.url) + startBrowserActivity(context!!, banner.url, banner.title) + } banner.start() } } diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt index 03b0b94..2e55582 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt @@ -2,7 +2,6 @@ package com.leeeyou.zhihudaily.view import `in`.srain.cube.views.ptr.PtrDefaultHandler import `in`.srain.cube.views.ptr.PtrFrameLayout -import android.content.Intent import android.os.Bundle import android.support.v7.widget.LinearLayoutManager import android.view.LayoutInflater @@ -11,11 +10,8 @@ import android.view.ViewGroup import com.chad.library.adapter.base.BaseQuickAdapter import com.leeeyou.R import com.leeeyou.manager.BaseFragment -import com.leeeyou.manager.sonic.BrowserActivity -import com.leeeyou.manager.sonic.BrowserActivity.* -import com.leeeyou.manager.sonic.MODE_SONIC -import com.leeeyou.manager.sonic.SonicJavaScriptInterface import com.leeeyou.util.T.showShort +import com.leeeyou.util.startBrowserActivity import com.leeeyou.zhihudaily.model.bean.ZhiHuDaily import com.leeeyou.zhihudaily.model.bean.ZhiHuDailyDetail import com.leeeyou.zhihudaily.model.bean.ZhiHuDailyItem @@ -77,7 +73,7 @@ class ZhiHuDailyFragment : BaseFragment() { mAdapter.openLoadAnimation(BaseQuickAdapter.SCALEIN) mAdapter.setOnItemChildClickListener { adapter, _, position -> val item: ZhiHuDailyItem? = adapter.getItem(position) as ZhiHuDailyItem - item?.let { + item?.let { it -> fetchZhiHuDailyDetailById(it.id) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) @@ -92,7 +88,7 @@ class ZhiHuDailyFragment : BaseFragment() { override fun onNext(storyDetail: ZhiHuDailyDetail) { Timber.i("fetchZhiHuDailyDetailById onNext") - startBrowserActivity(MODE_SONIC, storyDetail.share_url, it.title) + startBrowserActivity(context!!, storyDetail.share_url, it.title) } }) } @@ -109,15 +105,6 @@ class ZhiHuDailyFragment : BaseFragment() { recyclerViewRiBao.adapter = mAdapter } - private fun startBrowserActivity(mode: Int, url: String, title: String) { - val intent = Intent(activity, BrowserActivity::class.java) - intent.putExtra(PARAM_URL, url) - intent.putExtra(PARAM_MODE, mode) - intent.putExtra(PARAM_TITLE, title) - intent.putExtra(SonicJavaScriptInterface.PARAM_CLICK_TIME, System.currentTimeMillis()) - startActivity(intent) - } - private fun initDataList() { val now = DateTime.now().plusDays(1) for (i in 0 until mMostDate) { From 15f13c039054acb20bedd88f0e995a1742d4d5f0 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Fri, 28 Dec 2018 11:17:34 +0800 Subject: [PATCH 045/150] Optimization non-empty judgment --- .../wanandroid/WanAndroidRecommendFragment.kt | 24 ++++++++++--------- .../zhihudaily/view/ZhiHuDailyFragment.kt | 4 ++-- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt index acaf6b7..a05b3ba 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt @@ -47,7 +47,7 @@ class WanAndroidRecommendFragment : BaseFragment() { .observeOn(AndroidSchedulers.mainThread()) .subscribe(object : Subscriber() { override fun onNext(responseBanner: ResponseBanner) { - println("fetchBannerList onNext") + Timber.d("fetchBannerList onNext") println(responseBanner) responseBanner.takeIf { @@ -58,11 +58,11 @@ class WanAndroidRecommendFragment : BaseFragment() { } override fun onCompleted() { - println("fetchBannerList onCompleted") + Timber.d("fetchBannerList onCompleted") } override fun onError(e: Throwable?) { - println("fetchBannerList onError") + Timber.d("fetchBannerList onError") } }) } @@ -70,14 +70,16 @@ class WanAndroidRecommendFragment : BaseFragment() { private fun initBanner() { banner.setImageLoader(object : ImageLoader() { override fun displayImage(context: Context?, path: Any?, imageView: ImageView?) { - if (context != null && imageView != null) { - Glide.with(context) - .load(path) - .apply(RequestOptions() - .override(banner.width, banner.height) - .fitCenter() - .transforms(CenterCrop(), RoundedCorners(30))) - .into(imageView) + context?.let { + imageView?.let { + Glide.with(context) + .load(path) + .apply(RequestOptions() + .override(banner.width, banner.height) + .fitCenter() + .transforms(CenterCrop(), RoundedCorners(30))) + .into(imageView) + } } } }) diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt index 2e55582..a3e2b16 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt @@ -73,7 +73,7 @@ class ZhiHuDailyFragment : BaseFragment() { mAdapter.openLoadAnimation(BaseQuickAdapter.SCALEIN) mAdapter.setOnItemChildClickListener { adapter, _, position -> val item: ZhiHuDailyItem? = adapter.getItem(position) as ZhiHuDailyItem - item?.let { it -> + item?.let { fetchZhiHuDailyDetailById(it.id) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) @@ -88,7 +88,7 @@ class ZhiHuDailyFragment : BaseFragment() { override fun onNext(storyDetail: ZhiHuDailyDetail) { Timber.i("fetchZhiHuDailyDetailById onNext") - startBrowserActivity(context!!, storyDetail.share_url, it.title) + startBrowserActivity(context!!, storyDetail.share_url, storyDetail.title) } }) } From 3098381a88146fa67efc7fff10cd3bb0ab6d0435 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Sat, 29 Dec 2018 15:14:27 +0800 Subject: [PATCH 046/150] Remove IndexActivity Toolbar --- .../main/java/com/leeeyou/IndexActivity.kt | 4 +-- .../manager/sonic/BrowserActivity.java | 26 ++++++------------- .../java/com/leeeyou/util/ToolbarHelper.java | 4 +-- .../wanandroid/WanAndroidRecommendFragment.kt | 3 +++ app/src/main/res/layout/activity_browser.xml | 11 +------- app/src/main/res/layout/activity_index.xml | 3 ++- .../layout/fragment_wan_android_recommend.xml | 6 ++--- 7 files changed, 20 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/com/leeeyou/IndexActivity.kt b/app/src/main/java/com/leeeyou/IndexActivity.kt index 99f7e53..a520089 100644 --- a/app/src/main/java/com/leeeyou/IndexActivity.kt +++ b/app/src/main/java/com/leeeyou/IndexActivity.kt @@ -2,7 +2,7 @@ package com.leeeyou import android.os.Bundle import android.support.v4.view.ViewPager -import com.leeeyou.manager.BaseActivity +import android.support.v7.app.AppCompatActivity import com.leeeyou.util.ViewPagerAdapter import com.leeeyou.wanandroid.WanAndroidFragment import com.leeeyou.weather.WeatherFragment @@ -17,7 +17,7 @@ private const val FIRST_PAGE_INDEX: Int = 0 * Author: leeeyou * Date: 2018/12/21 18:02 */ -class IndexActivity : BaseActivity() { +class IndexActivity : AppCompatActivity() { private lateinit var mViewPagerAdapter: ViewPagerAdapter diff --git a/app/src/main/java/com/leeeyou/manager/sonic/BrowserActivity.java b/app/src/main/java/com/leeeyou/manager/sonic/BrowserActivity.java index f3a97ca..ed1436b 100644 --- a/app/src/main/java/com/leeeyou/manager/sonic/BrowserActivity.java +++ b/app/src/main/java/com/leeeyou/manager/sonic/BrowserActivity.java @@ -13,13 +13,12 @@ package com.leeeyou.manager.sonic; +import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.support.design.widget.FloatingActionButton; import android.text.TextUtils; -import android.view.View; import android.view.WindowManager; import android.webkit.WebResourceRequest; import android.webkit.WebResourceResponse; @@ -67,6 +66,7 @@ public class BrowserActivity extends BaseActivity { private SonicSession sonicSession; + @SuppressLint({"SetJavaScriptEnabled", "AddJavascriptInterface"}) @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -128,18 +128,8 @@ public SonicSessionConnection getConnection(SonicSession session, Intent intent) setContentView(R.layout.activity_browser); setLeftTitleAndDisplayHomeAsUp(intent.getStringExtra(PARAM_TITLE)); - FloatingActionButton btnFab = findViewById(R.id.btn_refresh); - btnFab.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if (sonicSession != null) { - sonicSession.refresh(); - } - } - }); - - // init webview - WebView webView = (WebView) findViewById(R.id.webview); + // init webView + WebView webView = findViewById(R.id.webView); webView.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView view, String url) { @@ -175,7 +165,7 @@ public WebResourceResponse shouldInterceptRequest(WebView view, String url) { intent.putExtra(SonicJavaScriptInterface.PARAM_LOAD_URL_TIME, System.currentTimeMillis()); webView.addJavascriptInterface(new SonicJavaScriptInterface(sonicSessionClient, intent), "sonic"); - // init webview settings + // init webView settings webSettings.setAllowContentAccess(true); webSettings.setDatabaseEnabled(true); webSettings.setDomStorageEnabled(true); @@ -186,7 +176,7 @@ public WebResourceResponse shouldInterceptRequest(WebView view, String url) { webSettings.setLoadWithOverviewMode(true); - // webview is ready now, just tell session client to bind + // webView is ready now, just tell session client to bind if (sonicSessionClient != null) { sonicSessionClient.bindWebView(webView); sonicSessionClient.clientReady(); @@ -214,9 +204,9 @@ private static class OfflinePkgSessionConnection extends SonicSessionConnection private final WeakReference context; - public OfflinePkgSessionConnection(Context context, SonicSession session, Intent intent) { + OfflinePkgSessionConnection(Context context, SonicSession session, Intent intent) { super(session, intent); - this.context = new WeakReference(context); + this.context = new WeakReference<>(context); } @Override diff --git a/app/src/main/java/com/leeeyou/util/ToolbarHelper.java b/app/src/main/java/com/leeeyou/util/ToolbarHelper.java index 95d1ad1..68a10f1 100644 --- a/app/src/main/java/com/leeeyou/util/ToolbarHelper.java +++ b/app/src/main/java/com/leeeyou/util/ToolbarHelper.java @@ -29,7 +29,7 @@ public static void checkSdkVersionToTranslucentFlag(Window window) { } public static void initToolbar(AppCompatActivity activity) { - Toolbar toolbar = (Toolbar) activity.findViewById(R.id.toolbar); + Toolbar toolbar = activity.findViewById(R.id.toolbar); if (toolbar != null) activity.setSupportActionBar(toolbar); } @@ -39,7 +39,7 @@ public static void setContentView(AppCompatActivity activity, int layoutResID) { } public static void setContentView(AppCompatActivity activity, View view) { - LinearLayout rootLayout = (LinearLayout) activity.findViewById(R.id.rootLayout); + LinearLayout rootLayout = activity.findViewById(R.id.rootLayout); if (rootLayout == null) return; diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt index a05b3ba..8c1f5ec 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt @@ -41,7 +41,10 @@ class WanAndroidRecommendFragment : BaseFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) initBanner() + fetchBannerListFromServer() + } + private fun fetchBannerListFromServer() { fetchBannerList() .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) diff --git a/app/src/main/res/layout/activity_browser.xml b/app/src/main/res/layout/activity_browser.xml index c8c357f..6d58029 100644 --- a/app/src/main/res/layout/activity_browser.xml +++ b/app/src/main/res/layout/activity_browser.xml @@ -1,20 +1,11 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_index.xml b/app/src/main/res/layout/activity_index.xml index ce8dc23..2419f66 100644 --- a/app/src/main/res/layout/activity_index.xml +++ b/app/src/main/res/layout/activity_index.xml @@ -4,7 +4,8 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:background="#fff" - android:orientation="vertical"> + android:orientation="vertical" + android:paddingTop="25dp"> - \ No newline at end of file From d60061d92a7935b25d6c2be1d451f31b9d943afc Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Sat, 29 Dec 2018 17:55:33 +0800 Subject: [PATCH 047/150] Rewrite IndexActivity UI Style --- app/build.gradle | 3 + .../main/java/com/leeeyou/IndexActivity.kt | 59 +++++++++--------- .../java/com/leeeyou/util/ViewPagerAdapter.kt | 2 +- .../com/leeeyou/widget/TintableImageView.java | 58 +++++++++++++++++ app/src/main/res/color/custom_tab_icon.xml | 5 ++ app/src/main/res/layout/activity_index.xml | 18 +++--- app/src/main/res/layout/custom_tab_icon1.xml | 11 ++++ .../res/mipmap-xhdpi/index_icon_android.png | Bin 0 -> 1077 bytes .../res/mipmap-xhdpi/index_icon_weather.png | Bin 0 -> 1046 bytes .../res/mipmap-xhdpi/index_icon_zhihu.png | Bin 0 -> 1311 bytes app/src/main/res/values/attrs.xml | 6 ++ app/src/main/res/values/colors.xml | 4 +- 12 files changed, 128 insertions(+), 38 deletions(-) create mode 100644 app/src/main/java/com/leeeyou/widget/TintableImageView.java create mode 100644 app/src/main/res/color/custom_tab_icon.xml create mode 100644 app/src/main/res/layout/custom_tab_icon1.xml create mode 100644 app/src/main/res/mipmap-xhdpi/index_icon_android.png create mode 100644 app/src/main/res/mipmap-xhdpi/index_icon_weather.png create mode 100644 app/src/main/res/mipmap-xhdpi/index_icon_zhihu.png create mode 100644 app/src/main/res/values/attrs.xml diff --git a/app/build.gradle b/app/build.gradle index 26cf99e..0fb9ca7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -89,4 +89,7 @@ dependencies { implementation 'com.jakewharton.timber:timber:4.7.1' implementation 'com.tencent.sonic:sdk:3.1.0' + //smarttablayout + implementation 'com.ogaclejapan.smarttablayout:library:1.6.1@aar' + implementation 'com.ogaclejapan.smarttablayout:utils-v4:1.6.1@aar' } \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/IndexActivity.kt b/app/src/main/java/com/leeeyou/IndexActivity.kt index a520089..7d726d2 100644 --- a/app/src/main/java/com/leeeyou/IndexActivity.kt +++ b/app/src/main/java/com/leeeyou/IndexActivity.kt @@ -1,15 +1,20 @@ package com.leeeyou import android.os.Bundle -import android.support.v4.view.ViewPager import android.support.v7.app.AppCompatActivity -import com.leeeyou.util.ViewPagerAdapter +import android.view.LayoutInflater +import android.widget.ImageView import com.leeeyou.wanandroid.WanAndroidFragment import com.leeeyou.weather.WeatherFragment import com.leeeyou.zhihudaily.view.ZhiHuDailyFragment +import com.ogaclejapan.smarttablayout.utils.v4.FragmentPagerItem +import com.ogaclejapan.smarttablayout.utils.v4.FragmentPagerItemAdapter +import com.ogaclejapan.smarttablayout.utils.v4.FragmentPagerItems import kotlinx.android.synthetic.main.activity_index.* -private const val FIRST_PAGE_INDEX: Int = 0 +private const val INDEX_VIEWPAGER_WEATHER_STR = "天气" +private const val INDEX_VIEWPAGER_ANDROID_STR = "安卓" +private const val INDEX_VIEWPAGER_ZHIHU_STR = "知乎" /** * ClassName: IndexActivity @@ -19,39 +24,37 @@ private const val FIRST_PAGE_INDEX: Int = 0 */ class IndexActivity : AppCompatActivity() { - private lateinit var mViewPagerAdapter: ViewPagerAdapter - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_index) - initAdapter() initViewPager() } private fun initViewPager() { - indexViewPager.adapter = mViewPagerAdapter - indexViewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { - override fun onPageScrollStateChanged(state: Int) { - } - - override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) { - } - - override fun onPageSelected(position: Int) { - mViewPagerAdapter.switchTo(position) + val pages = FragmentPagerItems(this) + arrayOf(INDEX_VIEWPAGER_WEATHER_STR, INDEX_VIEWPAGER_ANDROID_STR, INDEX_VIEWPAGER_ZHIHU_STR) + .forEach { + when (it) { + INDEX_VIEWPAGER_WEATHER_STR -> pages.add(FragmentPagerItem.of("", WeatherFragment::class.java)) + INDEX_VIEWPAGER_ANDROID_STR -> pages.add(FragmentPagerItem.of("", WanAndroidFragment::class.java)) + INDEX_VIEWPAGER_ZHIHU_STR -> pages.add(FragmentPagerItem.of("", ZhiHuDailyFragment::class.java)) + } + } + + indexTabLayout.setCustomTabView { container, position, _ -> + val icon = LayoutInflater.from(this@IndexActivity).inflate(R.layout.custom_tab_icon1, container, false) as ImageView + val res = this@IndexActivity.resources + + when (position) { + 0 -> icon.setImageDrawable(res.getDrawable(R.mipmap.index_icon_weather)) + 1 -> icon.setImageDrawable(res.getDrawable(R.mipmap.index_icon_android)) + 2 -> icon.setImageDrawable(res.getDrawable(R.mipmap.index_icon_zhihu)) + else -> throw IllegalStateException("Invalid position: $position") } - }) + icon + } - indexTabLayout.setupWithViewPager(indexViewPager) + indexViewPager.adapter = FragmentPagerItemAdapter(supportFragmentManager, pages) + indexTabLayout.setViewPager(indexViewPager) } - - private fun initAdapter() { - //create a collection object using arrayOf - val fragmentList = arrayOf(WeatherFragment(), WanAndroidFragment(), ZhiHuDailyFragment()) - val titleList = arrayOf("天气", "WanAndroid", "知乎日报") - - mViewPagerAdapter = ViewPagerAdapter(supportFragmentManager, fragmentList, titleList) - mViewPagerAdapter.switchTo(FIRST_PAGE_INDEX) - } - } diff --git a/app/src/main/java/com/leeeyou/util/ViewPagerAdapter.kt b/app/src/main/java/com/leeeyou/util/ViewPagerAdapter.kt index 51eb061..17640f9 100644 --- a/app/src/main/java/com/leeeyou/util/ViewPagerAdapter.kt +++ b/app/src/main/java/com/leeeyou/util/ViewPagerAdapter.kt @@ -27,6 +27,6 @@ class ViewPagerAdapter(fm: FragmentManager, mCurrentFragment = mFragmentList[position] } - override fun getPageTitle(position: Int): CharSequence = titleList[position] +// override fun getPageTitle(position: Int): CharSequence = titleList[position] } \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/widget/TintableImageView.java b/app/src/main/java/com/leeeyou/widget/TintableImageView.java new file mode 100644 index 0000000..d79ed8e --- /dev/null +++ b/app/src/main/java/com/leeeyou/widget/TintableImageView.java @@ -0,0 +1,58 @@ +package com.leeeyou.widget; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.widget.ImageView; + +import com.leeeyou.R; + +/** + * https://gist.github.com/tylerchesley/5d15d859be4f3ce31213 + */ +@SuppressLint("AppCompatCustomView") +public class TintableImageView extends ImageView { + + private ColorStateList tint; + + public TintableImageView(Context context) { + super(context); + } + + public TintableImageView(Context context, AttributeSet attrs) { + super(context, attrs); + init(context, attrs, 0); + } + + public TintableImageView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(context, attrs, defStyle); + } + + private void init(Context context, AttributeSet attrs, int defStyle) { + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TintableImageView, defStyle, 0); + tint = a.getColorStateList(R.styleable.TintableImageView_tint); + a.recycle(); + } + + @Override + protected void drawableStateChanged() { + super.drawableStateChanged(); + if (tint != null && tint.isStateful()) { + updateTintColor(); + } + } + + public void setColorFilter(ColorStateList tint) { + this.tint = tint; + super.setColorFilter(tint.getColorForState(getDrawableState(), 0)); + } + + private void updateTintColor() { + int color = tint.getColorForState(getDrawableState(), 0); + setColorFilter(color); + } + +} diff --git a/app/src/main/res/color/custom_tab_icon.xml b/app/src/main/res/color/custom_tab_icon.xml new file mode 100644 index 0000000..3e73be9 --- /dev/null +++ b/app/src/main/res/color/custom_tab_icon.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_index.xml b/app/src/main/res/layout/activity_index.xml index 2419f66..03c514f 100644 --- a/app/src/main/res/layout/activity_index.xml +++ b/app/src/main/res/layout/activity_index.xml @@ -5,16 +5,20 @@ android:layout_height="match_parent" android:background="#fff" android:orientation="vertical" - android:paddingTop="25dp"> + android:paddingTop="23dp"> - + app:stl_distributeEvenly="true" + app:stl_dividerColor="@color/transparent" + app:stl_dividerThickness="0dp" + app:stl_indicatorColor="@color/transparent" + app:stl_indicatorThickness="0dp" + app:stl_underlineColor="@color/transparent" + app:stl_underlineThickness="0dp"/> + \ No newline at end of file diff --git a/app/src/main/res/mipmap-xhdpi/index_icon_android.png b/app/src/main/res/mipmap-xhdpi/index_icon_android.png new file mode 100644 index 0000000000000000000000000000000000000000..7f99f07dad11d4571186eb61b09781673129cf4a GIT binary patch literal 1077 zcmV-51j_q~P)zVp0DlkzVAHydEV#seayOf>-*Mv*81()v;mO#wvNTvKuOacZYG0J{tbby+vc1id4vKs_oHE?`pv|iF!*8qSeam)s$XTIN)bV@0Jn3{)VMw=x~wS5`z zR7WK=4~W%|6KpPPCB+2)hYZTVe-6MFNmFbuNT<&(k}#4COj-b&Bu%q@DX_SUsPNK((6UXxAyZoqy7o`mRS=j??B+V=xWNXs>b-P`#Z~Ju(K++Q1 z)eF;`lFlv#a6RxyX7qrhn>!w4b0s}*J5IaX4{w_jX|}WoKq%Y31ULeSW5r@gTSoyP z`92jm8CWXm^L}%u_(Ie1AiGe~3nfGHe+eLn+*eChsX%wOq!k7F<>apIy@6=4VXq}wWYX((gq6({l?(;fhmbr%$)}7_CY0zSv|OBI_v z&(chp6aZ?KP>{fqf?jVd!ziIWfuAZ7^eUmXz%diCgyM~$N`tJBG`mtlD}j7tZzBmB zFa5B(P-?610y**Ypro5B0G^09vFvYeNjh_)0601hT|mr-csh-DuOBM_4v1bK@5$*! v^GZo^?`|cn_dqM}LonV6UJxtfRw}7L<3?VX00000NkvXXu0mjfMn&(t literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/index_icon_weather.png b/app/src/main/res/mipmap-xhdpi/index_icon_weather.png new file mode 100644 index 0000000000000000000000000000000000000000..7952ab4b23c2bf3246dd72bd328ffca2832e3e96 GIT binary patch literal 1046 zcmV+x1nK*UP)zb#I&SESxJaeEpt)05rq~NT^2%%F1jcz!4w09 zD5;<*i=>-GrJ)dokVH4ru4+B;pWY+yH_gm9=VNrd=ZFCp4LE*A z3G~~7qZSw#3q-^W;Gm>``VBgNe^)LP5!-+}fUkh*lKyT*A|mDiGl6ZA{x};%yCv`! zFg^jAE9s+Va1pTpcr*R~lBC;8BJgaozyV-hD+@%#QsCtTdbgw-D*_R5DPTf30seg< zZ~^cu@B{EI@D{K`(&u%EcV&TY4vYv}=zd@p@R+0n5pf;x5HLTT5zw~wRM)-)9tO5b z@_!wrHi3v31Iz`^1AYg-kn~&rmK5+C09)ZCaL#Z*vg?kou|5~LSJK;^p6!}IL@WmG z1a1Zio)B)a%^AuoZt&{Y4I})b}M8xyJBAZ;&)0zKT)0=_YJ808d z^I6{jmjRtzrG_z1-?|-GCCSNTh%^X9#2nzmbmf?&hK3`;rrZrI?BKg20aW)HD`<

)GVY?pL2A}$8L1}5}b`#D~B z0ar@;topO9W+TGdUk^;IsiiY{yItuuNvGg>4wSCErO3XyASIa8` ztAIxUr=}H>PDX@_+5^C~rKvyRaXnc4zaWkX4;pTs+}M>WZWcF7x_bzLh&UJUMC6Xr zt!$~{u5^Q>_00s_)2}QvaC2okQ@XL+l&8_Wr7l(TIj&129mxsU?{6Id?VH4YNwbHv z5)tup+7y(oefL5xVjlee>xCj>3h-0u$P>O}fZeCDNT>*SS95p(2za1bBk73>Yeirj z;M7!d>hv(PADAP_twcleAb#Ilw?eI8&Hng_QPAjy^_4`t|h$!RO_X^ym^#BFSR+6vqmj260P;}nSr;!zotDiK*rpn QssI2007*qoM6N<$f=x8*4*&oF literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/index_icon_zhihu.png b/app/src/main/res/mipmap-xhdpi/index_icon_zhihu.png new file mode 100644 index 0000000000000000000000000000000000000000..53a486ef8261b3e84aae7e7231b4d0d70fe89946 GIT binary patch literal 1311 zcmV+)1>pLLP)PmjiN*tcsMZU?g9jy) z#MBs*MwA$9Oo;?VsHww}|CjyUoSyHTd-lEGxsfmFdb!CxYp=ckd(CT$F-{ue=VvD+GD+X` zxVFRI7l4SE2HXbBhEbd0R^SETZb@(T3Zy3h5wQpGAaF^q8)fo83e1!AdnSMW?M1{< zz_Y+Xxx)M8`wBQm(nmS#vosJ9$0X<5J4a{>Jij;)Ncx~jRwICjI2d@RBC0gW9_{y^ zfvJ+d=q9KufQZ;H9e(0yPt)i6Zxe_g>ekl+h=`p5M}_11+`O%2?*Y>#{Zl2d8-NFZ zYa34SHEy6ze|TYyQD)|S6lY9Jz+Cet|b|pS^{9Pvm{xoLsSN^2w2bn;0fS*;C|r3jv#4BRzy_Q_-z7k)#^&P z5`fijr|d?~j#Zi2=4YqQo420RKAa zG+h7FlFrXnQAC^uJl`UKA#K)~(64~waW`58yj@~gFKJms*nj4fzPSmS+aiG9B-vCe zqfoz2{FI~%BH}7w>41G;oup2nDVtDE7_HLIjgsz*h=+iSk~0_i+H~TsVf0Sm_FVfe z@J*4lCL%o8a-Mh>DE7~70$3!ebH=g;P6aw?Iupnzl8#Kh^KP!$)7;2%oEuDS0+=c3 z)jA)rcmI^aVdnXnBkA#oxC5{c94~2oM4Sz*Oxd|D050YxNOH6s>BRmgA|6TO!W;k} zrdHA&lZ(3pfR7W1jS1Akf(Be_T%CqvUgO*`tZ~mxP2Ku|<&s2Qc{f@hX>mmOR^25{DKS5s zhGDK=4b~HBtA4hmE$Ohg0H>GMd9qzaFG?EG=GOJZuJ>&obxr+3Nq42gF9EKp*>oLn zNa>q3^Cj?@O)bYx0h`;=lH7l6L;Z|Zt^}S;H|LRxd+1)slLc3k!x1WHZEs_hWJa!u zTry0`*xT$K7oYCT%J{~XH!t;HqWP2Yi4xb<*JiL12e;V$3nlZxei?`EM z`w#Js>G66&6Jz&*qX1&;J~0*TE+VF<@k^VJe2bmcd-eV-AE*;rcxJr<@MB0XiL<~WBR^mQ~(O5HT=-+a{MH~zjY7YE-73Nug#gQHlb<-K+`6J{JtH)Aa6HE_J2Yu V_&@=Jds+Yh002ovPDHLkV1l~0YGVKZ literal 0 HcmV?d00001 diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml new file mode 100644 index 0000000..a86f3e3 --- /dev/null +++ b/app/src/main/res/values/attrs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index a3130e7..014fb77 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -16,9 +16,9 @@ #00000000 #FFFFFFFF - #4DFFFFFF + #626262 - #FFFFFFFF + #DC4037 #FF63727B #FF000000 From 0036110d40d100afaa8e1331507faf55c8927f27 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Sat, 29 Dec 2018 18:08:34 +0800 Subject: [PATCH 048/150] Adjust the background color of the Fragment --- .../java/com/leeeyou/util/ViewPagerAdapter.kt | 32 ------------------- .../leeeyou/wanandroid/WanAndroidFragment.kt | 14 ++++++-- .../main/res/layout/fragment_wan_android.xml | 6 ++-- .../layout/fragment_wan_android_project.xml | 3 +- .../layout/fragment_wan_android_system.xml | 3 +- app/src/main/res/layout/fragment_weather.xml | 3 +- 6 files changed, 18 insertions(+), 43 deletions(-) delete mode 100644 app/src/main/java/com/leeeyou/util/ViewPagerAdapter.kt diff --git a/app/src/main/java/com/leeeyou/util/ViewPagerAdapter.kt b/app/src/main/java/com/leeeyou/util/ViewPagerAdapter.kt deleted file mode 100644 index 17640f9..0000000 --- a/app/src/main/java/com/leeeyou/util/ViewPagerAdapter.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.leeeyou.util - -import android.support.v4.app.Fragment -import android.support.v4.app.FragmentManager -import android.support.v4.app.FragmentStatePagerAdapter -import com.leeeyou.manager.BaseFragment - -/** - * ClassName: ViewPagerAdapter - * Description: main activity adapter - * - * Author: leeeyou - * Date: 2018/2/24 15:05 - */ -class ViewPagerAdapter(fm: FragmentManager, - private val mFragmentList: Array, - private val titleList: Array) - : FragmentStatePagerAdapter(fm) { - - private var mCurrentFragment: BaseFragment? = null - - override fun getItem(position: Int): Fragment = mFragmentList[position] - - override fun getCount(): Int = mFragmentList.size - - fun switchTo(position: Int) { - mCurrentFragment = mFragmentList[position] - } - -// override fun getPageTitle(position: Int): CharSequence = titleList[position] - -} \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidFragment.kt index 21a8b7e..c90d3cb 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidFragment.kt @@ -1,12 +1,14 @@ package com.leeeyou.wanandroid import android.os.Bundle +import android.support.v4.app.Fragment +import android.support.v4.app.FragmentManager +import android.support.v4.app.FragmentStatePagerAdapter import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import com.leeeyou.R import com.leeeyou.manager.BaseFragment -import com.leeeyou.util.ViewPagerAdapter import com.leeeyou.util.inflate import kotlinx.android.synthetic.main.fragment_wan_android.* @@ -32,9 +34,17 @@ class WanAndroidFragment : BaseFragment() { val titleList = arrayOf("推荐", "体系", "项目") mViewPagerAdapter = ViewPagerAdapter(activity!!.supportFragmentManager, fragmentList, titleList) - wanAndroidViewPager.adapter = mViewPagerAdapter + wanAndroidViewPager.adapter = mViewPagerAdapter wanAndroidTabLayout.setupWithViewPager(wanAndroidViewPager) } + private class ViewPagerAdapter(fm: FragmentManager, private val mFragmentList: Array, private val titleList: Array) + : FragmentStatePagerAdapter(fm) { + override fun getItem(position: Int): Fragment = mFragmentList[position] + + override fun getCount(): Int = mFragmentList.size + + override fun getPageTitle(position: Int): CharSequence = titleList[position] + } } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_wan_android.xml b/app/src/main/res/layout/fragment_wan_android.xml index eadbc05..76613c0 100644 --- a/app/src/main/res/layout/fragment_wan_android.xml +++ b/app/src/main/res/layout/fragment_wan_android.xml @@ -9,12 +9,12 @@ + app:tabTextColor="@color/icon_disabled"/> + android:layout_height="match_parent"> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_wan_android_system.xml b/app/src/main/res/layout/fragment_wan_android_system.xml index 4fa09c6..e45aee9 100644 --- a/app/src/main/res/layout/fragment_wan_android_system.xml +++ b/app/src/main/res/layout/fragment_wan_android_system.xml @@ -1,8 +1,7 @@ + android:layout_height="match_parent"> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_weather.xml b/app/src/main/res/layout/fragment_weather.xml index 5918f1c..e45aee9 100644 --- a/app/src/main/res/layout/fragment_weather.xml +++ b/app/src/main/res/layout/fragment_weather.xml @@ -1,8 +1,7 @@ + android:layout_height="match_parent"> \ No newline at end of file From 992abff4f9d506c0d0fa27276a605cc932d25b02 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Sat, 29 Dec 2018 18:12:25 +0800 Subject: [PATCH 049/150] Adjust the background color of the Fragment --- .../leeeyou/wanandroid/WanAndroidRecommendFragment.kt | 10 ++++------ .../main/res/layout/fragment_wan_android_recommend.xml | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt index 8c1f5ec..db2c9d7 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt @@ -75,12 +75,10 @@ class WanAndroidRecommendFragment : BaseFragment() { override fun displayImage(context: Context?, path: Any?, imageView: ImageView?) { context?.let { imageView?.let { - Glide.with(context) - .load(path) - .apply(RequestOptions() - .override(banner.width, banner.height) - .fitCenter() - .transforms(CenterCrop(), RoundedCorners(30))) + Glide.with(context).load(path).apply(RequestOptions() + .override(banner.width, banner.height) + .fitCenter() + .transforms(CenterCrop(), RoundedCorners(35))) .into(imageView) } } diff --git a/app/src/main/res/layout/fragment_wan_android_recommend.xml b/app/src/main/res/layout/fragment_wan_android_recommend.xml index 50677b5..70ebe4d 100644 --- a/app/src/main/res/layout/fragment_wan_android_recommend.xml +++ b/app/src/main/res/layout/fragment_wan_android_recommend.xml @@ -6,9 +6,9 @@ + android:paddingTop="10dp"/> \ No newline at end of file From 5b81d2fe7026adc3f257e641ad1486dfc9e82143 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Sat, 29 Dec 2018 18:20:54 +0800 Subject: [PATCH 050/150] Change TabLayout indicator color and height --- app/src/main/java/com/leeeyou/IndexActivity.kt | 2 ++ app/src/main/res/layout/fragment_wan_android.xml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/app/src/main/java/com/leeeyou/IndexActivity.kt b/app/src/main/java/com/leeeyou/IndexActivity.kt index 7d726d2..2e4a5fc 100644 --- a/app/src/main/java/com/leeeyou/IndexActivity.kt +++ b/app/src/main/java/com/leeeyou/IndexActivity.kt @@ -3,6 +3,7 @@ package com.leeeyou import android.os.Bundle import android.support.v7.app.AppCompatActivity import android.view.LayoutInflater +import android.view.Window import android.widget.ImageView import com.leeeyou.wanandroid.WanAndroidFragment import com.leeeyou.weather.WeatherFragment @@ -26,6 +27,7 @@ class IndexActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + requestWindowFeature(Window.FEATURE_NO_TITLE) setContentView(R.layout.activity_index) initViewPager() } diff --git a/app/src/main/res/layout/fragment_wan_android.xml b/app/src/main/res/layout/fragment_wan_android.xml index 76613c0..7911c86 100644 --- a/app/src/main/res/layout/fragment_wan_android.xml +++ b/app/src/main/res/layout/fragment_wan_android.xml @@ -11,6 +11,8 @@ android:layout_width="match_parent" android:layout_height="35dp" android:layout_gravity="center_horizontal" + app:tabIndicatorColor="@color/icon_enabled" + app:tabIndicatorHeight="1dp" app:tabMode="fixed" app:tabSelectedTextColor="@color/icon_enabled" app:tabTextAppearance="@android:style/TextAppearance.Widget.TabWidget" From 5576189011f228d09d1fcb7288d3b6b6be253a90 Mon Sep 17 00:00:00 2001 From: leeeyou Date: Mon, 31 Dec 2018 22:26:22 +0800 Subject: [PATCH 051/150] fetch RecommendList data from server --- .../wanandroid/WanAndroidRecommendFragment.kt | 33 ++++++++++++++++++- .../wanandroid/model/WanAndroidRepository.kt | 7 ++++ .../wanandroid/model/bean/RecommendItem.kt | 24 ++++++++++++++ .../wanandroid/model/bean/RecommendList.kt | 9 +++++ .../model/bean/ResponseRecommendList.kt | 5 +++ .../com/leeeyou/wanandroid/model/bean/Tag.kt | 9 +++++ .../wanandroid/service/WanAndroidService.kt | 5 +++ 7 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendItem.kt create mode 100644 app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendList.kt create mode 100644 app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseRecommendList.kt create mode 100644 app/src/main/java/com/leeeyou/wanandroid/model/bean/Tag.kt diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt index db2c9d7..2b72266 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt @@ -15,8 +15,10 @@ import com.leeeyou.manager.BaseFragment import com.leeeyou.util.inflate import com.leeeyou.util.startBrowserActivity import com.leeeyou.wanandroid.model.bean.Banner +import com.leeeyou.wanandroid.model.bean.RecommendList import com.leeeyou.wanandroid.model.bean.ResponseBanner import com.leeeyou.wanandroid.model.fetchBannerList +import com.leeeyou.wanandroid.model.fetchRecommendList import com.youth.banner.Transformer import com.youth.banner.loader.ImageLoader import kotlinx.android.synthetic.main.fragment_wan_android_recommend.* @@ -42,6 +44,35 @@ class WanAndroidRecommendFragment : BaseFragment() { super.onViewCreated(view, savedInstanceState) initBanner() fetchBannerListFromServer() + fetchRecommendListFromServer() + } + + private fun fetchRecommendListFromServer() { + fetchRecommendList(0) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext { + Timber.d("fetchRecommendListFromServer doOnNext") + + it.takeIf { + it.errorCode >= 0 + }?.also { + Timber.d(it.data.toString()) + renderRecommendList(it.data) + } ?: IllegalArgumentException("fetchRecommendListFromServer接口返回异常") + } + .doOnError { + Timber.d("fetchRecommendListFromServer doOnError") + println(it) + } + .doOnCompleted { + Timber.d("fetchRecommendListFromServer doOnCompleted") + } + .subscribe() + } + + private fun renderRecommendList(data: RecommendList) { + } private fun fetchBannerListFromServer() { @@ -51,7 +82,7 @@ class WanAndroidRecommendFragment : BaseFragment() { .subscribe(object : Subscriber() { override fun onNext(responseBanner: ResponseBanner) { Timber.d("fetchBannerList onNext") - println(responseBanner) + Timber.d(responseBanner.toString()) responseBanner.takeIf { it.errorCode >= 0 diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt b/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt index 0c33419..d07244d 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt @@ -2,6 +2,7 @@ package com.leeeyou.wanandroid.model import com.leeeyou.factory.ServiceFactory import com.leeeyou.wanandroid.model.bean.ResponseBanner +import com.leeeyou.wanandroid.model.bean.ResponseRecommendList import com.leeeyou.wanandroid.service.WanAndroidService import rx.Observable @@ -11,4 +12,10 @@ fun fetchBannerList(): Observable { return ServiceFactory .createRxRetrofitService(WanAndroidService::class.java, endPoint) .getBannerList() +} + +fun fetchRecommendList(index: Int = 0): Observable { + return ServiceFactory + .createRxRetrofitService(WanAndroidService::class.java, endPoint) + .getRecommendList(index) } \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendItem.kt b/app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendItem.kt new file mode 100644 index 0000000..4aa985f --- /dev/null +++ b/app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendItem.kt @@ -0,0 +1,24 @@ +package com.leeeyou.wanandroid.model.bean + +data class RecommendItem(val apkLink: String, + val author: String, + val chapterId: Int, + val chapterName: String, + val collect: Boolean = false, + val desc: String, + val envelopePic: String, + val fresh: Boolean = false, + val id: Int, + val link: String, + val nickDate: String, + val origin: String, + val projectLink: String, + val publishTime: Long, + val superChapterId: Int, + val superChapterName: String, + val tags: List, + val title: String, + val type: Int = 0, + val userId: Int = -1, + val visible: Int = 1, + val zan: Long = 0) \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendList.kt b/app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendList.kt new file mode 100644 index 0000000..4636ec6 --- /dev/null +++ b/app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendList.kt @@ -0,0 +1,9 @@ +package com.leeeyou.wanandroid.model.bean + +data class RecommendList(val curPage: Int, + val datas: List, + val offset: Int, + val over: Boolean, + val pageCount: Int, + val size: Int, + val total: Int) \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseRecommendList.kt b/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseRecommendList.kt new file mode 100644 index 0000000..fbda5b1 --- /dev/null +++ b/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseRecommendList.kt @@ -0,0 +1,5 @@ +package com.leeeyou.wanandroid.model.bean + +data class ResponseRecommendList(val data: RecommendList, + val errorCode: Int = 0, + var errorMsg: String = "") \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/bean/Tag.kt b/app/src/main/java/com/leeeyou/wanandroid/model/bean/Tag.kt new file mode 100644 index 0000000..80625b4 --- /dev/null +++ b/app/src/main/java/com/leeeyou/wanandroid/model/bean/Tag.kt @@ -0,0 +1,9 @@ +package com.leeeyou.wanandroid.model.bean + +//{ +// "name": "公众号", +// "url": "/wxarticle/list/408/1" +//} + +data class Tag(val name: String, + val url: String) \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt b/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt index 22133c1..cfc2683 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt @@ -1,7 +1,9 @@ package com.leeeyou.wanandroid.service import com.leeeyou.wanandroid.model.bean.ResponseBanner +import com.leeeyou.wanandroid.model.bean.ResponseRecommendList import retrofit.http.GET +import retrofit.http.Path import rx.Observable interface WanAndroidService { @@ -9,4 +11,7 @@ interface WanAndroidService { @GET("banner/json") fun getBannerList(): Observable + @GET("article/list/{index}/json") + fun getRecommendList(@Path("index") index: Int): Observable + } \ No newline at end of file From b0996b0299c2e53c77feb3d730f0e3db306edb76 Mon Sep 17 00:00:00 2001 From: leeeyou Date: Tue, 1 Jan 2019 22:23:45 +0800 Subject: [PATCH 052/150] render RecommendList data to UI --- .../wanandroid/WanAndroidRecommendFragment.kt | 14 ++++- .../wanandroid/model/bean/RecommendItem.kt | 2 +- .../layout/fragment_wan_android_recommend.xml | 14 +++-- app/src/main/res/layout/item_recommend.xml | 51 +++++++++++++++++++ 4 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 app/src/main/res/layout/item_recommend.xml diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt index 2b72266..584a944 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt @@ -2,6 +2,7 @@ package com.leeeyou.wanandroid import android.content.Context import android.os.Bundle +import android.support.v7.widget.LinearLayoutManager import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -10,11 +11,14 @@ import com.bumptech.glide.Glide import com.bumptech.glide.load.resource.bitmap.CenterCrop import com.bumptech.glide.load.resource.bitmap.RoundedCorners import com.bumptech.glide.request.RequestOptions +import com.chad.library.adapter.base.BaseQuickAdapter +import com.chad.library.adapter.base.BaseViewHolder import com.leeeyou.R import com.leeeyou.manager.BaseFragment import com.leeeyou.util.inflate import com.leeeyou.util.startBrowserActivity import com.leeeyou.wanandroid.model.bean.Banner +import com.leeeyou.wanandroid.model.bean.RecommendItem import com.leeeyou.wanandroid.model.bean.RecommendList import com.leeeyou.wanandroid.model.bean.ResponseBanner import com.leeeyou.wanandroid.model.fetchBannerList @@ -72,7 +76,15 @@ class WanAndroidRecommendFragment : BaseFragment() { } private fun renderRecommendList(data: RecommendList) { - + recyclerViewRecommend.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) + recyclerViewRecommend.adapter = object : BaseQuickAdapter(R.layout.item_recommend, data.datas) { + override fun convert(helper: BaseViewHolder?, item: RecommendItem?) { + helper?.setText(R.id.tv_title, item?.title) + helper?.setText(R.id.tv_author, item?.author) + helper?.setText(R.id.tv_category, item?.superChapterName + " " + item?.chapterName) + helper?.setText(R.id.tv_niceDate, item?.niceDate) + } + } } private fun fetchBannerListFromServer() { diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendItem.kt b/app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendItem.kt index 4aa985f..c739fb8 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendItem.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendItem.kt @@ -10,7 +10,7 @@ data class RecommendItem(val apkLink: String, val fresh: Boolean = false, val id: Int, val link: String, - val nickDate: String, + val niceDate: String, val origin: String, val projectLink: String, val publishTime: Long, diff --git a/app/src/main/res/layout/fragment_wan_android_recommend.xml b/app/src/main/res/layout/fragment_wan_android_recommend.xml index 70ebe4d..708c9ba 100644 --- a/app/src/main/res/layout/fragment_wan_android_recommend.xml +++ b/app/src/main/res/layout/fragment_wan_android_recommend.xml @@ -1,7 +1,7 @@ + android:id="@+id/ptrFrame" + android:layout_width="match_parent" + android:layout_height="match_parent"> + android:paddingTop="10dp" /> + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_recommend.xml b/app/src/main/res/layout/item_recommend.xml new file mode 100644 index 0000000..ff40c3b --- /dev/null +++ b/app/src/main/res/layout/item_recommend.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + From 0b7626522311801f62ed08ea8ed1ddeec42a2db7 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Wed, 2 Jan 2019 17:08:05 +0800 Subject: [PATCH 053/150] render RecommendList data to UI --- .../wanandroid/WanAndroidRecommendFragment.kt | 144 ++++++++++++------ app/src/main/res/drawable/selector_item.xml | 4 +- .../main/res/layout/fragment_wan_android.xml | 13 +- .../layout/fragment_wan_android_recommend.xml | 38 +++-- app/src/main/res/layout/item_recommend.xml | 79 +++++++--- app/src/main/res/values/colors.xml | 12 +- 6 files changed, 195 insertions(+), 95 deletions(-) diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt index 584a944..6c6f00d 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt @@ -1,5 +1,7 @@ package com.leeeyou.wanandroid +import `in`.srain.cube.views.ptr.PtrFrameLayout +import `in`.srain.cube.views.ptr.PtrHandler import android.content.Context import android.os.Bundle import android.support.v7.widget.LinearLayoutManager @@ -8,9 +10,6 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView import com.bumptech.glide.Glide -import com.bumptech.glide.load.resource.bitmap.CenterCrop -import com.bumptech.glide.load.resource.bitmap.RoundedCorners -import com.bumptech.glide.request.RequestOptions import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.BaseViewHolder import com.leeeyou.R @@ -40,50 +39,123 @@ import timber.log.Timber * Date: 2017/4/24 13:46 */ class WanAndroidRecommendFragment : BaseFragment() { + lateinit var mLinearLayoutManager: LinearLayoutManager + var mPageIndex: Int = 0 + private lateinit var mRecommendAdapter: BaseQuickAdapter + private var mPageCount: Int = 0 + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return container?.inflate(R.layout.fragment_wan_android_recommend) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - initBanner() + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + initView() fetchBannerListFromServer() - fetchRecommendListFromServer() + fetchRecommendListFromServer(mPageIndex) + } + + private fun initView() { + initBanner() + initPtrFrame() + initRecyclerView() + } + + private fun initRecyclerView() { + mLinearLayoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) + mRecommendAdapter = object : BaseQuickAdapter(R.layout.item_recommend, null) { + override fun convert(helper: BaseViewHolder?, item: RecommendItem?) { + item?.takeIf { it.visible == 1 }?.also { + helper?.setText(R.id.tv_title, it.title) + ?.setText(R.id.tv_author, "作者:" + it.author) + ?.setText(R.id.tv_category, "分类:" + it.superChapterName + " / " + it.chapterName) + ?.setText(R.id.tv_niceDate, it.niceDate) + ?.setGone(R.id.tv_refresh, it.fresh) + } + } + } + mRecommendAdapter.setOnLoadMoreListener({ + if (mPageIndex + 1 == mPageCount) { + mRecommendAdapter.loadMoreEnd() + } else { + fetchRecommendListFromServer(++mPageIndex) + } + }, recyclerViewRecommend) + mRecommendAdapter.setOnItemClickListener { adapter, _, position -> + val item: RecommendItem = adapter.getItem(position) as RecommendItem + startBrowserActivity(context!!, item.link, item.title) + } + mRecommendAdapter.openLoadAnimation(BaseQuickAdapter.SCALEIN) + + recyclerViewRecommend.layoutManager = mLinearLayoutManager + recyclerViewRecommend.adapter = mRecommendAdapter + } + + private fun initBanner() { + banner.setImageLoader(object : ImageLoader() { + override fun displayImage(context: Context?, path: Any?, imageView: ImageView?) { + context?.let { + imageView?.let { + Glide.with(context).load(path).into(imageView) + } + } + } + }) + banner.setDelayTime(3000) } - private fun fetchRecommendListFromServer() { - fetchRecommendList(0) + private fun initPtrFrame() { + ptrFrameRecommend.disableWhenHorizontalMove(true) + ptrFrameRecommend.setPtrHandler(object : PtrHandler { + override fun onRefreshBegin(frame: PtrFrameLayout?) { + fetchBannerListFromServer() + + mPageIndex = 0 + fetchRecommendListFromServer(mPageIndex) + } + + override fun checkCanDoRefresh(frame: PtrFrameLayout?, content: View?, header: View?): Boolean { + return mLinearLayoutManager.findFirstCompletelyVisibleItemPosition() <= 0 + } + }) + } + + private fun fetchRecommendListFromServer(pageIndex: Int) { + fetchRecommendList(pageIndex) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .doOnNext { Timber.d("fetchRecommendListFromServer doOnNext") - it.takeIf { - it.errorCode >= 0 - }?.also { - Timber.d(it.data.toString()) - renderRecommendList(it.data) + ptrFrameRecommend.refreshComplete() + + it.takeIf { response -> + response.errorCode >= 0 + }?.also { response -> + Timber.d(response.data.toString()) + renderRecommendList(pageIndex, response.data) } ?: IllegalArgumentException("fetchRecommendListFromServer接口返回异常") } .doOnError { - Timber.d("fetchRecommendListFromServer doOnError") - println(it) + ptrFrameRecommend.refreshComplete() + Timber.e(it, "fetchRecommendListFromServer doOnError") } .doOnCompleted { Timber.d("fetchRecommendListFromServer doOnCompleted") + if (mPageIndex > 0) { + mRecommendAdapter.loadMoreComplete() + } + } .subscribe() } - private fun renderRecommendList(data: RecommendList) { - recyclerViewRecommend.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) - recyclerViewRecommend.adapter = object : BaseQuickAdapter(R.layout.item_recommend, data.datas) { - override fun convert(helper: BaseViewHolder?, item: RecommendItem?) { - helper?.setText(R.id.tv_title, item?.title) - helper?.setText(R.id.tv_author, item?.author) - helper?.setText(R.id.tv_category, item?.superChapterName + " " + item?.chapterName) - helper?.setText(R.id.tv_niceDate, item?.niceDate) - } + private fun renderRecommendList(witchPage: Int, data: RecommendList) { + if (witchPage == 0) { + mRecommendAdapter.setNewData(data.datas) + } else { + mPageCount = data.pageCount + mRecommendAdapter.addData(data.datas) } } @@ -93,8 +165,7 @@ class WanAndroidRecommendFragment : BaseFragment() { .observeOn(AndroidSchedulers.mainThread()) .subscribe(object : Subscriber() { override fun onNext(responseBanner: ResponseBanner) { - Timber.d("fetchBannerList onNext") - Timber.d(responseBanner.toString()) + Timber.d("fetchBannerList onNext , result is %s ", responseBanner.toString()) responseBanner.takeIf { it.errorCode >= 0 @@ -108,28 +179,11 @@ class WanAndroidRecommendFragment : BaseFragment() { } override fun onError(e: Throwable?) { - Timber.d("fetchBannerList onError") + Timber.d(e, "fetchBannerList onError") } }) } - private fun initBanner() { - banner.setImageLoader(object : ImageLoader() { - override fun displayImage(context: Context?, path: Any?, imageView: ImageView?) { - context?.let { - imageView?.let { - Glide.with(context).load(path).apply(RequestOptions() - .override(banner.width, banner.height) - .fitCenter() - .transforms(CenterCrop(), RoundedCorners(35))) - .into(imageView) - } - } - } - }) - banner.setDelayTime(3000) - } - private fun renderBanner(bannerList: List) { bannerList.map { it.imagePath }.run { banner.setImages(this) diff --git a/app/src/main/res/drawable/selector_item.xml b/app/src/main/res/drawable/selector_item.xml index 64b3d79..b5e4d0c 100755 --- a/app/src/main/res/drawable/selector_item.xml +++ b/app/src/main/res/drawable/selector_item.xml @@ -1,7 +1,7 @@ - - + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_wan_android.xml b/app/src/main/res/layout/fragment_wan_android.xml index 7911c86..a3adc7e 100644 --- a/app/src/main/res/layout/fragment_wan_android.xml +++ b/app/src/main/res/layout/fragment_wan_android.xml @@ -18,17 +18,10 @@ app:tabTextAppearance="@android:style/TextAppearance.Widget.TabWidget" app:tabTextColor="@color/icon_disabled"/> - - - - + android:layout_height="match_parent"/> diff --git a/app/src/main/res/layout/fragment_wan_android_recommend.xml b/app/src/main/res/layout/fragment_wan_android_recommend.xml index 708c9ba..f89f28e 100644 --- a/app/src/main/res/layout/fragment_wan_android_recommend.xml +++ b/app/src/main/res/layout/fragment_wan_android_recommend.xml @@ -1,20 +1,28 @@ - + + android:layout_height="match_parent" + cube_ptr:ptr_pull_to_fresh="true"> - - - + android:orientation="vertical"> + + - \ No newline at end of file + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_recommend.xml b/app/src/main/res/layout/item_recommend.xml index ff40c3b..1f5c895 100644 --- a/app/src/main/res/layout/item_recommend.xml +++ b/app/src/main/res/layout/item_recommend.xml @@ -1,51 +1,90 @@ + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/rl_recommend_item" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="@drawable/selector_item"> + android:textSize="16sp" + tools:text="Android 开发高手课 文章更新学习笔记Android 开发高手课 文章更新学习笔记Android 开发高手课 文章更新学习笔记"/> + + android:text="置顶" + android:textColor="@color/default_red" + android:textSize="12sp" + android:visibility="gone"/> + android:layout_marginTop="10dp" + android:layout_toRightOf="@id/tv_topping" + android:text="新" + android:textColor="@color/default_red" + android:textSize="12sp" + android:visibility="gone"/> + + + android:textSize="12sp"/> + + + + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 014fb77..addf3be 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -18,9 +18,6 @@ #FFFFFFFF #626262 - #DC4037 - #FF63727B - #FF000000 #4D000000 @@ -38,4 +35,13 @@ @color/light_green_500 + @color/default_red + #FF63727B + + #f0f0f0 + @color/default_white + + #DC4037 + #ffffff + From 64aa319530b0c4e8e780d4d8b50c26124272ac4b Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Wed, 2 Jan 2019 17:12:21 +0800 Subject: [PATCH 054/150] Change ZhiHuDaily Item UI style --- app/src/main/res/layout/item_zhihu_daily.xml | 21 +++++++++++--------- app/src/main/res/values/colors.xml | 1 + 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/app/src/main/res/layout/item_zhihu_daily.xml b/app/src/main/res/layout/item_zhihu_daily.xml index ae2f82e..520f216 100644 --- a/app/src/main/res/layout/item_zhihu_daily.xml +++ b/app/src/main/res/layout/item_zhihu_daily.xml @@ -1,16 +1,16 @@ + android:id="@+id/rl_item_recommend" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="@drawable/selector_item"> + android:scaleType="centerCrop"/> + android:textSize="15sp"/> + android:textSize="12sp"/> + android:layout_marginLeft="10dp" + android:layout_marginRight="10dp" + android:layout_marginTop="10dp" + android:background="@color/default_item_divider"/> diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index addf3be..f53b0a9 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -43,5 +43,6 @@ #DC4037 #ffffff + #c5c5c5 From 7cbb6fb1a4e9531620a61517ce299c726f1926d0 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Wed, 2 Jan 2019 18:10:12 +0800 Subject: [PATCH 055/150] Handling Tablayout's double-click event --- .../leeeyou/wanandroid/WanAndroidFragment.kt | 38 +++++++++++++++---- .../wanandroid/WanAndroidRecommendFragment.kt | 23 +++++++---- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidFragment.kt index c90d3cb..8436f40 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidFragment.kt @@ -1,6 +1,7 @@ package com.leeeyou.wanandroid import android.os.Bundle +import android.support.design.widget.TabLayout import android.support.v4.app.Fragment import android.support.v4.app.FragmentManager import android.support.v4.app.FragmentStatePagerAdapter @@ -11,6 +12,8 @@ import com.leeeyou.R import com.leeeyou.manager.BaseFragment import com.leeeyou.util.inflate import kotlinx.android.synthetic.main.fragment_wan_android.* +import timber.log.Timber + /** * ClassName: WanAndroidFragment @@ -19,6 +22,8 @@ import kotlinx.android.synthetic.main.fragment_wan_android.* * Author: leeeyou * Date: 2017/4/24 13:46 */ +private const val DOUBLE_CLICK_TIME = 500 //ms + class WanAndroidFragment : BaseFragment() { private lateinit var mViewPagerAdapter: ViewPagerAdapter @@ -29,22 +34,39 @@ class WanAndroidFragment : BaseFragment() { override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) - //create a collection object using arrayOf - val fragmentList = arrayOf(WanAndroidRecommendFragment(), WanAndroidSystemFragment(), WanAndroidProjectFragment()) + val wanAndroidRecommendFragment = WanAndroidRecommendFragment() + val fragmentList = arrayOf(wanAndroidRecommendFragment, WanAndroidSystemFragment(), WanAndroidProjectFragment()) val titleList = arrayOf("推荐", "体系", "项目") mViewPagerAdapter = ViewPagerAdapter(activity!!.supportFragmentManager, fragmentList, titleList) wanAndroidViewPager.adapter = mViewPagerAdapter wanAndroidTabLayout.setupWithViewPager(wanAndroidViewPager) + wanAndroidTabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { + var lastPressTime: Long = 0 + override fun onTabReselected(p0: TabLayout.Tab?) { + if (System.currentTimeMillis() - lastPressTime < DOUBLE_CLICK_TIME) { + Timber.d("Invalid double click event , click position is %s", p0?.position.toString()) + } else { + wanAndroidRecommendFragment.gotoFirstPage() + } + lastPressTime = System.currentTimeMillis() + } + + override fun onTabUnselected(p0: TabLayout.Tab?) { + } + + override fun onTabSelected(p0: TabLayout.Tab?) { + } + }) } +} - private class ViewPagerAdapter(fm: FragmentManager, private val mFragmentList: Array, private val titleList: Array) - : FragmentStatePagerAdapter(fm) { - override fun getItem(position: Int): Fragment = mFragmentList[position] +private class ViewPagerAdapter(fm: FragmentManager, private val mFragmentList: Array, private val titleList: Array) + : FragmentStatePagerAdapter(fm) { + override fun getItem(position: Int): Fragment = mFragmentList[position] - override fun getCount(): Int = mFragmentList.size + override fun getCount(): Int = mFragmentList.size - override fun getPageTitle(position: Int): CharSequence = titleList[position] - } + override fun getPageTitle(position: Int): CharSequence = titleList[position] } \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt index 6c6f00d..a84a53e 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt @@ -108,18 +108,26 @@ class WanAndroidRecommendFragment : BaseFragment() { ptrFrameRecommend.disableWhenHorizontalMove(true) ptrFrameRecommend.setPtrHandler(object : PtrHandler { override fun onRefreshBegin(frame: PtrFrameLayout?) { - fetchBannerListFromServer() - - mPageIndex = 0 - fetchRecommendListFromServer(mPageIndex) + pullDownToRefresh() } - override fun checkCanDoRefresh(frame: PtrFrameLayout?, content: View?, header: View?): Boolean { - return mLinearLayoutManager.findFirstCompletelyVisibleItemPosition() <= 0 - } + override fun checkCanDoRefresh(frame: PtrFrameLayout?, content: View?, header: View?): Boolean = recyclerViewFirstItemCanVisible() }) } + private fun recyclerViewFirstItemCanVisible() = + mLinearLayoutManager.findFirstCompletelyVisibleItemPosition() <= 0 + + fun gotoFirstPage() { + if (!recyclerViewFirstItemCanVisible()) pullDownToRefresh() + } + + private fun pullDownToRefresh() { + fetchBannerListFromServer() + mPageIndex = 0 + fetchRecommendListFromServer(mPageIndex) + } + private fun fetchRecommendListFromServer(pageIndex: Int) { fetchRecommendList(pageIndex) .subscribeOn(Schedulers.newThread()) @@ -145,7 +153,6 @@ class WanAndroidRecommendFragment : BaseFragment() { if (mPageIndex > 0) { mRecommendAdapter.loadMoreComplete() } - } .subscribe() } From ccca4b71893df50cce515dba58ffb13cd4c9083f Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Thu, 3 Jan 2019 18:49:36 +0800 Subject: [PATCH 056/150] fetch RecommendSystem data --- app/build.gradle | 1 + .../wanandroid/WanAndroidSystemFragment.kt | 40 ++++++++++++++++++- .../wanandroid/model/WanAndroidRepository.kt | 9 ++++- .../wanandroid/model/bean/RecommendItem.kt | 2 +- .../model/bean/{Tag.kt => RecommendTag.kt} | 4 +- .../model/bean/ResponseSystemTag.kt | 5 +++ .../wanandroid/model/bean/SystemTag.kt | 10 +++++ .../wanandroid/service/WanAndroidService.kt | 3 ++ app/src/main/res/color/text_color.xml | 7 ++++ app/src/main/res/drawable/checked_bg.xml | 14 +++++++ app/src/main/res/drawable/normal_bg.xml | 10 +++++ app/src/main/res/drawable/tag_bg.xml | 11 +++++ .../layout/fragment_wan_android_system.xml | 7 ++++ app/src/main/res/layout/item_system_tag.xml | 10 +++++ 14 files changed, 128 insertions(+), 5 deletions(-) rename app/src/main/java/com/leeeyou/wanandroid/model/bean/{Tag.kt => RecommendTag.kt} (58%) create mode 100644 app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseSystemTag.kt create mode 100644 app/src/main/java/com/leeeyou/wanandroid/model/bean/SystemTag.kt create mode 100644 app/src/main/res/color/text_color.xml create mode 100644 app/src/main/res/drawable/checked_bg.xml create mode 100644 app/src/main/res/drawable/normal_bg.xml create mode 100644 app/src/main/res/drawable/tag_bg.xml create mode 100644 app/src/main/res/layout/item_system_tag.xml diff --git a/app/build.gradle b/app/build.gradle index 0fb9ca7..af7a3d4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -88,6 +88,7 @@ dependencies { implementation 'com.youth.banner:banner:1.4.10' implementation 'com.jakewharton.timber:timber:4.7.1' implementation 'com.tencent.sonic:sdk:3.1.0' + implementation 'com.hyman:flowlayout-lib:1.1.2' //smarttablayout implementation 'com.ogaclejapan.smarttablayout:library:1.6.1@aar' diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt index 76c8b9e..f560410 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt @@ -4,9 +4,18 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.TextView import com.leeeyou.R import com.leeeyou.manager.BaseFragment import com.leeeyou.util.inflate +import com.leeeyou.wanandroid.model.bean.SystemTag +import com.leeeyou.wanandroid.model.fetchSystemTagList +import com.zhy.view.flowlayout.FlowLayout +import com.zhy.view.flowlayout.TagAdapter +import kotlinx.android.synthetic.main.fragment_wan_android_system.* +import rx.android.schedulers.AndroidSchedulers +import rx.schedulers.Schedulers +import timber.log.Timber /** * ClassName: WeatherFragment @@ -20,4 +29,33 @@ class WanAndroidSystemFragment : BaseFragment() { return container?.inflate(R.layout.fragment_wan_android_system) } -} \ No newline at end of file + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + fetchSystemTagList() + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext { + Timber.d("fetchSystemTagList doOnNext") + + it.takeIf { response -> + response.errorCode >= 0 + }?.also { response -> + Timber.d(response.data.toString()) + + + systemFlowLayout.adapter = object : TagAdapter(response.data) { + override fun getView(parent: FlowLayout?, position: Int, t: SystemTag?): View { + t?.let { + val textView = LayoutInflater.from(context).inflate(R.layout.item_system_tag, null) as TextView + textView.text = t.name + return textView + } + } + } + + } ?: IllegalArgumentException("fetchSystemTagList接口返回异常") + }.subscribe() + + + } +} diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt b/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt index d07244d..8fd7331 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt @@ -3,6 +3,7 @@ package com.leeeyou.wanandroid.model import com.leeeyou.factory.ServiceFactory import com.leeeyou.wanandroid.model.bean.ResponseBanner import com.leeeyou.wanandroid.model.bean.ResponseRecommendList +import com.leeeyou.wanandroid.model.bean.ResponseSystemTag import com.leeeyou.wanandroid.service.WanAndroidService import rx.Observable @@ -18,4 +19,10 @@ fun fetchRecommendList(index: Int = 0): Observable { return ServiceFactory .createRxRetrofitService(WanAndroidService::class.java, endPoint) .getRecommendList(index) -} \ No newline at end of file +} + +fun fetchSystemTagList(): Observable { + return ServiceFactory + .createRxRetrofitService(WanAndroidService::class.java, endPoint) + .getSystemTagList() +} diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendItem.kt b/app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendItem.kt index c739fb8..d7c4a75 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendItem.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendItem.kt @@ -16,7 +16,7 @@ data class RecommendItem(val apkLink: String, val publishTime: Long, val superChapterId: Int, val superChapterName: String, - val tags: List, + val tags: List, val title: String, val type: Int = 0, val userId: Int = -1, diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/bean/Tag.kt b/app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendTag.kt similarity index 58% rename from app/src/main/java/com/leeeyou/wanandroid/model/bean/Tag.kt rename to app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendTag.kt index 80625b4..8f1effb 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/model/bean/Tag.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendTag.kt @@ -5,5 +5,5 @@ package com.leeeyou.wanandroid.model.bean // "url": "/wxarticle/list/408/1" //} -data class Tag(val name: String, - val url: String) \ No newline at end of file +data class RecommendTag(val name: String, + val url: String) \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseSystemTag.kt b/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseSystemTag.kt new file mode 100644 index 0000000..5ad43f6 --- /dev/null +++ b/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseSystemTag.kt @@ -0,0 +1,5 @@ +package com.leeeyou.wanandroid.model.bean + +data class ResponseSystemTag(val data: List, + val errorCode: Int, + val errorMsg: String) \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/bean/SystemTag.kt b/app/src/main/java/com/leeeyou/wanandroid/model/bean/SystemTag.kt new file mode 100644 index 0000000..796e2d3 --- /dev/null +++ b/app/src/main/java/com/leeeyou/wanandroid/model/bean/SystemTag.kt @@ -0,0 +1,10 @@ +package com.leeeyou.wanandroid.model.bean + +data class SystemTag(val children: List, + val courseId: Int, + val id: Int, + val name: String, + val order: Int, + val parentChapterId: Int, + val userControlSetTop: Boolean, + val visible: Int) \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt b/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt index cfc2683..a12ea7b 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt @@ -2,6 +2,7 @@ package com.leeeyou.wanandroid.service import com.leeeyou.wanandroid.model.bean.ResponseBanner import com.leeeyou.wanandroid.model.bean.ResponseRecommendList +import com.leeeyou.wanandroid.model.bean.ResponseSystemTag import retrofit.http.GET import retrofit.http.Path import rx.Observable @@ -14,4 +15,6 @@ interface WanAndroidService { @GET("article/list/{index}/json") fun getRecommendList(@Path("index") index: Int): Observable + @GET("tree/json") + fun getSystemTagList():Observable } \ No newline at end of file diff --git a/app/src/main/res/color/text_color.xml b/app/src/main/res/color/text_color.xml new file mode 100644 index 0000000..68de3d5 --- /dev/null +++ b/app/src/main/res/color/text_color.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/checked_bg.xml b/app/src/main/res/drawable/checked_bg.xml new file mode 100644 index 0000000..92a12c2 --- /dev/null +++ b/app/src/main/res/drawable/checked_bg.xml @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/normal_bg.xml b/app/src/main/res/drawable/normal_bg.xml new file mode 100644 index 0000000..ccb9d6d --- /dev/null +++ b/app/src/main/res/drawable/normal_bg.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/tag_bg.xml b/app/src/main/res/drawable/tag_bg.xml new file mode 100644 index 0000000..4edd05c --- /dev/null +++ b/app/src/main/res/drawable/tag_bg.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_wan_android_system.xml b/app/src/main/res/layout/fragment_wan_android_system.xml index e45aee9..40bc9bc 100644 --- a/app/src/main/res/layout/fragment_wan_android_system.xml +++ b/app/src/main/res/layout/fragment_wan_android_system.xml @@ -1,7 +1,14 @@ + \ No newline at end of file diff --git a/app/src/main/res/layout/item_system_tag.xml b/app/src/main/res/layout/item_system_tag.xml new file mode 100644 index 0000000..5deb717 --- /dev/null +++ b/app/src/main/res/layout/item_system_tag.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file From 2dd5cb3e87fa69983721684eab9feb9c15fdf732 Mon Sep 17 00:00:00 2001 From: leeeyou Date: Thu, 3 Jan 2019 22:09:31 +0800 Subject: [PATCH 057/150] Update SystemTag UI Style --- app/src/main/res/color/text_color.xml | 4 ++-- app/src/main/res/drawable/checked_bg.xml | 14 -------------- app/src/main/res/drawable/system_tag_bg.xml | 5 +++++ .../{normal_bg.xml => system_tag_normal_bg.xml} | 8 ++++---- .../main/res/drawable/system_tag_selected_bg.xml | 13 +++++++++++++ app/src/main/res/drawable/tag_bg.xml | 11 ----------- .../res/layout/fragment_wan_android_system.xml | 4 ++-- app/src/main/res/layout/item_system_tag.xml | 14 ++++++-------- app/src/main/res/values/colors.xml | 3 ++- 9 files changed, 34 insertions(+), 42 deletions(-) delete mode 100644 app/src/main/res/drawable/checked_bg.xml create mode 100644 app/src/main/res/drawable/system_tag_bg.xml rename app/src/main/res/drawable/{normal_bg.xml => system_tag_normal_bg.xml} (68%) create mode 100644 app/src/main/res/drawable/system_tag_selected_bg.xml delete mode 100644 app/src/main/res/drawable/tag_bg.xml diff --git a/app/src/main/res/color/text_color.xml b/app/src/main/res/color/text_color.xml index 68de3d5..5cb54ff 100644 --- a/app/src/main/res/color/text_color.xml +++ b/app/src/main/res/color/text_color.xml @@ -1,7 +1,7 @@ - - + + \ No newline at end of file diff --git a/app/src/main/res/drawable/checked_bg.xml b/app/src/main/res/drawable/checked_bg.xml deleted file mode 100644 index 92a12c2..0000000 --- a/app/src/main/res/drawable/checked_bg.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/system_tag_bg.xml b/app/src/main/res/drawable/system_tag_bg.xml new file mode 100644 index 0000000..30c17f0 --- /dev/null +++ b/app/src/main/res/drawable/system_tag_bg.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/normal_bg.xml b/app/src/main/res/drawable/system_tag_normal_bg.xml similarity index 68% rename from app/src/main/res/drawable/normal_bg.xml rename to app/src/main/res/drawable/system_tag_normal_bg.xml index ccb9d6d..d7f57e0 100644 --- a/app/src/main/res/drawable/normal_bg.xml +++ b/app/src/main/res/drawable/system_tag_normal_bg.xml @@ -1,10 +1,10 @@ - + - + + android:top="1dp" /> \ No newline at end of file diff --git a/app/src/main/res/drawable/system_tag_selected_bg.xml b/app/src/main/res/drawable/system_tag_selected_bg.xml new file mode 100644 index 0000000..948ec6f --- /dev/null +++ b/app/src/main/res/drawable/system_tag_selected_bg.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/tag_bg.xml b/app/src/main/res/drawable/tag_bg.xml deleted file mode 100644 index 4edd05c..0000000 --- a/app/src/main/res/drawable/tag_bg.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_wan_android_system.xml b/app/src/main/res/layout/fragment_wan_android_system.xml index 40bc9bc..be1544c 100644 --- a/app/src/main/res/layout/fragment_wan_android_system.xml +++ b/app/src/main/res/layout/fragment_wan_android_system.xml @@ -8,7 +8,7 @@ android:id="@+id/systemFlowLayout" android:layout_width="match_parent" android:layout_height="wrap_content" - android:padding="20dp" - zhy:max_select="-1"/> + android:padding="10dp" + zhy:max_select="1"/> \ No newline at end of file diff --git a/app/src/main/res/layout/item_system_tag.xml b/app/src/main/res/layout/item_system_tag.xml index 5deb717..728fc3c 100644 --- a/app/src/main/res/layout/item_system_tag.xml +++ b/app/src/main/res/layout/item_system_tag.xml @@ -1,10 +1,8 @@ - - \ No newline at end of file + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:background="@drawable/system_tag_bg" + android:textColor="@color/text_color" + tools:text="HelloWorld" /> \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index f53b0a9..844e613 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -36,12 +36,13 @@ @color/default_red - #FF63727B + @color/default_gray #f0f0f0 @color/default_white #DC4037 + #FF63727B #ffffff #c5c5c5 From dd9ed88244ef89339dec4305e27a0e781c3f4d45 Mon Sep 17 00:00:00 2001 From: leeeyou Date: Thu, 3 Jan 2019 22:16:00 +0800 Subject: [PATCH 058/150] Update Resource Name --- ... index_custom_tab_icon_color_selector.xml} | 0 ...xml => system_tag_text_color_selector.xml} | 0 .../{selector_item.xml => list_selector.xml} | 0 app/src/main/res/drawable/selector_click.xml | 7 -- ...ab_icon1.xml => index_custom_tab_icon.xml} | 2 +- .../main/res/layout/item_one_index_blank.xml | 5 - .../main/res/layout/item_one_index_read.xml | 107 ------------------ .../main/res/layout/item_one_index_top.xml | 90 --------------- .../res/layout/item_one_index_weather.xml | 29 ----- app/src/main/res/layout/item_recommend.xml | 2 +- app/src/main/res/layout/item_system_tag.xml | 2 +- app/src/main/res/layout/item_zhihu_daily.xml | 2 +- 12 files changed, 4 insertions(+), 242 deletions(-) rename app/src/main/res/color/{custom_tab_icon.xml => index_custom_tab_icon_color_selector.xml} (100%) rename app/src/main/res/color/{text_color.xml => system_tag_text_color_selector.xml} (100%) rename app/src/main/res/drawable/{selector_item.xml => list_selector.xml} (100%) delete mode 100755 app/src/main/res/drawable/selector_click.xml rename app/src/main/res/layout/{custom_tab_icon1.xml => index_custom_tab_icon.xml} (87%) delete mode 100644 app/src/main/res/layout/item_one_index_blank.xml delete mode 100644 app/src/main/res/layout/item_one_index_read.xml delete mode 100644 app/src/main/res/layout/item_one_index_top.xml delete mode 100644 app/src/main/res/layout/item_one_index_weather.xml diff --git a/app/src/main/res/color/custom_tab_icon.xml b/app/src/main/res/color/index_custom_tab_icon_color_selector.xml similarity index 100% rename from app/src/main/res/color/custom_tab_icon.xml rename to app/src/main/res/color/index_custom_tab_icon_color_selector.xml diff --git a/app/src/main/res/color/text_color.xml b/app/src/main/res/color/system_tag_text_color_selector.xml similarity index 100% rename from app/src/main/res/color/text_color.xml rename to app/src/main/res/color/system_tag_text_color_selector.xml diff --git a/app/src/main/res/drawable/selector_item.xml b/app/src/main/res/drawable/list_selector.xml similarity index 100% rename from app/src/main/res/drawable/selector_item.xml rename to app/src/main/res/drawable/list_selector.xml diff --git a/app/src/main/res/drawable/selector_click.xml b/app/src/main/res/drawable/selector_click.xml deleted file mode 100755 index 992803d..0000000 --- a/app/src/main/res/drawable/selector_click.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/custom_tab_icon1.xml b/app/src/main/res/layout/index_custom_tab_icon.xml similarity index 87% rename from app/src/main/res/layout/custom_tab_icon1.xml rename to app/src/main/res/layout/index_custom_tab_icon.xml index 35eef04..e79bf52 100644 --- a/app/src/main/res/layout/custom_tab_icon1.xml +++ b/app/src/main/res/layout/index_custom_tab_icon.xml @@ -8,4 +8,4 @@ android:paddingLeft="15dp" android:paddingRight="15dp" android:scaleType="center" - app:tint="@color/custom_tab_icon"/> \ No newline at end of file + app:tint="@color/index_custom_tab_icon_color_selector"/> \ No newline at end of file diff --git a/app/src/main/res/layout/item_one_index_blank.xml b/app/src/main/res/layout/item_one_index_blank.xml deleted file mode 100644 index 5fdb4a8..0000000 --- a/app/src/main/res/layout/item_one_index_blank.xml +++ /dev/null @@ -1,5 +0,0 @@ - - diff --git a/app/src/main/res/layout/item_one_index_read.xml b/app/src/main/res/layout/item_one_index_read.xml deleted file mode 100644 index 2fb2c31..0000000 --- a/app/src/main/res/layout/item_one_index_read.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/item_one_index_top.xml b/app/src/main/res/layout/item_one_index_top.xml deleted file mode 100644 index 956f7cd..0000000 --- a/app/src/main/res/layout/item_one_index_top.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/item_one_index_weather.xml b/app/src/main/res/layout/item_one_index_weather.xml deleted file mode 100644 index 001a5a8..0000000 --- a/app/src/main/res/layout/item_one_index_weather.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - diff --git a/app/src/main/res/layout/item_recommend.xml b/app/src/main/res/layout/item_recommend.xml index 1f5c895..8f81074 100644 --- a/app/src/main/res/layout/item_recommend.xml +++ b/app/src/main/res/layout/item_recommend.xml @@ -4,7 +4,7 @@ android:id="@+id/rl_recommend_item" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="@drawable/selector_item"> + android:background="@drawable/list_selector"> \ No newline at end of file diff --git a/app/src/main/res/layout/item_zhihu_daily.xml b/app/src/main/res/layout/item_zhihu_daily.xml index 520f216..53f30eb 100644 --- a/app/src/main/res/layout/item_zhihu_daily.xml +++ b/app/src/main/res/layout/item_zhihu_daily.xml @@ -3,7 +3,7 @@ android:id="@+id/rl_item_recommend" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="@drawable/selector_item"> + android:background="@drawable/list_selector"> Date: Thu, 3 Jan 2019 22:21:07 +0800 Subject: [PATCH 059/150] Update Resource Name --- app/src/main/java/com/leeeyou/IndexActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/leeeyou/IndexActivity.kt b/app/src/main/java/com/leeeyou/IndexActivity.kt index 2e4a5fc..ac686f3 100644 --- a/app/src/main/java/com/leeeyou/IndexActivity.kt +++ b/app/src/main/java/com/leeeyou/IndexActivity.kt @@ -44,7 +44,7 @@ class IndexActivity : AppCompatActivity() { } indexTabLayout.setCustomTabView { container, position, _ -> - val icon = LayoutInflater.from(this@IndexActivity).inflate(R.layout.custom_tab_icon1, container, false) as ImageView + val icon = LayoutInflater.from(this@IndexActivity).inflate(R.layout.index_custom_tab_icon, container, false) as ImageView val res = this@IndexActivity.resources when (position) { From 01a631f285abfa055a2f1126977585b799256f8a Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Fri, 4 Jan 2019 09:49:31 +0800 Subject: [PATCH 060/150] Update SystemTag UI Style --- app/src/main/res/drawable/system_tag_normal_bg.xml | 8 ++++---- .../main/res/drawable/system_tag_selected_bg.xml | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/src/main/res/drawable/system_tag_normal_bg.xml b/app/src/main/res/drawable/system_tag_normal_bg.xml index d7f57e0..411b385 100644 --- a/app/src/main/res/drawable/system_tag_normal_bg.xml +++ b/app/src/main/res/drawable/system_tag_normal_bg.xml @@ -3,8 +3,8 @@ + android:bottom="1.5dp" + android:left="5dp" + android:right="5dp" + android:top="1.5dp" /> \ No newline at end of file diff --git a/app/src/main/res/drawable/system_tag_selected_bg.xml b/app/src/main/res/drawable/system_tag_selected_bg.xml index 948ec6f..691f203 100644 --- a/app/src/main/res/drawable/system_tag_selected_bg.xml +++ b/app/src/main/res/drawable/system_tag_selected_bg.xml @@ -1,13 +1,13 @@ - - + + + android:color="@color/default_red"/> + android:bottom="1.5dp" + android:left="5dp" + android:right="5dp" + android:top="1.5dp"/> \ No newline at end of file From 2389a5643cd6b37d21f598d2a6105056daf72d48 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Fri, 4 Jan 2019 18:45:02 +0800 Subject: [PATCH 061/150] fetch RecommendSystemTagArticle data --- .../wanandroid/WanAndroidSystemFragment.kt | 234 +++++++++++++++++- .../wanandroid/model/WanAndroidRepository.kt | 7 + .../bean/ResponseSystemTagArticleList.kt | 5 + .../model/bean/SystemTagArticleList.kt | 9 + .../wanandroid/service/WanAndroidService.kt | 7 +- .../layout/fragment_wan_android_system.xml | 78 +++++- .../res/mipmap-xhdpi/icon_arrow_right.png | Bin 0 -> 283 bytes app/src/main/res/values/colors.xml | 1 + 8 files changed, 318 insertions(+), 23 deletions(-) create mode 100644 app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseSystemTagArticleList.kt create mode 100644 app/src/main/java/com/leeeyou/wanandroid/model/bean/SystemTagArticleList.kt create mode 100644 app/src/main/res/mipmap-xhdpi/icon_arrow_right.png diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt index f560410..e5ae425 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt @@ -1,14 +1,28 @@ package com.leeeyou.wanandroid +import `in`.srain.cube.views.ptr.PtrFrameLayout +import `in`.srain.cube.views.ptr.PtrHandler +import android.annotation.SuppressLint import android.os.Bundle +import android.support.v7.widget.LinearLayoutManager import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.view.animation.AccelerateInterpolator +import android.view.animation.Animation +import android.view.animation.RotateAnimation import android.widget.TextView +import com.chad.library.adapter.base.BaseQuickAdapter +import com.chad.library.adapter.base.BaseViewHolder import com.leeeyou.R import com.leeeyou.manager.BaseFragment import com.leeeyou.util.inflate +import com.leeeyou.util.startBrowserActivity +import com.leeeyou.wanandroid.model.bean.RecommendItem +import com.leeeyou.wanandroid.model.bean.ResponseSystemTag import com.leeeyou.wanandroid.model.bean.SystemTag +import com.leeeyou.wanandroid.model.bean.SystemTagArticleList +import com.leeeyou.wanandroid.model.fetchSystemTagArticleList import com.leeeyou.wanandroid.model.fetchSystemTagList import com.zhy.view.flowlayout.FlowLayout import com.zhy.view.flowlayout.TagAdapter @@ -25,37 +39,231 @@ import timber.log.Timber * Date: 2017/4/24 13:46 */ class WanAndroidSystemFragment : BaseFragment() { + private lateinit var mLinearLayoutManager: LinearLayoutManager + private var mPageIndex: Int = 0 + private lateinit var mSystemTagArticleAdapter: BaseQuickAdapter + private var mPageCount: Int = 0 + + private var mSelectedParentTagPosition: Int = 0 + private var mSelectedChildTagPosition: Int = 0 + + private var mSelectedParentTagId: Int = 0 + private var mSelectedChildTagId: Int = 0 + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return container?.inflate(R.layout.fragment_wan_android_system) } override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) + + initRecyclerView() + initPtrFrame() + + rl_system_tag_combine.setOnClickListener { + val animation: RotateAnimation = if (sv_system_tag_all.visibility == View.VISIBLE) { + RotateAnimation(90f, 0f, (iv_arrow_right.width / 2).toFloat(), (iv_arrow_right.height / 2).toFloat()) + } else { + RotateAnimation(0f, 90f, (iv_arrow_right.width / 2).toFloat(), (iv_arrow_right.height / 2).toFloat()) + } + animation.duration = 100 + animation.fillAfter = true + animation.interpolator = AccelerateInterpolator() + iv_arrow_right.startAnimation(animation) + + animation.setAnimationListener(object : Animation.AnimationListener { + override fun onAnimationRepeat(animation: Animation?) { + } + + override fun onAnimationEnd(animation: Animation?) { + if (sv_system_tag_all.visibility == View.VISIBLE) { + sv_system_tag_all.visibility = View.GONE + } else { + sv_system_tag_all.visibility = View.VISIBLE + } + } + + override fun onAnimationStart(animation: Animation?) { + } + }) + } + fetchSystemTagList() .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .doOnNext { - Timber.d("fetchSystemTagList doOnNext") - it.takeIf { response -> response.errorCode >= 0 }?.also { response -> - Timber.d(response.data.toString()) + renderSystemTag(response) + } ?: IllegalArgumentException("fetchSystemTagList接口返回异常") + }.subscribe() + } + + private fun initRecyclerView() { + mLinearLayoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) + mSystemTagArticleAdapter = object : BaseQuickAdapter(R.layout.item_recommend, null) { + override fun convert(helper: BaseViewHolder?, item: RecommendItem?) { + item?.takeIf { it.visible == 1 }?.also { + helper?.setText(R.id.tv_title, it.title) + ?.setText(R.id.tv_author, "作者:" + it.author) + ?.setText(R.id.tv_category, "分类:" + it.superChapterName + " / " + it.chapterName) + ?.setText(R.id.tv_niceDate, it.niceDate) + ?.setGone(R.id.tv_refresh, it.fresh) + } + } + } + mSystemTagArticleAdapter.setOnLoadMoreListener({ + if (mPageIndex + 1 == mPageCount) { + mSystemTagArticleAdapter.loadMoreEnd() + } else { + fetchSystemTagArticleList(++mPageIndex) + } + }, recyclerViewSystem) + mSystemTagArticleAdapter.setOnItemClickListener { adapter, _, position -> + val item: RecommendItem = adapter.getItem(position) as RecommendItem + startBrowserActivity(context!!, item.link, item.title) + } + mSystemTagArticleAdapter.openLoadAnimation(BaseQuickAdapter.SCALEIN) + + recyclerViewSystem.layoutManager = mLinearLayoutManager + recyclerViewSystem.adapter = mSystemTagArticleAdapter + } + + private fun initPtrFrame() { + ptrFrameSystemTag.disableWhenHorizontalMove(true) + ptrFrameSystemTag.setPtrHandler(object : PtrHandler { + override fun onRefreshBegin(frame: PtrFrameLayout?) { + pullDownToRefresh() + } + + override fun checkCanDoRefresh(frame: PtrFrameLayout?, content: View?, header: View?): Boolean = + sv_system_tag_all.visibility != View.VISIBLE && recyclerViewFirstItemCanVisible() + }) + } + + private fun pullDownToRefresh() { + mPageIndex = 0 + fetchSystemTagArticleList(mPageIndex) + } + + private fun recyclerViewFirstItemCanVisible() = + mLinearLayoutManager.findFirstCompletelyVisibleItemPosition() <= 0 + + private fun renderSystemTag(response: ResponseSystemTag) { + mSelectedParentTagPosition = 0 + mSelectedChildTagPosition = 0 + + val parentTagList = response.data + val childTagList = parentTagList[mSelectedParentTagPosition].children + mSelectedParentTagId = parentTagList[mSelectedParentTagPosition].id + mSelectedChildTagId = childTagList[mSelectedChildTagPosition].id - systemFlowLayout.adapter = object : TagAdapter(response.data) { - override fun getView(parent: FlowLayout?, position: Int, t: SystemTag?): View { - t?.let { - val textView = LayoutInflater.from(context).inflate(R.layout.item_system_tag, null) as TextView - textView.text = t.name - return textView - } - } + renderParentTag(parentTagList) + renderChildTag(childTagList) + processClickEvent(response) + } + + private fun processClickEvent(response: ResponseSystemTag) { + system_tag_parent.setOnTagClickListener { _, position, parent -> + mSelectedParentTagPosition = position + mSelectedChildTagPosition = 0 + mSelectedParentTagId = response.data[mSelectedParentTagPosition].id + mSelectedChildTagId = response.data[mSelectedParentTagPosition].children[mSelectedChildTagPosition].id + + renderChildTag(response.data[mSelectedParentTagPosition].children) + for (index in 0..parent.childCount) { + parent.getChildAt(index)?.isClickable = mSelectedParentTagPosition != index + } + true + } + + system_tag_child.setOnTagClickListener { _, position, parent -> + mSelectedChildTagPosition = position + mSelectedChildTagId = response.data[mSelectedParentTagPosition].children[mSelectedChildTagPosition].id + for (index in 0..parent.childCount) { + parent.getChildAt(index)?.isClickable = mSelectedChildTagPosition != index + } + updateSystemTagCombineShow() + pullDownToRefresh() + sv_system_tag_all.visibility = View.GONE + true + } + } + + private fun fetchSystemTagArticleList(pageIndex: Int) { + Timber.d("fetchSystemTagArticleList , parent id is %s , child id is %s", mSelectedParentTagId, mSelectedChildTagId) + fetchSystemTagArticleList(pageIndex, mSelectedChildTagId) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext { + ptrFrameSystemTag?.refreshComplete() + + it.takeIf { response -> + response.errorCode >= 0 + }?.also { response -> + Timber.d(it.data.toString()) + renderSystemTagArticleList(pageIndex, response.data) + + mSystemTagArticleAdapter.loadMoreComplete() + if (mPageIndex == 0 && response.data.datas.size <= response.data.size) { + mSystemTagArticleAdapter.loadMoreEnd() } + } ?: IllegalArgumentException("fetchSystemTagArticleList接口返回异常") + } + .subscribe() + } - } ?: IllegalArgumentException("fetchSystemTagList接口返回异常") - }.subscribe() + private fun renderSystemTagArticleList(pageIndex: Int, data: SystemTagArticleList) { + if (pageIndex == 0) { + mSystemTagArticleAdapter.setNewData(data.datas) + } else { + mPageCount = data.pageCount + mSystemTagArticleAdapter.addData(data.datas) + } + } + private fun renderParentTag(parentTagList: List) { + system_tag_parent.adapter = object : TagAdapter(parentTagList) { + override fun getView(parent: FlowLayout?, position: Int, systemTag: SystemTag?): View { + systemTag?.let { + val parentTag = layoutInflater.inflate(R.layout.item_system_tag, null) as TextView + parentTag.text = it.name + return parentTag + } + } + } + system_tag_parent.adapter.setSelectedList(mSelectedParentTagPosition) + system_tag_parent.getChildAt(mSelectedParentTagPosition)?.isClickable = false + } + + private fun renderChildTag(childTagList: List) { + system_tag_child.adapter = object : TagAdapter(childTagList) { + override fun getView(parent: FlowLayout?, position: Int, systemTag: SystemTag?): View { + systemTag?.let { + val childTag = layoutInflater.inflate(R.layout.item_system_tag, null) as TextView + childTag.text = it.name + return childTag + } + } + } + system_tag_child.adapter.setSelectedList(mSelectedChildTagPosition) + system_tag_child.getChildAt(mSelectedChildTagPosition)?.isClickable = false + + updateSystemTagCombineShow() + pullDownToRefresh() + if (childTagList.size == 1) { + sv_system_tag_all.visibility = View.GONE + } } + + @SuppressLint("SetTextI18n") + private fun updateSystemTagCombineShow() { + val parentTag: SystemTag = system_tag_parent?.adapter?.getItem(mSelectedParentTagPosition) as SystemTag + val childTag = system_tag_child?.adapter?.getItem(mSelectedChildTagPosition) as SystemTag + tv_system_tag_combine.text = parentTag.name + " / " + childTag.name + } + } diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt b/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt index 8fd7331..42bb204 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt @@ -4,6 +4,7 @@ import com.leeeyou.factory.ServiceFactory import com.leeeyou.wanandroid.model.bean.ResponseBanner import com.leeeyou.wanandroid.model.bean.ResponseRecommendList import com.leeeyou.wanandroid.model.bean.ResponseSystemTag +import com.leeeyou.wanandroid.model.bean.ResponseSystemTagArticleList import com.leeeyou.wanandroid.service.WanAndroidService import rx.Observable @@ -26,3 +27,9 @@ fun fetchSystemTagList(): Observable { .createRxRetrofitService(WanAndroidService::class.java, endPoint) .getSystemTagList() } + +fun fetchSystemTagArticleList(pageIndex: Int, cid: Int): Observable { + return ServiceFactory + .createRxRetrofitService(WanAndroidService::class.java, endPoint) + .getSystemTagArticleList(pageIndex, cid) +} \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseSystemTagArticleList.kt b/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseSystemTagArticleList.kt new file mode 100644 index 0000000..8f38245 --- /dev/null +++ b/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseSystemTagArticleList.kt @@ -0,0 +1,5 @@ +package com.leeeyou.wanandroid.model.bean + +data class ResponseSystemTagArticleList(val data: SystemTagArticleList, + val errorCode: Int, + val errorMsg: String) \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/bean/SystemTagArticleList.kt b/app/src/main/java/com/leeeyou/wanandroid/model/bean/SystemTagArticleList.kt new file mode 100644 index 0000000..fb0bb8e --- /dev/null +++ b/app/src/main/java/com/leeeyou/wanandroid/model/bean/SystemTagArticleList.kt @@ -0,0 +1,9 @@ +package com.leeeyou.wanandroid.model.bean + +data class SystemTagArticleList(val curPage: Int, + val datas: List, + val offset: Int, + val over: Boolean, + val pageCount: Int, + val size: Int, + val total: Int) \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt b/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt index a12ea7b..5c06f7b 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt @@ -3,8 +3,10 @@ package com.leeeyou.wanandroid.service import com.leeeyou.wanandroid.model.bean.ResponseBanner import com.leeeyou.wanandroid.model.bean.ResponseRecommendList import com.leeeyou.wanandroid.model.bean.ResponseSystemTag +import com.leeeyou.wanandroid.model.bean.ResponseSystemTagArticleList import retrofit.http.GET import retrofit.http.Path +import retrofit.http.Query import rx.Observable interface WanAndroidService { @@ -16,5 +18,8 @@ interface WanAndroidService { fun getRecommendList(@Path("index") index: Int): Observable @GET("tree/json") - fun getSystemTagList():Observable + fun getSystemTagList(): Observable + + @GET("article/list/{pageIndex}/json") + fun getSystemTagArticleList(@Path("pageIndex") pageIndex: Int, @Query("cid") cid: Int): Observable } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_wan_android_system.xml b/app/src/main/res/layout/fragment_wan_android_system.xml index be1544c..99dfb78 100644 --- a/app/src/main/res/layout/fragment_wan_android_system.xml +++ b/app/src/main/res/layout/fragment_wan_android_system.xml @@ -1,14 +1,74 @@ - - + android:layout_height="match_parent"> - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-xhdpi/icon_arrow_right.png b/app/src/main/res/mipmap-xhdpi/icon_arrow_right.png new file mode 100644 index 0000000000000000000000000000000000000000..beb4f292a9ddfe381ff34af9f9100a0a43ce4603 GIT binary patch literal 283 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpUtN1iT@AsLNtZ*2Evbrfm4sM)~8 z@$p`3OG(#vJr$J&99|20oHuwZV2^TB*n3g-Zt%hH=h=2|UbC6PvQ|%v#9T(l9GkZXRp>E3uZ7U)QN)qdwXtV-~Fz=rcGABwvJUi@bUD*c^@ygsm^ijjX#ok%wJlp zK*;i+Mb@91CqFD@T6^@DiX4tD4_YA~&0fJ*{wZG4Zt{Jnxqnm+&o)o1@zPxS;U43< XB45+;nZLAwzGd)q^>bP0l+XkKGZ=bx literal 0 HcmV?d00001 diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 844e613..ce03ce4 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -44,6 +44,7 @@ #DC4037 #FF63727B #ffffff + #f9f900 #c5c5c5 From f8f77699a65c383502a784b92e26e716a3ef32ff Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Sat, 5 Jan 2019 18:18:27 +0800 Subject: [PATCH 062/150] process RecommendSystemTagArticle data not visible problem --- .../wanandroid/WanAndroidSystemFragment.kt | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt index e5ae425..81627e3 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt @@ -104,7 +104,7 @@ class WanAndroidSystemFragment : BaseFragment() { mLinearLayoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) mSystemTagArticleAdapter = object : BaseQuickAdapter(R.layout.item_recommend, null) { override fun convert(helper: BaseViewHolder?, item: RecommendItem?) { - item?.takeIf { it.visible == 1 }?.also { + item?.also { helper?.setText(R.id.tv_title, it.title) ?.setText(R.id.tv_author, "作者:" + it.author) ?.setText(R.id.tv_category, "分类:" + it.superChapterName + " / " + it.chapterName) @@ -120,6 +120,7 @@ class WanAndroidSystemFragment : BaseFragment() { fetchSystemTagArticleList(++mPageIndex) } }, recyclerViewSystem) + mSystemTagArticleAdapter.disableLoadMoreIfNotFullPage() mSystemTagArticleAdapter.setOnItemClickListener { adapter, _, position -> val item: RecommendItem = adapter.getItem(position) as RecommendItem startBrowserActivity(context!!, item.link, item.title) @@ -217,11 +218,37 @@ class WanAndroidSystemFragment : BaseFragment() { private fun renderSystemTagArticleList(pageIndex: Int, data: SystemTagArticleList) { if (pageIndex == 0) { - mSystemTagArticleAdapter.setNewData(data.datas) + mSystemTagArticleAdapter.setNewData(ArrayList(data.datas)) } else { mPageCount = data.pageCount mSystemTagArticleAdapter.addData(data.datas) } + + // recyclerViewSystem.getChildAt(0)?.height * itemCount < recyclerViewSystem.height -> removeFooter 否则 addFooter + +// val countHeight = recyclerViewSystem.height +// val itemHeight = recyclerViewSystem.getChildAt(0)?.height +// +// itemHeight?.let { +// val currentHeight: Int = mSystemTagArticleAdapter.itemCount * it +// if (currentHeight < countHeight) { +// +// mSystemTagArticleAdapter.refreshNotifyItemChanged(mSystemTagArticleAdapter.itemCount - 1) +// +//// mSystemTagArticleAdapter.removeAllFooterView() +//// mSystemTagArticleAdapter.notifyItemRemoved() +// +// Timber.d("recyclerViewSystem.childCount %s ", recyclerViewSystem.childCount) +// Timber.d("mSystemTagArticleAdapter.itemCount %s ", mSystemTagArticleAdapter.itemCount) +// } +// } +// +// Timber.d("recyclerViewSystem.height %s ", countHeight) +// Timber.d("recyclerViewSystem.getChildAt(0).height %s ", recyclerViewSystem.getChildAt(0)?.height) + } + + private fun isFullScreen(llm: LinearLayoutManager): Boolean { + return llm.findLastCompletelyVisibleItemPosition() + 1 != mSystemTagArticleAdapter.itemCount || llm.findFirstCompletelyVisibleItemPosition() != 0 } private fun renderParentTag(parentTagList: List) { From aee4b01cbd6443eddc51bce0f98a6f10939a8a9f Mon Sep 17 00:00:00 2001 From: leeeyou Date: Sun, 6 Jan 2019 20:43:23 +0800 Subject: [PATCH 063/150] Update SystemTag UI Style --- .../layout/fragment_wan_android_system.xml | 43 +++++++++++++------ app/src/main/res/layout/item_system_tag.xml | 1 + 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/app/src/main/res/layout/fragment_wan_android_system.xml b/app/src/main/res/layout/fragment_wan_android_system.xml index 99dfb78..40119fe 100644 --- a/app/src/main/res/layout/fragment_wan_android_system.xml +++ b/app/src/main/res/layout/fragment_wan_android_system.xml @@ -1,9 +1,9 @@ + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/ptrFrameSystemTag" + android:layout_width="match_parent" + android:layout_height="match_parent"> + tools:text="开发环境 / gradle" /> + android:tint="@color/default_white" /> + android:layout_below="@id/rl_system_tag_combine" /> + android:visibility="visible"> + + + app:max_select="1" /> + + + app:max_select="1" /> diff --git a/app/src/main/res/layout/item_system_tag.xml b/app/src/main/res/layout/item_system_tag.xml index 069f5b3..699e2d7 100644 --- a/app/src/main/res/layout/item_system_tag.xml +++ b/app/src/main/res/layout/item_system_tag.xml @@ -5,4 +5,5 @@ android:layout_height="wrap_content" android:background="@drawable/system_tag_bg" android:textColor="@color/system_tag_text_color_selector" + android:textSize="14sp" tools:text="HelloWorld" /> \ No newline at end of file From 17d7efccea3e3b9ee860529fc4451a0dba89dcda Mon Sep 17 00:00:00 2001 From: leeeyou Date: Sun, 6 Jan 2019 21:59:28 +0800 Subject: [PATCH 064/150] Update SystemTag UI style --- .../wanandroid/WanAndroidSystemFragment.kt | 95 +++++++++---------- .../layout/fragment_wan_android_system.xml | 4 +- 2 files changed, 46 insertions(+), 53 deletions(-) diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt index 81627e3..4460022 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt @@ -54,6 +54,46 @@ class WanAndroidSystemFragment : BaseFragment() { return container?.inflate(R.layout.fragment_wan_android_system) } + private fun showDetailTagAnimation() { + val rotateAnimation = RotateAnimation(0f, 90f, (iv_arrow_right.width / 2).toFloat(), (iv_arrow_right.height / 2).toFloat()) + rotateAnimation.duration = 100 + rotateAnimation.fillAfter = true + rotateAnimation.interpolator = AccelerateInterpolator() + iv_arrow_right.startAnimation(rotateAnimation) + + rotateAnimation.setAnimationListener(object : Animation.AnimationListener { + override fun onAnimationRepeat(animation: Animation?) { + } + + override fun onAnimationEnd(animation: Animation?) { + sv_system_tag_all.visibility = View.VISIBLE + } + + override fun onAnimationStart(animation: Animation?) { + } + }) + } + + private fun hiddenDetailTagAnimation() { + val rotateAnimation = RotateAnimation(90f, 0f, (iv_arrow_right.width / 2).toFloat(), (iv_arrow_right.height / 2).toFloat()) + rotateAnimation.duration = 100 + rotateAnimation.fillAfter = true + rotateAnimation.interpolator = AccelerateInterpolator() + iv_arrow_right.startAnimation(rotateAnimation) + + rotateAnimation.setAnimationListener(object : Animation.AnimationListener { + override fun onAnimationRepeat(animation: Animation?) { + } + + override fun onAnimationEnd(animation: Animation?) { + sv_system_tag_all.visibility = View.GONE + } + + override fun onAnimationStart(animation: Animation?) { + } + }) + } + override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) @@ -61,31 +101,7 @@ class WanAndroidSystemFragment : BaseFragment() { initPtrFrame() rl_system_tag_combine.setOnClickListener { - val animation: RotateAnimation = if (sv_system_tag_all.visibility == View.VISIBLE) { - RotateAnimation(90f, 0f, (iv_arrow_right.width / 2).toFloat(), (iv_arrow_right.height / 2).toFloat()) - } else { - RotateAnimation(0f, 90f, (iv_arrow_right.width / 2).toFloat(), (iv_arrow_right.height / 2).toFloat()) - } - animation.duration = 100 - animation.fillAfter = true - animation.interpolator = AccelerateInterpolator() - iv_arrow_right.startAnimation(animation) - - animation.setAnimationListener(object : Animation.AnimationListener { - override fun onAnimationRepeat(animation: Animation?) { - } - - override fun onAnimationEnd(animation: Animation?) { - if (sv_system_tag_all.visibility == View.VISIBLE) { - sv_system_tag_all.visibility = View.GONE - } else { - sv_system_tag_all.visibility = View.VISIBLE - } - } - - override fun onAnimationStart(animation: Animation?) { - } - }) + if (sv_system_tag_all.visibility == View.VISIBLE) hiddenDetailTagAnimation() else showDetailTagAnimation() } fetchSystemTagList() @@ -188,7 +204,7 @@ class WanAndroidSystemFragment : BaseFragment() { } updateSystemTagCombineShow() pullDownToRefresh() - sv_system_tag_all.visibility = View.GONE + hiddenDetailTagAnimation() true } } @@ -223,28 +239,6 @@ class WanAndroidSystemFragment : BaseFragment() { mPageCount = data.pageCount mSystemTagArticleAdapter.addData(data.datas) } - - // recyclerViewSystem.getChildAt(0)?.height * itemCount < recyclerViewSystem.height -> removeFooter 否则 addFooter - -// val countHeight = recyclerViewSystem.height -// val itemHeight = recyclerViewSystem.getChildAt(0)?.height -// -// itemHeight?.let { -// val currentHeight: Int = mSystemTagArticleAdapter.itemCount * it -// if (currentHeight < countHeight) { -// -// mSystemTagArticleAdapter.refreshNotifyItemChanged(mSystemTagArticleAdapter.itemCount - 1) -// -//// mSystemTagArticleAdapter.removeAllFooterView() -//// mSystemTagArticleAdapter.notifyItemRemoved() -// -// Timber.d("recyclerViewSystem.childCount %s ", recyclerViewSystem.childCount) -// Timber.d("mSystemTagArticleAdapter.itemCount %s ", mSystemTagArticleAdapter.itemCount) -// } -// } -// -// Timber.d("recyclerViewSystem.height %s ", countHeight) -// Timber.d("recyclerViewSystem.getChildAt(0).height %s ", recyclerViewSystem.getChildAt(0)?.height) } private fun isFullScreen(llm: LinearLayoutManager): Boolean { @@ -280,10 +274,7 @@ class WanAndroidSystemFragment : BaseFragment() { updateSystemTagCombineShow() pullDownToRefresh() - - if (childTagList.size == 1) { - sv_system_tag_all.visibility = View.GONE - } + childTagList.size.takeIf { it == 1 }.also { hiddenDetailTagAnimation() } } @SuppressLint("SetTextI18n") diff --git a/app/src/main/res/layout/fragment_wan_android_system.xml b/app/src/main/res/layout/fragment_wan_android_system.xml index 40119fe..5e9c9ef 100644 --- a/app/src/main/res/layout/fragment_wan_android_system.xml +++ b/app/src/main/res/layout/fragment_wan_android_system.xml @@ -22,6 +22,8 @@ android:gravity="center_vertical" android:paddingLeft="10dp" android:text="开发环境 / gradle" + android:textSize="14sp" + android:textStyle="bold" tools:text="开发环境 / gradle" /> + android:visibility="gone"> Date: Sun, 6 Jan 2019 22:05:49 +0800 Subject: [PATCH 065/150] Update SystemTag adapter return value --- app/build.gradle | 2 +- .../java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index af7a3d4..d5e34b5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,7 +3,7 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-android-extensions' -def keystorePropertiesFile = rootProject.file("D:\\keystore\\RsKotlin\\RsKotlinKeystore.properties") +def keystorePropertiesFile = rootProject.file("..\\..\\Leeeyou\\keystore\\RsKotlin\\RsKotlinKeystore.properties") def keystoreProperties = new Properties() keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt index 4460022..1067383 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt @@ -248,11 +248,12 @@ class WanAndroidSystemFragment : BaseFragment() { private fun renderParentTag(parentTagList: List) { system_tag_parent.adapter = object : TagAdapter(parentTagList) { override fun getView(parent: FlowLayout?, position: Int, systemTag: SystemTag?): View { + val parentTag = layoutInflater.inflate(R.layout.item_system_tag, null) as TextView systemTag?.let { - val parentTag = layoutInflater.inflate(R.layout.item_system_tag, null) as TextView parentTag.text = it.name return parentTag } + return parentTag } } system_tag_parent.adapter.setSelectedList(mSelectedParentTagPosition) @@ -262,11 +263,12 @@ class WanAndroidSystemFragment : BaseFragment() { private fun renderChildTag(childTagList: List) { system_tag_child.adapter = object : TagAdapter(childTagList) { override fun getView(parent: FlowLayout?, position: Int, systemTag: SystemTag?): View { + val childTag = layoutInflater.inflate(R.layout.item_system_tag, null) as TextView systemTag?.let { - val childTag = layoutInflater.inflate(R.layout.item_system_tag, null) as TextView childTag.text = it.name return childTag } + return childTag } } system_tag_child.adapter.setSelectedList(mSelectedChildTagPosition) From 9fbbbb0bc9aa484503a595c3acb6d42126a2ef0b Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Mon, 7 Jan 2019 11:04:38 +0800 Subject: [PATCH 066/150] fixbug takeif also --- app/build.gradle | 3 ++- .../java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d5e34b5..d20d0e9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,7 +3,8 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-android-extensions' -def keystorePropertiesFile = rootProject.file("..\\..\\Leeeyou\\keystore\\RsKotlin\\RsKotlinKeystore.properties") +def keystorePropertiesFile = rootProject.file("D:\\keystore\\RsKotlin\\RsKotlinKeystore.properties") +//def keystorePropertiesFile = rootProject.file("..\\..\\Leeeyou\\keystore\\RsKotlin\\RsKotlinKeystore.properties") def keystoreProperties = new Properties() keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt index 1067383..1bc2eb5 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt @@ -276,7 +276,8 @@ class WanAndroidSystemFragment : BaseFragment() { updateSystemTagCombineShow() pullDownToRefresh() - childTagList.size.takeIf { it == 1 }.also { hiddenDetailTagAnimation() } + childTagList.size.takeIf { it == 1 }?.also { hiddenDetailTagAnimation() } + ?: Timber.d("childTagList.size != 1") } @SuppressLint("SetTextI18n") From 877d1a50151170d15363f6c9032fa0de23ef353e Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Mon, 7 Jan 2019 18:37:17 +0800 Subject: [PATCH 067/150] 1. Refactor ServiceFactory, add custom GsonConvert, add custom OkHttpClient, add HttpLoggingInterceptor 2. Solve the problem of json conversion failure --- app/build.gradle | 23 ++++-- .../com/leeeyou/factory/ServiceFactory.kt | 35 --------- .../com/leeeyou/service/ServiceFactory.kt | 63 +++++++++++++++ .../service/converter/MyGsonConverter.java | 68 +++++++++++++++++ .../converter/MyGsonConverterFactory.java | 38 ++++++++++ .../leeeyou/service/entity/BaseEntity.java | 31 ++++++++ .../entity/HttpErrorResponseEntity.java | 27 +++++++ .../service/entity/HttpResultEntity.java | 7 ++ .../exception/HttpResultException.java | 21 +++++ .../DefaultHttpResultSubscriber.java | 15 ++++ .../subscriber/HttpResultSubscriber.java | 51 +++++++++++++ .../wanandroid/WanAndroidRecommendFragment.kt | 72 ++++++------------ .../wanandroid/WanAndroidSystemFragment.kt | 76 +++++++++---------- .../wanandroid/model/WanAndroidRepository.kt | 19 ++--- .../wanandroid/model/bean/ResponseBanner.kt | 5 -- .../model/bean/ResponseRecommendList.kt | 5 -- .../wanandroid/service/WanAndroidService.kt | 24 +++--- .../zhihudaily/model/ZhiHuDailyRepository.kt | 2 +- .../zhihudaily/service/ZhiHuDailyService.kt | 4 +- 19 files changed, 421 insertions(+), 165 deletions(-) delete mode 100644 app/src/main/java/com/leeeyou/factory/ServiceFactory.kt create mode 100644 app/src/main/java/com/leeeyou/service/ServiceFactory.kt create mode 100644 app/src/main/java/com/leeeyou/service/converter/MyGsonConverter.java create mode 100644 app/src/main/java/com/leeeyou/service/converter/MyGsonConverterFactory.java create mode 100644 app/src/main/java/com/leeeyou/service/entity/BaseEntity.java create mode 100644 app/src/main/java/com/leeeyou/service/entity/HttpErrorResponseEntity.java create mode 100644 app/src/main/java/com/leeeyou/service/entity/HttpResultEntity.java create mode 100644 app/src/main/java/com/leeeyou/service/exception/HttpResultException.java create mode 100644 app/src/main/java/com/leeeyou/service/subscriber/DefaultHttpResultSubscriber.java create mode 100644 app/src/main/java/com/leeeyou/service/subscriber/HttpResultSubscriber.java delete mode 100644 app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseBanner.kt delete mode 100644 app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseRecommendList.kt diff --git a/app/build.gradle b/app/build.gradle index d20d0e9..cc55e44 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -66,9 +66,9 @@ dependencies { implementation "com.android.support:multidex:1.0.3" //retrofit - implementation 'com.squareup.retrofit:retrofit:2.0.0-beta2' - implementation 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2' - implementation 'com.squareup.retrofit:converter-gson:2.0.0-beta2' + implementation 'com.squareup.retrofit2:retrofit:2.5.0' + implementation 'com.squareup.retrofit2:adapter-rxjava:2.5.0' + implementation 'com.squareup.retrofit2:converter-gson:2.5.0' //rx implementation 'io.reactivex:rxandroid:1.2.1' @@ -81,13 +81,24 @@ dependencies { //glide implementation 'com.github.bumptech.glide:glide:4.8.0' + //okhttp + implementation 'com.squareup.okhttp3:logging-interceptor:3.1.2' + implementation("com.squareup.okhttp3:okhttp:3.12.1") + + //kotlin implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.44' - implementation 'net.danlew:android.joda:2.9.9.4' - implementation 'com.afollestad.material-dialogs:core:0.9.4.7' + + //ptr implementation 'in.srain.cube:ultra-ptr:1.0.11' + implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.44' + + //banner implementation 'com.youth.banner:banner:1.4.10' + implementation 'com.jakewharton.timber:timber:4.7.1' + + implementation 'net.danlew:android.joda:2.9.9.4' + implementation 'com.afollestad.material-dialogs:core:0.9.4.7' implementation 'com.tencent.sonic:sdk:3.1.0' implementation 'com.hyman:flowlayout-lib:1.1.2' diff --git a/app/src/main/java/com/leeeyou/factory/ServiceFactory.kt b/app/src/main/java/com/leeeyou/factory/ServiceFactory.kt deleted file mode 100644 index ced94cc..0000000 --- a/app/src/main/java/com/leeeyou/factory/ServiceFactory.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.leeeyou.factory - -import retrofit.GsonConverterFactory -import retrofit.Retrofit -import retrofit.RxJavaCallAdapterFactory - -/** - * ClassName: ServiceFactory - * Description: The factory class mainly offers two kinds of Retrofit services, Rx mode and normal mode - * - * Author: leeeyou - * Date: 2018/4/24 15:11 - */ -class ServiceFactory { - companion object { - fun createRxRetrofitService(clazz: Class, endPoint: String): T { - return Retrofit - .Builder() - .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) - .addConverterFactory(GsonConverterFactory.create()) - .baseUrl(endPoint) - .build() - .create(clazz) - } - - fun createRetrofitService(clazz: Class, endPoint: String): T { - return Retrofit - .Builder() - .addConverterFactory(GsonConverterFactory.create()) - .baseUrl(endPoint) - .build() - .create(clazz) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/service/ServiceFactory.kt b/app/src/main/java/com/leeeyou/service/ServiceFactory.kt new file mode 100644 index 0000000..c569f25 --- /dev/null +++ b/app/src/main/java/com/leeeyou/service/ServiceFactory.kt @@ -0,0 +1,63 @@ +package com.leeeyou.service + +import android.os.Environment +import com.leeeyou.service.converter.MyGsonConverterFactory +import okhttp3.Cache +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import retrofit2.Retrofit +import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory +import retrofit2.converter.gson.GsonConverterFactory +import timber.log.Timber +import java.io.File +import java.util.concurrent.TimeUnit + +/** + * ClassName: ServiceFactory + * Description: The factory class mainly offers two kinds of Retrofit services, Rx mode and normal mode + * + * Author: leeeyou + * Date: 2018/4/24 15:11 + */ +class ServiceFactory { + companion object { + private const val DEFAULT_TIMEOUT: Long = 10 + + private val loggingInterceptor: HttpLoggingInterceptor = HttpLoggingInterceptor(HttpLoggingInterceptor.Logger { + Timber.tag("HttpLogging\$ Start") + Timber.d("┌────────────────────────────────────────────────────────────────────") + Timber.tag("HttpLogging\$Result") + Timber.d("| %s", it) + Timber.tag("HttpLogging\$TheEnd") + Timber.d("└────────────────────────────────────────────────────────────────────") + }) + + private fun getOkHttpClient(): OkHttpClient { + loggingInterceptor.level = HttpLoggingInterceptor.Level.BASIC + val builder = OkHttpClient.Builder() + builder.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) + builder.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) + builder.addInterceptor(loggingInterceptor) + val httpCacheDirectory = File(Environment.getExternalStorageDirectory(), "RsKotlin") + builder.cache(Cache(httpCacheDirectory, 10 * 1024 * 1024)) + return builder.build() + } + + fun createRxRetrofitService(clazz: Class, endPoint: String): T { + val retrofit = Retrofit.Builder().baseUrl(endPoint).client(getOkHttpClient()) + .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) + .addConverterFactory(MyGsonConverterFactory.create()) + .build() + return retrofit.create(clazz) + } + + fun createRetrofitService(clazz: Class, endPoint: String): T { + return Retrofit + .Builder() + .addConverterFactory(GsonConverterFactory.create()) + .baseUrl(endPoint) + .build() + .create(clazz) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/service/converter/MyGsonConverter.java b/app/src/main/java/com/leeeyou/service/converter/MyGsonConverter.java new file mode 100644 index 0000000..5c592a4 --- /dev/null +++ b/app/src/main/java/com/leeeyou/service/converter/MyGsonConverter.java @@ -0,0 +1,68 @@ +package com.leeeyou.service.converter; + +import android.support.annotation.NonNull; +import android.text.TextUtils; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.leeeyou.service.entity.HttpErrorResponseEntity; +import com.leeeyou.service.entity.HttpResultEntity; +import com.leeeyou.service.exception.HttpResultException; + +import java.io.IOException; +import java.lang.reflect.Type; + +import okhttp3.ResponseBody; +import retrofit2.Converter; +import timber.log.Timber; + +public class MyGsonConverter implements Converter { + private final Gson gson; + private final Type type; + + public MyGsonConverter(Gson gson, Type type) { + this.gson = gson; + this.type = type; + } + + @Override + public T convert(@NonNull ResponseBody responseBody) throws IOException { + String responseStr = responseBody.string(); + Timber.d("The responseStr is %s ", responseStr); + if (TextUtils.isEmpty(responseStr)) { + HttpErrorResponseEntity errorResponse = new HttpErrorResponseEntity(-200, "The result of the request is returned as null"); + HttpResultException resultException = new HttpResultException(errorResponse.getErrorCode(), errorResponse.getErrorMsg()); + Timber.e("this ResultException msg is %s", "request result is null"); + throw resultException; + } + + HttpResultEntity httpResult; + try { + httpResult = gson.fromJson(responseStr, HttpResultEntity.class); + } catch (JsonSyntaxException e) { + HttpResultException resultException = new HttpResultException(-201, "Json conversion exception"); + Timber.e("this JsonSyntaxException msg is %s", e.getLocalizedMessage()); + throw resultException; + } + + if (httpResult.getErrorCode() == 0) { + try { + return gson.fromJson(responseStr, type); + } catch (JsonSyntaxException e) { + Timber.e("this JsonSyntaxException msg is %s", e.getMessage()); + HttpErrorResponseEntity errorResponse = new HttpErrorResponseEntity(-202, "Json conversion exception"); + throw new HttpResultException(errorResponse.getErrorCode(), errorResponse.getErrorMsg()); + } + } else { + try { + Timber.e("this ResultException msg is %s", "json convert fail"); + HttpErrorResponseEntity errorResponse = gson.fromJson(responseStr, HttpErrorResponseEntity.class); + throw new HttpResultException(errorResponse.getErrorCode(), errorResponse.getErrorMsg()); + } catch (JsonSyntaxException e) { + Timber.e("this JsonSyntaxException msg is %s", e.getMessage()); + HttpErrorResponseEntity errorResponse = new HttpErrorResponseEntity(-203, "Json conversion exception"); + throw new HttpResultException(errorResponse.getErrorCode(), errorResponse.getErrorMsg()); + } + } + } +} diff --git a/app/src/main/java/com/leeeyou/service/converter/MyGsonConverterFactory.java b/app/src/main/java/com/leeeyou/service/converter/MyGsonConverterFactory.java new file mode 100644 index 0000000..efff864 --- /dev/null +++ b/app/src/main/java/com/leeeyou/service/converter/MyGsonConverterFactory.java @@ -0,0 +1,38 @@ +package com.leeeyou.service.converter; + +import com.google.gson.Gson; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +import okhttp3.RequestBody; +import okhttp3.ResponseBody; +import retrofit2.Converter; +import retrofit2.Retrofit; + +public class MyGsonConverterFactory extends Converter.Factory { + private final Gson gson; + + private MyGsonConverterFactory(Gson gson) { + if (gson == null) throw new NullPointerException("gson == null"); + this.gson = gson; + } + + public static MyGsonConverterFactory create() { + return create(new Gson()); + } + + public static MyGsonConverterFactory create(Gson gson) { + return new MyGsonConverterFactory(gson); + } + + @Override + public Converter responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { + return new MyGsonConverter<>(gson, type); + } + + @Override + public Converter requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { + return new MyGsonConverter<>(gson, type); + } +} diff --git a/app/src/main/java/com/leeeyou/service/entity/BaseEntity.java b/app/src/main/java/com/leeeyou/service/entity/BaseEntity.java new file mode 100644 index 0000000..3843288 --- /dev/null +++ b/app/src/main/java/com/leeeyou/service/entity/BaseEntity.java @@ -0,0 +1,31 @@ +package com.leeeyou.service.entity; + +public class BaseEntity { + private int errorCode; + private String errorMsg; + private T data; + + public int getErrorCode() { + return errorCode; + } + + public void setErrorCode(int errorCode) { + this.errorCode = errorCode; + } + + public String getErrorMsg() { + return errorMsg; + } + + public void setErrorMsg(String errorMsg) { + this.errorMsg = errorMsg; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } +} diff --git a/app/src/main/java/com/leeeyou/service/entity/HttpErrorResponseEntity.java b/app/src/main/java/com/leeeyou/service/entity/HttpErrorResponseEntity.java new file mode 100644 index 0000000..6f6e3dc --- /dev/null +++ b/app/src/main/java/com/leeeyou/service/entity/HttpErrorResponseEntity.java @@ -0,0 +1,27 @@ +package com.leeeyou.service.entity; + +public class HttpErrorResponseEntity { + private int errorCode; + private String errorMsg; + + public HttpErrorResponseEntity(int errorCode, String errorMsg) { + this.errorCode = errorCode; + this.errorMsg = errorMsg; + } + + public int getErrorCode() { + return errorCode; + } + + public void setErrorCode(int errorCode) { + this.errorCode = errorCode; + } + + public String getErrorMsg() { + return errorMsg; + } + + public void setErrorMsg(String errorMsg) { + this.errorMsg = errorMsg; + } +} diff --git a/app/src/main/java/com/leeeyou/service/entity/HttpResultEntity.java b/app/src/main/java/com/leeeyou/service/entity/HttpResultEntity.java new file mode 100644 index 0000000..a7ac52b --- /dev/null +++ b/app/src/main/java/com/leeeyou/service/entity/HttpResultEntity.java @@ -0,0 +1,7 @@ +package com.leeeyou.service.entity; + +public class HttpResultEntity extends BaseEntity { + public boolean isSuccess() { + return getErrorCode() == 0; + } +} diff --git a/app/src/main/java/com/leeeyou/service/exception/HttpResultException.java b/app/src/main/java/com/leeeyou/service/exception/HttpResultException.java new file mode 100644 index 0000000..8d21e49 --- /dev/null +++ b/app/src/main/java/com/leeeyou/service/exception/HttpResultException.java @@ -0,0 +1,21 @@ +package com.leeeyou.service.exception; + +import java.io.IOException; + +public class HttpResultException extends IOException { + private int code; + private String msg; + + public HttpResultException(int code, String msg) { + this.code = code; + this.msg = msg; + } + + public int getCode() { + return code; + } + + public String getMsg() { + return msg; + } +} diff --git a/app/src/main/java/com/leeeyou/service/subscriber/DefaultHttpResultSubscriber.java b/app/src/main/java/com/leeeyou/service/subscriber/DefaultHttpResultSubscriber.java new file mode 100644 index 0000000..42d260d --- /dev/null +++ b/app/src/main/java/com/leeeyou/service/subscriber/DefaultHttpResultSubscriber.java @@ -0,0 +1,15 @@ +package com.leeeyou.service.subscriber; + +import timber.log.Timber; + +public abstract class DefaultHttpResultSubscriber extends HttpResultSubscriber { + @Override + public void _onError(int status, String msg) { + + } + + @Override + public void onCompleted() { + Timber.d(" --> onCompleted"); + } +} diff --git a/app/src/main/java/com/leeeyou/service/subscriber/HttpResultSubscriber.java b/app/src/main/java/com/leeeyou/service/subscriber/HttpResultSubscriber.java new file mode 100644 index 0000000..1d179c6 --- /dev/null +++ b/app/src/main/java/com/leeeyou/service/subscriber/HttpResultSubscriber.java @@ -0,0 +1,51 @@ +package com.leeeyou.service.subscriber; + +import com.leeeyou.service.entity.HttpResultEntity; +import com.leeeyou.service.exception.HttpResultException; + +import java.net.ConnectException; +import java.net.SocketTimeoutException; +import java.util.concurrent.TimeoutException; + +import rx.Subscriber; +import timber.log.Timber; + +public abstract class HttpResultSubscriber extends Subscriber> { + @Override + public void onCompleted() { + + } + + @Override + public void onError(Throwable e) { + int code = -1000; + String msg = null; + if (e instanceof ConnectException + || e instanceof SocketTimeoutException + || e instanceof TimeoutException) { + code = -9999; + msg = "network anomaly"; + + } else if (e instanceof HttpResultException) { + HttpResultException resultException = (HttpResultException) e; + code = resultException.getCode(); + msg = resultException.getMsg(); + } + Timber.e("Request to enter the onError of HttpResultSubscriber , status is %s , msg is %s", code, msg); + _onError(code, msg); + onCompleted(); + } + + @Override + public void onNext(HttpResultEntity httpResult) { + if (httpResult.isSuccess()) { + onSuccess(httpResult.getData()); + } else { + _onError(httpResult.getErrorCode(), ""); + } + } + + public abstract void onSuccess(T t); + + public abstract void _onError(int status, String msg); +} diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt index a84a53e..24b5abb 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt @@ -14,18 +14,17 @@ import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.BaseViewHolder import com.leeeyou.R import com.leeeyou.manager.BaseFragment +import com.leeeyou.service.subscriber.DefaultHttpResultSubscriber import com.leeeyou.util.inflate import com.leeeyou.util.startBrowserActivity import com.leeeyou.wanandroid.model.bean.Banner import com.leeeyou.wanandroid.model.bean.RecommendItem import com.leeeyou.wanandroid.model.bean.RecommendList -import com.leeeyou.wanandroid.model.bean.ResponseBanner import com.leeeyou.wanandroid.model.fetchBannerList import com.leeeyou.wanandroid.model.fetchRecommendList import com.youth.banner.Transformer import com.youth.banner.loader.ImageLoader import kotlinx.android.synthetic.main.fragment_wan_android_recommend.* -import rx.Subscriber import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers import timber.log.Timber @@ -39,7 +38,7 @@ import timber.log.Timber * Date: 2017/4/24 13:46 */ class WanAndroidRecommendFragment : BaseFragment() { - lateinit var mLinearLayoutManager: LinearLayoutManager + private lateinit var mLinearLayoutManager: LinearLayoutManager var mPageIndex: Int = 0 private lateinit var mRecommendAdapter: BaseQuickAdapter private var mPageCount: Int = 0 @@ -129,32 +128,23 @@ class WanAndroidRecommendFragment : BaseFragment() { } private fun fetchRecommendListFromServer(pageIndex: Int) { - fetchRecommendList(pageIndex) - .subscribeOn(Schedulers.newThread()) - .observeOn(AndroidSchedulers.mainThread()) - .doOnNext { - Timber.d("fetchRecommendListFromServer doOnNext") - - ptrFrameRecommend.refreshComplete() - - it.takeIf { response -> - response.errorCode >= 0 - }?.also { response -> - Timber.d(response.data.toString()) - renderRecommendList(pageIndex, response.data) - } ?: IllegalArgumentException("fetchRecommendListFromServer接口返回异常") - } - .doOnError { - ptrFrameRecommend.refreshComplete() - Timber.e(it, "fetchRecommendListFromServer doOnError") - } - .doOnCompleted { - Timber.d("fetchRecommendListFromServer doOnCompleted") - if (mPageIndex > 0) { - mRecommendAdapter.loadMoreComplete() + fetchRecommendList(pageIndex).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : DefaultHttpResultSubscriber() { + override fun onSuccess(t: RecommendList?) { + t?.let { + renderRecommendList(pageIndex, it) + if (mPageIndex == 0 && it.datas.size < it.size) { + mRecommendAdapter.loadMoreEnd() + } else if (mPageIndex > 0) { + mRecommendAdapter.loadMoreComplete() + } + } } - } - .subscribe() + + override fun onCompleted() { + ptrFrameRecommend.refreshComplete() + } + }) } private fun renderRecommendList(witchPage: Int, data: RecommendList) { @@ -167,26 +157,10 @@ class WanAndroidRecommendFragment : BaseFragment() { } private fun fetchBannerListFromServer() { - fetchBannerList() - .subscribeOn(Schedulers.newThread()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(object : Subscriber() { - override fun onNext(responseBanner: ResponseBanner) { - Timber.d("fetchBannerList onNext , result is %s ", responseBanner.toString()) - - responseBanner.takeIf { - it.errorCode >= 0 - }?.also { - renderBanner(it.data) - } ?: onError(IllegalArgumentException("Banner接口返回异常")) - } - - override fun onCompleted() { - Timber.d("fetchBannerList onCompleted") - } - - override fun onError(e: Throwable?) { - Timber.d(e, "fetchBannerList onError") + fetchBannerList().subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : DefaultHttpResultSubscriber>() { + override fun onSuccess(t: List?) { + t?.let { renderBanner(it) } } }) } @@ -214,4 +188,4 @@ class WanAndroidRecommendFragment : BaseFragment() { banner.stopAutoPlay() } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt index 1bc2eb5..7a1357b 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt @@ -16,10 +16,10 @@ import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.BaseViewHolder import com.leeeyou.R import com.leeeyou.manager.BaseFragment +import com.leeeyou.service.subscriber.DefaultHttpResultSubscriber import com.leeeyou.util.inflate import com.leeeyou.util.startBrowserActivity import com.leeeyou.wanandroid.model.bean.RecommendItem -import com.leeeyou.wanandroid.model.bean.ResponseSystemTag import com.leeeyou.wanandroid.model.bean.SystemTag import com.leeeyou.wanandroid.model.bean.SystemTagArticleList import com.leeeyou.wanandroid.model.fetchSystemTagArticleList @@ -104,16 +104,14 @@ class WanAndroidSystemFragment : BaseFragment() { if (sv_system_tag_all.visibility == View.VISIBLE) hiddenDetailTagAnimation() else showDetailTagAnimation() } - fetchSystemTagList() - .subscribeOn(Schedulers.newThread()) - .observeOn(AndroidSchedulers.mainThread()) - .doOnNext { - it.takeIf { response -> - response.errorCode >= 0 - }?.also { response -> - renderSystemTag(response) - } ?: IllegalArgumentException("fetchSystemTagList接口返回异常") - }.subscribe() + fetchSystemTagList().subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : DefaultHttpResultSubscriber>() { + override fun onSuccess(t: List?) { + t?.let { + renderSystemTag(it) + } + } + }) } private fun initRecyclerView() { @@ -167,11 +165,10 @@ class WanAndroidSystemFragment : BaseFragment() { private fun recyclerViewFirstItemCanVisible() = mLinearLayoutManager.findFirstCompletelyVisibleItemPosition() <= 0 - private fun renderSystemTag(response: ResponseSystemTag) { + private fun renderSystemTag(parentTagList: List) { mSelectedParentTagPosition = 0 mSelectedChildTagPosition = 0 - val parentTagList = response.data val childTagList = parentTagList[mSelectedParentTagPosition].children mSelectedParentTagId = parentTagList[mSelectedParentTagPosition].id @@ -179,17 +176,17 @@ class WanAndroidSystemFragment : BaseFragment() { renderParentTag(parentTagList) renderChildTag(childTagList) - processClickEvent(response) + processClickEvent(parentTagList) } - private fun processClickEvent(response: ResponseSystemTag) { + private fun processClickEvent(parentTagList: List) { system_tag_parent.setOnTagClickListener { _, position, parent -> mSelectedParentTagPosition = position mSelectedChildTagPosition = 0 - mSelectedParentTagId = response.data[mSelectedParentTagPosition].id - mSelectedChildTagId = response.data[mSelectedParentTagPosition].children[mSelectedChildTagPosition].id + mSelectedParentTagId = parentTagList[mSelectedParentTagPosition].id + mSelectedChildTagId = parentTagList[mSelectedParentTagPosition].children[mSelectedChildTagPosition].id - renderChildTag(response.data[mSelectedParentTagPosition].children) + renderChildTag(parentTagList[mSelectedParentTagPosition].children) for (index in 0..parent.childCount) { parent.getChildAt(index)?.isClickable = mSelectedParentTagPosition != index } @@ -198,7 +195,7 @@ class WanAndroidSystemFragment : BaseFragment() { system_tag_child.setOnTagClickListener { _, position, parent -> mSelectedChildTagPosition = position - mSelectedChildTagId = response.data[mSelectedParentTagPosition].children[mSelectedChildTagPosition].id + mSelectedChildTagId = parentTagList[mSelectedParentTagPosition].children[mSelectedChildTagPosition].id for (index in 0..parent.childCount) { parent.getChildAt(index)?.isClickable = mSelectedChildTagPosition != index } @@ -211,25 +208,26 @@ class WanAndroidSystemFragment : BaseFragment() { private fun fetchSystemTagArticleList(pageIndex: Int) { Timber.d("fetchSystemTagArticleList , parent id is %s , child id is %s", mSelectedParentTagId, mSelectedChildTagId) - fetchSystemTagArticleList(pageIndex, mSelectedChildTagId) - .subscribeOn(Schedulers.newThread()) - .observeOn(AndroidSchedulers.mainThread()) - .doOnNext { - ptrFrameSystemTag?.refreshComplete() - - it.takeIf { response -> - response.errorCode >= 0 - }?.also { response -> - Timber.d(it.data.toString()) - renderSystemTagArticleList(pageIndex, response.data) - - mSystemTagArticleAdapter.loadMoreComplete() - if (mPageIndex == 0 && response.data.datas.size <= response.data.size) { - mSystemTagArticleAdapter.loadMoreEnd() + fetchSystemTagArticleList(pageIndex, mSelectedChildTagId).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : DefaultHttpResultSubscriber() { + override fun onSuccess(t: SystemTagArticleList?) { + t?.let { + renderSystemTagArticleList(pageIndex, t) + if (mPageIndex == 0 && t.datas.size < t.size) { + mSystemTagArticleAdapter.loadMoreEnd() + } else if (mPageIndex > 0) { + mSystemTagArticleAdapter.loadMoreComplete() + } } - } ?: IllegalArgumentException("fetchSystemTagArticleList接口返回异常") - } - .subscribe() + } + + override fun onCompleted() { + ptrFrameSystemTag.refreshComplete() + if (mPageIndex > 0) { + mSystemTagArticleAdapter.loadMoreComplete() + } + } + }) } private fun renderSystemTagArticleList(pageIndex: Int, data: SystemTagArticleList) { @@ -241,10 +239,6 @@ class WanAndroidSystemFragment : BaseFragment() { } } - private fun isFullScreen(llm: LinearLayoutManager): Boolean { - return llm.findLastCompletelyVisibleItemPosition() + 1 != mSystemTagArticleAdapter.itemCount || llm.findFirstCompletelyVisibleItemPosition() != 0 - } - private fun renderParentTag(parentTagList: List) { system_tag_parent.adapter = object : TagAdapter(parentTagList) { override fun getView(parent: FlowLayout?, position: Int, systemTag: SystemTag?): View { diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt b/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt index 42bb204..73f8ce5 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt @@ -1,34 +1,35 @@ package com.leeeyou.wanandroid.model -import com.leeeyou.factory.ServiceFactory -import com.leeeyou.wanandroid.model.bean.ResponseBanner -import com.leeeyou.wanandroid.model.bean.ResponseRecommendList -import com.leeeyou.wanandroid.model.bean.ResponseSystemTag -import com.leeeyou.wanandroid.model.bean.ResponseSystemTagArticleList +import com.leeeyou.service.ServiceFactory +import com.leeeyou.service.entity.HttpResultEntity +import com.leeeyou.wanandroid.model.bean.Banner +import com.leeeyou.wanandroid.model.bean.RecommendList +import com.leeeyou.wanandroid.model.bean.SystemTag +import com.leeeyou.wanandroid.model.bean.SystemTagArticleList import com.leeeyou.wanandroid.service.WanAndroidService import rx.Observable private const val endPoint = "http://www.wanandroid.com/" -fun fetchBannerList(): Observable { +fun fetchBannerList(): Observable>> { return ServiceFactory .createRxRetrofitService(WanAndroidService::class.java, endPoint) .getBannerList() } -fun fetchRecommendList(index: Int = 0): Observable { +fun fetchRecommendList(index: Int = 0): Observable> { return ServiceFactory .createRxRetrofitService(WanAndroidService::class.java, endPoint) .getRecommendList(index) } -fun fetchSystemTagList(): Observable { +fun fetchSystemTagList(): Observable>> { return ServiceFactory .createRxRetrofitService(WanAndroidService::class.java, endPoint) .getSystemTagList() } -fun fetchSystemTagArticleList(pageIndex: Int, cid: Int): Observable { +fun fetchSystemTagArticleList(pageIndex: Int, cid: Int): Observable> { return ServiceFactory .createRxRetrofitService(WanAndroidService::class.java, endPoint) .getSystemTagArticleList(pageIndex, cid) diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseBanner.kt b/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseBanner.kt deleted file mode 100644 index 37163d7..0000000 --- a/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseBanner.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.leeeyou.wanandroid.model.bean - -data class ResponseBanner(val data: List, - val errorCode: Int = 0, - var errorMsg: String = "") \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseRecommendList.kt b/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseRecommendList.kt deleted file mode 100644 index fbda5b1..0000000 --- a/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseRecommendList.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.leeeyou.wanandroid.model.bean - -data class ResponseRecommendList(val data: RecommendList, - val errorCode: Int = 0, - var errorMsg: String = "") \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt b/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt index 5c06f7b..4d9a78c 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt @@ -1,25 +1,25 @@ package com.leeeyou.wanandroid.service -import com.leeeyou.wanandroid.model.bean.ResponseBanner -import com.leeeyou.wanandroid.model.bean.ResponseRecommendList -import com.leeeyou.wanandroid.model.bean.ResponseSystemTag -import com.leeeyou.wanandroid.model.bean.ResponseSystemTagArticleList -import retrofit.http.GET -import retrofit.http.Path -import retrofit.http.Query +import com.leeeyou.service.entity.HttpResultEntity +import com.leeeyou.wanandroid.model.bean.Banner +import com.leeeyou.wanandroid.model.bean.RecommendList +import com.leeeyou.wanandroid.model.bean.SystemTag +import com.leeeyou.wanandroid.model.bean.SystemTagArticleList +import retrofit2.http.GET +import retrofit2.http.Path +import retrofit2.http.Query import rx.Observable interface WanAndroidService { - @GET("banner/json") - fun getBannerList(): Observable + fun getBannerList(): Observable>> @GET("article/list/{index}/json") - fun getRecommendList(@Path("index") index: Int): Observable + fun getRecommendList(@Path("index") index: Int): Observable> @GET("tree/json") - fun getSystemTagList(): Observable + fun getSystemTagList(): Observable>> @GET("article/list/{pageIndex}/json") - fun getSystemTagArticleList(@Path("pageIndex") pageIndex: Int, @Query("cid") cid: Int): Observable + fun getSystemTagArticleList(@Path("pageIndex") pageIndex: Int, @Query("cid") cid: Int): Observable> } \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/zhihudaily/model/ZhiHuDailyRepository.kt b/app/src/main/java/com/leeeyou/zhihudaily/model/ZhiHuDailyRepository.kt index 1934166..e66588b 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/model/ZhiHuDailyRepository.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/model/ZhiHuDailyRepository.kt @@ -1,6 +1,6 @@ package com.leeeyou.zhihudaily.model -import com.leeeyou.factory.ServiceFactory +import com.leeeyou.service.ServiceFactory import com.leeeyou.zhihudaily.model.bean.ZhiHuDaily import com.leeeyou.zhihudaily.model.bean.ZhiHuDailyDetail import com.leeeyou.zhihudaily.service.ZhiHuDailyService diff --git a/app/src/main/java/com/leeeyou/zhihudaily/service/ZhiHuDailyService.kt b/app/src/main/java/com/leeeyou/zhihudaily/service/ZhiHuDailyService.kt index ec50efa..4c1b7b5 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/service/ZhiHuDailyService.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/service/ZhiHuDailyService.kt @@ -2,8 +2,8 @@ package com.leeeyou.zhihudaily.service import com.leeeyou.zhihudaily.model.bean.ZhiHuDaily import com.leeeyou.zhihudaily.model.bean.ZhiHuDailyDetail -import retrofit.http.GET -import retrofit.http.Path +import retrofit2.http.GET +import retrofit2.http.Path import rx.Observable /** From 79c8f028ad9b3ccaf5a4a93a93cac6fcba843b20 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Mon, 7 Jan 2019 18:42:12 +0800 Subject: [PATCH 068/150] 1. Refactor ServiceFactory, add custom GsonConvert, add custom OkHttpClient, add HttpLoggingInterceptor 2. Solve the problem of json conversion failure --- .../wanandroid/WanAndroidSystemFragment.kt | 95 ++++++++++--------- 1 file changed, 50 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt index 7a1357b..97d0d47 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt @@ -54,56 +54,15 @@ class WanAndroidSystemFragment : BaseFragment() { return container?.inflate(R.layout.fragment_wan_android_system) } - private fun showDetailTagAnimation() { - val rotateAnimation = RotateAnimation(0f, 90f, (iv_arrow_right.width / 2).toFloat(), (iv_arrow_right.height / 2).toFloat()) - rotateAnimation.duration = 100 - rotateAnimation.fillAfter = true - rotateAnimation.interpolator = AccelerateInterpolator() - iv_arrow_right.startAnimation(rotateAnimation) - - rotateAnimation.setAnimationListener(object : Animation.AnimationListener { - override fun onAnimationRepeat(animation: Animation?) { - } - - override fun onAnimationEnd(animation: Animation?) { - sv_system_tag_all.visibility = View.VISIBLE - } - - override fun onAnimationStart(animation: Animation?) { - } - }) - } - - private fun hiddenDetailTagAnimation() { - val rotateAnimation = RotateAnimation(90f, 0f, (iv_arrow_right.width / 2).toFloat(), (iv_arrow_right.height / 2).toFloat()) - rotateAnimation.duration = 100 - rotateAnimation.fillAfter = true - rotateAnimation.interpolator = AccelerateInterpolator() - iv_arrow_right.startAnimation(rotateAnimation) - - rotateAnimation.setAnimationListener(object : Animation.AnimationListener { - override fun onAnimationRepeat(animation: Animation?) { - } - - override fun onAnimationEnd(animation: Animation?) { - sv_system_tag_all.visibility = View.GONE - } - - override fun onAnimationStart(animation: Animation?) { - } - }) - } - override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) - initRecyclerView() initPtrFrame() + initSystemTagUI() + fetchSystemTagListFromServer() + } - rl_system_tag_combine.setOnClickListener { - if (sv_system_tag_all.visibility == View.VISIBLE) hiddenDetailTagAnimation() else showDetailTagAnimation() - } - + private fun fetchSystemTagListFromServer() { fetchSystemTagList().subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) .subscribe(object : DefaultHttpResultSubscriber>() { override fun onSuccess(t: List?) { @@ -114,6 +73,12 @@ class WanAndroidSystemFragment : BaseFragment() { }) } + private fun initSystemTagUI() { + rl_system_tag_combine.setOnClickListener { + if (sv_system_tag_all.visibility == View.VISIBLE) hiddenDetailTagAnimation() else showDetailTagAnimation() + } + } + private fun initRecyclerView() { mLinearLayoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) mSystemTagArticleAdapter = object : BaseQuickAdapter(R.layout.item_recommend, null) { @@ -206,6 +171,46 @@ class WanAndroidSystemFragment : BaseFragment() { } } + private fun showDetailTagAnimation() { + val rotateAnimation = RotateAnimation(0f, 90f, (iv_arrow_right.width / 2).toFloat(), (iv_arrow_right.height / 2).toFloat()) + rotateAnimation.duration = 100 + rotateAnimation.fillAfter = true + rotateAnimation.interpolator = AccelerateInterpolator() + iv_arrow_right.startAnimation(rotateAnimation) + + rotateAnimation.setAnimationListener(object : Animation.AnimationListener { + override fun onAnimationRepeat(animation: Animation?) { + } + + override fun onAnimationEnd(animation: Animation?) { + sv_system_tag_all.visibility = View.VISIBLE + } + + override fun onAnimationStart(animation: Animation?) { + } + }) + } + + private fun hiddenDetailTagAnimation() { + val rotateAnimation = RotateAnimation(90f, 0f, (iv_arrow_right.width / 2).toFloat(), (iv_arrow_right.height / 2).toFloat()) + rotateAnimation.duration = 100 + rotateAnimation.fillAfter = true + rotateAnimation.interpolator = AccelerateInterpolator() + iv_arrow_right.startAnimation(rotateAnimation) + + rotateAnimation.setAnimationListener(object : Animation.AnimationListener { + override fun onAnimationRepeat(animation: Animation?) { + } + + override fun onAnimationEnd(animation: Animation?) { + sv_system_tag_all.visibility = View.GONE + } + + override fun onAnimationStart(animation: Animation?) { + } + }) + } + private fun fetchSystemTagArticleList(pageIndex: Int) { Timber.d("fetchSystemTagArticleList , parent id is %s , child id is %s", mSelectedParentTagId, mSelectedChildTagId) fetchSystemTagArticleList(pageIndex, mSelectedChildTagId).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) From a305500b35fdd28a2bcf37e47c7b20420bdc11e3 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Mon, 7 Jan 2019 18:50:05 +0800 Subject: [PATCH 069/150] 1. Refactor ServiceFactory, add custom GsonConvert, add custom OkHttpClient, add HttpLoggingInterceptor 2. Solve the problem of json conversion failure 3. Kotlin rewriting --- .../leeeyou/service/entity/BaseEntity.java | 31 ----------- .../com/leeeyou/service/entity/BaseEntity.kt | 7 +++ .../entity/HttpErrorResponseEntity.java | 27 ---------- .../service/entity/HttpErrorResponseEntity.kt | 3 ++ .../service/entity/HttpResultEntity.java | 7 --- .../service/entity/HttpResultEntity.kt | 6 +++ .../exception/HttpResultException.java | 21 -------- .../service/exception/HttpResultException.kt | 5 ++ .../DefaultHttpResultSubscriber.java | 15 ------ .../subscriber/DefaultHttpResultSubscriber.kt | 13 +++++ .../subscriber/HttpResultSubscriber.java | 51 ------------------- .../subscriber/HttpResultSubscriber.kt | 43 ++++++++++++++++ 12 files changed, 77 insertions(+), 152 deletions(-) delete mode 100644 app/src/main/java/com/leeeyou/service/entity/BaseEntity.java create mode 100644 app/src/main/java/com/leeeyou/service/entity/BaseEntity.kt delete mode 100644 app/src/main/java/com/leeeyou/service/entity/HttpErrorResponseEntity.java create mode 100644 app/src/main/java/com/leeeyou/service/entity/HttpErrorResponseEntity.kt delete mode 100644 app/src/main/java/com/leeeyou/service/entity/HttpResultEntity.java create mode 100644 app/src/main/java/com/leeeyou/service/entity/HttpResultEntity.kt delete mode 100644 app/src/main/java/com/leeeyou/service/exception/HttpResultException.java create mode 100644 app/src/main/java/com/leeeyou/service/exception/HttpResultException.kt delete mode 100644 app/src/main/java/com/leeeyou/service/subscriber/DefaultHttpResultSubscriber.java create mode 100644 app/src/main/java/com/leeeyou/service/subscriber/DefaultHttpResultSubscriber.kt delete mode 100644 app/src/main/java/com/leeeyou/service/subscriber/HttpResultSubscriber.java create mode 100644 app/src/main/java/com/leeeyou/service/subscriber/HttpResultSubscriber.kt diff --git a/app/src/main/java/com/leeeyou/service/entity/BaseEntity.java b/app/src/main/java/com/leeeyou/service/entity/BaseEntity.java deleted file mode 100644 index 3843288..0000000 --- a/app/src/main/java/com/leeeyou/service/entity/BaseEntity.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.leeeyou.service.entity; - -public class BaseEntity { - private int errorCode; - private String errorMsg; - private T data; - - public int getErrorCode() { - return errorCode; - } - - public void setErrorCode(int errorCode) { - this.errorCode = errorCode; - } - - public String getErrorMsg() { - return errorMsg; - } - - public void setErrorMsg(String errorMsg) { - this.errorMsg = errorMsg; - } - - public T getData() { - return data; - } - - public void setData(T data) { - this.data = data; - } -} diff --git a/app/src/main/java/com/leeeyou/service/entity/BaseEntity.kt b/app/src/main/java/com/leeeyou/service/entity/BaseEntity.kt new file mode 100644 index 0000000..064e5a3 --- /dev/null +++ b/app/src/main/java/com/leeeyou/service/entity/BaseEntity.kt @@ -0,0 +1,7 @@ +package com.leeeyou.service.entity + +open class BaseEntity { + var errorCode: Int = 0 + var errorMsg: String? = null + var data: T? = null +} diff --git a/app/src/main/java/com/leeeyou/service/entity/HttpErrorResponseEntity.java b/app/src/main/java/com/leeeyou/service/entity/HttpErrorResponseEntity.java deleted file mode 100644 index 6f6e3dc..0000000 --- a/app/src/main/java/com/leeeyou/service/entity/HttpErrorResponseEntity.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.leeeyou.service.entity; - -public class HttpErrorResponseEntity { - private int errorCode; - private String errorMsg; - - public HttpErrorResponseEntity(int errorCode, String errorMsg) { - this.errorCode = errorCode; - this.errorMsg = errorMsg; - } - - public int getErrorCode() { - return errorCode; - } - - public void setErrorCode(int errorCode) { - this.errorCode = errorCode; - } - - public String getErrorMsg() { - return errorMsg; - } - - public void setErrorMsg(String errorMsg) { - this.errorMsg = errorMsg; - } -} diff --git a/app/src/main/java/com/leeeyou/service/entity/HttpErrorResponseEntity.kt b/app/src/main/java/com/leeeyou/service/entity/HttpErrorResponseEntity.kt new file mode 100644 index 0000000..7522b07 --- /dev/null +++ b/app/src/main/java/com/leeeyou/service/entity/HttpErrorResponseEntity.kt @@ -0,0 +1,3 @@ +package com.leeeyou.service.entity + +class HttpErrorResponseEntity(var errorCode: Int, var errorMsg: String?) diff --git a/app/src/main/java/com/leeeyou/service/entity/HttpResultEntity.java b/app/src/main/java/com/leeeyou/service/entity/HttpResultEntity.java deleted file mode 100644 index a7ac52b..0000000 --- a/app/src/main/java/com/leeeyou/service/entity/HttpResultEntity.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.leeeyou.service.entity; - -public class HttpResultEntity extends BaseEntity { - public boolean isSuccess() { - return getErrorCode() == 0; - } -} diff --git a/app/src/main/java/com/leeeyou/service/entity/HttpResultEntity.kt b/app/src/main/java/com/leeeyou/service/entity/HttpResultEntity.kt new file mode 100644 index 0000000..628e805 --- /dev/null +++ b/app/src/main/java/com/leeeyou/service/entity/HttpResultEntity.kt @@ -0,0 +1,6 @@ +package com.leeeyou.service.entity + +class HttpResultEntity : BaseEntity() { + val isSuccess: Boolean + get() = errorCode == 0 +} diff --git a/app/src/main/java/com/leeeyou/service/exception/HttpResultException.java b/app/src/main/java/com/leeeyou/service/exception/HttpResultException.java deleted file mode 100644 index 8d21e49..0000000 --- a/app/src/main/java/com/leeeyou/service/exception/HttpResultException.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.leeeyou.service.exception; - -import java.io.IOException; - -public class HttpResultException extends IOException { - private int code; - private String msg; - - public HttpResultException(int code, String msg) { - this.code = code; - this.msg = msg; - } - - public int getCode() { - return code; - } - - public String getMsg() { - return msg; - } -} diff --git a/app/src/main/java/com/leeeyou/service/exception/HttpResultException.kt b/app/src/main/java/com/leeeyou/service/exception/HttpResultException.kt new file mode 100644 index 0000000..6c7d13c --- /dev/null +++ b/app/src/main/java/com/leeeyou/service/exception/HttpResultException.kt @@ -0,0 +1,5 @@ +package com.leeeyou.service.exception + +import java.io.IOException + +class HttpResultException(val code: Int, val msg: String) : IOException() \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/service/subscriber/DefaultHttpResultSubscriber.java b/app/src/main/java/com/leeeyou/service/subscriber/DefaultHttpResultSubscriber.java deleted file mode 100644 index 42d260d..0000000 --- a/app/src/main/java/com/leeeyou/service/subscriber/DefaultHttpResultSubscriber.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.leeeyou.service.subscriber; - -import timber.log.Timber; - -public abstract class DefaultHttpResultSubscriber extends HttpResultSubscriber { - @Override - public void _onError(int status, String msg) { - - } - - @Override - public void onCompleted() { - Timber.d(" --> onCompleted"); - } -} diff --git a/app/src/main/java/com/leeeyou/service/subscriber/DefaultHttpResultSubscriber.kt b/app/src/main/java/com/leeeyou/service/subscriber/DefaultHttpResultSubscriber.kt new file mode 100644 index 0000000..933bab9 --- /dev/null +++ b/app/src/main/java/com/leeeyou/service/subscriber/DefaultHttpResultSubscriber.kt @@ -0,0 +1,13 @@ +package com.leeeyou.service.subscriber + +import timber.log.Timber + +abstract class DefaultHttpResultSubscriber : HttpResultSubscriber() { + override fun _onError(status: Int, msg: String?) { + + } + + override fun onCompleted() { + Timber.d(" --> onCompleted") + } +} diff --git a/app/src/main/java/com/leeeyou/service/subscriber/HttpResultSubscriber.java b/app/src/main/java/com/leeeyou/service/subscriber/HttpResultSubscriber.java deleted file mode 100644 index 1d179c6..0000000 --- a/app/src/main/java/com/leeeyou/service/subscriber/HttpResultSubscriber.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.leeeyou.service.subscriber; - -import com.leeeyou.service.entity.HttpResultEntity; -import com.leeeyou.service.exception.HttpResultException; - -import java.net.ConnectException; -import java.net.SocketTimeoutException; -import java.util.concurrent.TimeoutException; - -import rx.Subscriber; -import timber.log.Timber; - -public abstract class HttpResultSubscriber extends Subscriber> { - @Override - public void onCompleted() { - - } - - @Override - public void onError(Throwable e) { - int code = -1000; - String msg = null; - if (e instanceof ConnectException - || e instanceof SocketTimeoutException - || e instanceof TimeoutException) { - code = -9999; - msg = "network anomaly"; - - } else if (e instanceof HttpResultException) { - HttpResultException resultException = (HttpResultException) e; - code = resultException.getCode(); - msg = resultException.getMsg(); - } - Timber.e("Request to enter the onError of HttpResultSubscriber , status is %s , msg is %s", code, msg); - _onError(code, msg); - onCompleted(); - } - - @Override - public void onNext(HttpResultEntity httpResult) { - if (httpResult.isSuccess()) { - onSuccess(httpResult.getData()); - } else { - _onError(httpResult.getErrorCode(), ""); - } - } - - public abstract void onSuccess(T t); - - public abstract void _onError(int status, String msg); -} diff --git a/app/src/main/java/com/leeeyou/service/subscriber/HttpResultSubscriber.kt b/app/src/main/java/com/leeeyou/service/subscriber/HttpResultSubscriber.kt new file mode 100644 index 0000000..d8ca712 --- /dev/null +++ b/app/src/main/java/com/leeeyou/service/subscriber/HttpResultSubscriber.kt @@ -0,0 +1,43 @@ +package com.leeeyou.service.subscriber + +import com.leeeyou.service.entity.HttpResultEntity +import com.leeeyou.service.exception.HttpResultException +import rx.Subscriber +import timber.log.Timber +import java.net.ConnectException +import java.net.SocketTimeoutException +import java.util.concurrent.TimeoutException + +abstract class HttpResultSubscriber : Subscriber>() { + override fun onCompleted() { + + } + + override fun onError(e: Throwable) { + var code = -1000 + var msg: String? = null + if (e is ConnectException + || e is SocketTimeoutException + || e is TimeoutException) { + code = -9999 + msg = "network anomaly" + + } else if (e is HttpResultException) { + code = e.code + msg = e.msg + } + Timber.e("Request to enter the onError of HttpResultSubscriber , status is %s , msg is %s", code, msg) + _onError(code, msg) + onCompleted() + } + + override fun onNext(httpResult: HttpResultEntity) { + httpResult.takeIf { it.isSuccess }?.also { + onSuccess(httpResult.data) + } ?: _onError(httpResult.errorCode, "") + } + + abstract fun onSuccess(t: T?) + + abstract fun _onError(status: Int, msg: String?) +} From 4fffdd549911d14bc81c8647a37d5b8fa5e5d9f5 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Tue, 8 Jan 2019 17:20:12 +0800 Subject: [PATCH 070/150] fetchProjectListFromServer --- .../wanandroid/WanAndroidProjectFragment.kt | 118 ++++++++++++++++++ .../wanandroid/model/WanAndroidRepository.kt | 5 + .../wanandroid/service/WanAndroidService.kt | 4 + .../layout/fragment_wan_android_project.xml | 14 ++- app/src/main/res/layout/item_project.xml | 78 ++++++++++++ .../mipmap-xhdpi/icon_arrow_right_project.png | Bin 0 -> 328 bytes 6 files changed, 214 insertions(+), 5 deletions(-) create mode 100644 app/src/main/res/layout/item_project.xml create mode 100644 app/src/main/res/mipmap-xhdpi/icon_arrow_right_project.png diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt index 12c6f6f..8f1dd71 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt @@ -1,12 +1,28 @@ package com.leeeyou.wanandroid +import `in`.srain.cube.views.ptr.PtrFrameLayout +import `in`.srain.cube.views.ptr.PtrHandler import android.os.Bundle +import android.support.v7.widget.LinearLayoutManager import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.ImageView +import com.bumptech.glide.Glide +import com.chad.library.adapter.base.BaseQuickAdapter +import com.chad.library.adapter.base.BaseViewHolder import com.leeeyou.R import com.leeeyou.manager.BaseFragment +import com.leeeyou.service.subscriber.DefaultHttpResultSubscriber +import com.leeeyou.util.T import com.leeeyou.util.inflate +import com.leeeyou.util.startBrowserActivity +import com.leeeyou.wanandroid.model.bean.RecommendItem +import com.leeeyou.wanandroid.model.bean.RecommendList +import com.leeeyou.wanandroid.model.fetchProjectList +import kotlinx.android.synthetic.main.fragment_wan_android_project.* +import rx.android.schedulers.AndroidSchedulers +import rx.schedulers.Schedulers /** * ClassName: WeatherFragment @@ -16,8 +32,110 @@ import com.leeeyou.util.inflate * Date: 2017/4/24 13:46 */ class WanAndroidProjectFragment : BaseFragment() { + private lateinit var mLinearLayoutManager: LinearLayoutManager + private lateinit var mProjectAdapter: BaseQuickAdapter + private var mPageCount: Int = 0 + private var mPageIndex: Int = 0 + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return container?.inflate(R.layout.fragment_wan_android_project) } + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + initRecyclerView() + initPtrFrame() + fetchProjectListFromServer(mPageIndex) + } + + private fun initRecyclerView() { + mLinearLayoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) + mProjectAdapter = object : BaseQuickAdapter(R.layout.item_project, null) { + override fun convert(helper: BaseViewHolder?, item: RecommendItem?) { + item?.also { + helper?.also { helper -> + helper.setText(R.id.tv_title, it.title) + .setText(R.id.tv_author, it.author) + .setText(R.id.tv_niceDate, it.niceDate) + + val imageView = helper.getView(R.id.iv_project) as ImageView + Glide.with(mContext).load(item.envelopePic).into(imageView) + + helper.setOnClickListener(R.id.tv_view_similar_projects) { + T.showShort(mContext, "显示同类项目") + } + } + } + } + } + mProjectAdapter.setOnLoadMoreListener({ + if (mPageIndex + 1 == mPageCount) { + mProjectAdapter.loadMoreEnd() + } else { + fetchProjectListFromServer(++mPageIndex) + } + }, recyclerViewProject) + mProjectAdapter.disableLoadMoreIfNotFullPage() + mProjectAdapter.setOnItemClickListener { adapter, _, position -> + val item: RecommendItem = adapter.getItem(position) as RecommendItem + startBrowserActivity(context!!, item.link, item.title) + } + mProjectAdapter.openLoadAnimation(BaseQuickAdapter.SCALEIN) + + recyclerViewProject.layoutManager = mLinearLayoutManager + recyclerViewProject.adapter = mProjectAdapter + } + + private fun initPtrFrame() { + ptrFrameProject.disableWhenHorizontalMove(true) + ptrFrameProject.setPtrHandler(object : PtrHandler { + override fun onRefreshBegin(frame: PtrFrameLayout?) { + pullDownToRefresh() + } + + override fun checkCanDoRefresh(frame: PtrFrameLayout?, content: View?, header: View?): Boolean = + recyclerViewFirstItemCanVisible() + }) + } + + private fun recyclerViewFirstItemCanVisible() = + mLinearLayoutManager.findFirstCompletelyVisibleItemPosition() <= 0 + + private fun pullDownToRefresh() { + mPageIndex = 0 + fetchProjectListFromServer(mPageIndex) + } + + private fun fetchProjectListFromServer(pageIndex: Int) { + fetchProjectList(pageIndex).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : DefaultHttpResultSubscriber() { + override fun onSuccess(t: RecommendList?) { + t?.let { + renderProjectList(pageIndex, t) + if (mPageIndex == 0 && t.datas.size < t.size) { + mProjectAdapter.loadMoreEnd() + } else if (mPageIndex > 0) { + mProjectAdapter.loadMoreComplete() + } + } + } + + override fun onCompleted() { + ptrFrameProject?.refreshComplete() + if (mPageIndex > 0) { + mProjectAdapter.loadMoreComplete() + } + } + }) + } + + private fun renderProjectList(pageIndex: Int, data: RecommendList) { + if (pageIndex == 0) { + mProjectAdapter.setNewData(ArrayList(data.datas)) + } else { + mPageCount = data.pageCount + mProjectAdapter.addData(data.datas) + } + } + } \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt b/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt index 73f8ce5..2e087e6 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt @@ -33,4 +33,9 @@ fun fetchSystemTagArticleList(pageIndex: Int, cid: Int): Observable> { + return ServiceFactory.createRxRetrofitService(WanAndroidService::class.java, endPoint) + .getProjectList(pageIndex) } \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt b/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt index 4d9a78c..957bf28 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt @@ -22,4 +22,8 @@ interface WanAndroidService { @GET("article/list/{pageIndex}/json") fun getSystemTagArticleList(@Path("pageIndex") pageIndex: Int, @Query("cid") cid: Int): Observable> + + @GET("article/listproject/{pageIndex}/json") + fun getProjectList(@Path("pageIndex") pageIndex: Int): Observable> + } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_wan_android_project.xml b/app/src/main/res/layout/fragment_wan_android_project.xml index e45aee9..8dfb60a 100644 --- a/app/src/main/res/layout/fragment_wan_android_project.xml +++ b/app/src/main/res/layout/fragment_wan_android_project.xml @@ -1,7 +1,11 @@ - + + - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/item_project.xml b/app/src/main/res/layout/item_project.xml new file mode 100644 index 0000000..658a670 --- /dev/null +++ b/app/src/main/res/layout/item_project.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/mipmap-xhdpi/icon_arrow_right_project.png b/app/src/main/res/mipmap-xhdpi/icon_arrow_right_project.png new file mode 100644 index 0000000000000000000000000000000000000000..bab5cf9819bd23e9bc27ca6bbd75f78782bc4009 GIT binary patch literal 328 zcmV-O0k{5%P)_98+eAu`dvCu+!D2Sl0LAPLOrIppItgIA8ENldE0WL+$sJNwa8G!fpZEYrrFLAn9#r;U+M(ALs)xmGm)> zHiJDh5^hR*@1y?(FMtWKE9rM3&~_FJxGACSOJEh)lk~IDP-?L1gto7N6<|A;tV>(E z%Td2d*p8&{(tRF#ZK8GqECE$mwq@HL7H!5^D<;dfoUj?N3~WjIDz!O!4%5SW2As5F a0sjFgg=7`-awD_=0000 Date: Tue, 8 Jan 2019 18:14:49 +0800 Subject: [PATCH 071/150] fetchProjectCategoryFromServer --- .../wanandroid/WanAndroidProjectFragment.kt | 147 +++++++++++++++++- .../wanandroid/model/WanAndroidRepository.kt | 10 ++ .../wanandroid/model/bean/RecommendTag.kt | 5 - .../model/bean/ResponseSystemTag.kt | 5 - .../bean/ResponseSystemTagArticleList.kt | 5 - .../wanandroid/service/WanAndroidService.kt | 5 + .../layout/fragment_wan_android_project.xml | 64 +++++++- 7 files changed, 222 insertions(+), 19 deletions(-) delete mode 100644 app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseSystemTag.kt delete mode 100644 app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseSystemTagArticleList.kt diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt index 8f1dd71..b6d38e7 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt @@ -7,7 +7,11 @@ import android.support.v7.widget.LinearLayoutManager import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.view.animation.AccelerateInterpolator +import android.view.animation.Animation +import android.view.animation.RotateAnimation import android.widget.ImageView +import android.widget.TextView import com.bumptech.glide.Glide import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.BaseViewHolder @@ -19,7 +23,12 @@ import com.leeeyou.util.inflate import com.leeeyou.util.startBrowserActivity import com.leeeyou.wanandroid.model.bean.RecommendItem import com.leeeyou.wanandroid.model.bean.RecommendList +import com.leeeyou.wanandroid.model.bean.SystemTag +import com.leeeyou.wanandroid.model.fetchProjectCategory import com.leeeyou.wanandroid.model.fetchProjectList +import com.leeeyou.wanandroid.model.fetchProjectListByCategory +import com.zhy.view.flowlayout.FlowLayout +import com.zhy.view.flowlayout.TagAdapter import kotlinx.android.synthetic.main.fragment_wan_android_project.* import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers @@ -37,6 +46,9 @@ class WanAndroidProjectFragment : BaseFragment() { private var mPageCount: Int = 0 private var mPageIndex: Int = 0 + private var mSelectedCategoryPosition: Int = 0 + private var mSelectedCategoryId: Int = 0 + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return container?.inflate(R.layout.fragment_wan_android_project) } @@ -45,7 +57,77 @@ class WanAndroidProjectFragment : BaseFragment() { super.onActivityCreated(savedInstanceState) initRecyclerView() initPtrFrame() - fetchProjectListFromServer(mPageIndex) + initProjectCategoryUI() + fetchProjectCategoryFromServer() + } + + private fun initProjectCategoryUI() { + rl_project_category.setOnClickListener { + if (sv_project_category.visibility == View.VISIBLE) hiddenDetailTagAnimation() else showDetailTagAnimation() + } + } + + private fun fetchProjectCategoryFromServer() { + fetchProjectCategory().subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : DefaultHttpResultSubscriber>() { + override fun onSuccess(t: List?) { + t?.let { + renderProjectCategory(it) + } + } + }) + } + + private fun renderProjectCategory(categoryList: List) { + mSelectedCategoryPosition = 0 + mSelectedCategoryId = categoryList[mSelectedCategoryPosition].id + renderCategory(categoryList) + processClickEvent(categoryList) + } + + private fun processClickEvent(categoryList: List) { + flowLayout_project_category.setOnTagClickListener { _, position, parent -> + mSelectedCategoryPosition = position + mSelectedCategoryId = categoryList[mSelectedCategoryPosition].id + + for (index in 0..parent.childCount) { + parent.getChildAt(index)?.isClickable = mSelectedCategoryPosition != index + } + + updateCategoryShow() + clickToRefreshList() + hiddenDetailTagAnimation() + + true + } + } + + private fun clickToRefreshList() { + mPageIndex = 0 + fetchProjectListByCategoryFromServer(mPageIndex) + } + + private fun renderCategory(categoryList: List) { + flowLayout_project_category.adapter = object : TagAdapter(categoryList) { + override fun getView(parent: FlowLayout?, position: Int, systemTag: SystemTag?): View { + val parentTag = layoutInflater.inflate(R.layout.item_system_tag, null) as TextView + systemTag?.let { + parentTag.text = it.name + return parentTag + } + return parentTag + } + } + flowLayout_project_category.adapter.setSelectedList(mSelectedCategoryPosition) + flowLayout_project_category.getChildAt(mSelectedCategoryPosition)?.isClickable = false + + updateCategoryShow() + pullDownToRefresh() + } + + private fun updateCategoryShow() { + val parentTag: SystemTag = flowLayout_project_category?.adapter?.getItem(mSelectedCategoryPosition) as SystemTag + tv_project_category.text = parentTag.name } private fun initRecyclerView() { @@ -129,6 +211,29 @@ class WanAndroidProjectFragment : BaseFragment() { }) } + private fun fetchProjectListByCategoryFromServer(pageIndex: Int) { + fetchProjectListByCategory(pageIndex, mSelectedCategoryId).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : DefaultHttpResultSubscriber() { + override fun onSuccess(t: RecommendList?) { + t?.let { + renderProjectList(pageIndex, t) + if (pageIndex == 0 && t.datas.size < t.size) { + mProjectAdapter.loadMoreEnd() + } else if (pageIndex > 0) { + mProjectAdapter.loadMoreComplete() + } + } + } + + override fun onCompleted() { + ptrFrameProject?.refreshComplete() + if (pageIndex > 0) { + mProjectAdapter.loadMoreComplete() + } + } + }) + } + private fun renderProjectList(pageIndex: Int, data: RecommendList) { if (pageIndex == 0) { mProjectAdapter.setNewData(ArrayList(data.datas)) @@ -138,4 +243,44 @@ class WanAndroidProjectFragment : BaseFragment() { } } + private fun showDetailTagAnimation() { + val rotateAnimation = RotateAnimation(0f, 90f, (iv_arrow_right.width / 2).toFloat(), (iv_arrow_right.height / 2).toFloat()) + rotateAnimation.duration = 100 + rotateAnimation.fillAfter = true + rotateAnimation.interpolator = AccelerateInterpolator() + iv_arrow_right.startAnimation(rotateAnimation) + + rotateAnimation.setAnimationListener(object : Animation.AnimationListener { + override fun onAnimationRepeat(animation: Animation?) { + } + + override fun onAnimationEnd(animation: Animation?) { + sv_project_category.visibility = View.VISIBLE + } + + override fun onAnimationStart(animation: Animation?) { + } + }) + } + + private fun hiddenDetailTagAnimation() { + val rotateAnimation = RotateAnimation(90f, 0f, (iv_arrow_right.width / 2).toFloat(), (iv_arrow_right.height / 2).toFloat()) + rotateAnimation.duration = 100 + rotateAnimation.fillAfter = true + rotateAnimation.interpolator = AccelerateInterpolator() + iv_arrow_right.startAnimation(rotateAnimation) + + rotateAnimation.setAnimationListener(object : Animation.AnimationListener { + override fun onAnimationRepeat(animation: Animation?) { + } + + override fun onAnimationEnd(animation: Animation?) { + sv_project_category.visibility = View.GONE + } + + override fun onAnimationStart(animation: Animation?) { + } + }) + } + } \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt b/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt index 2e087e6..44c939a 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt @@ -38,4 +38,14 @@ fun fetchSystemTagArticleList(pageIndex: Int, cid: Int): Observable> { return ServiceFactory.createRxRetrofitService(WanAndroidService::class.java, endPoint) .getProjectList(pageIndex) +} + +fun fetchProjectListByCategory(pageIndex: Int, categoryId: Int): Observable> { + return ServiceFactory.createRxRetrofitService(WanAndroidService::class.java, endPoint) + .getProjectListByCategory(pageIndex, categoryId) +} + +fun fetchProjectCategory(): Observable>> { + return ServiceFactory.createRxRetrofitService(WanAndroidService::class.java, endPoint) + .getProjectCategory() } \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendTag.kt b/app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendTag.kt index 8f1effb..839961e 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendTag.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/model/bean/RecommendTag.kt @@ -1,9 +1,4 @@ package com.leeeyou.wanandroid.model.bean -//{ -// "name": "公众号", -// "url": "/wxarticle/list/408/1" -//} - data class RecommendTag(val name: String, val url: String) \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseSystemTag.kt b/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseSystemTag.kt deleted file mode 100644 index 5ad43f6..0000000 --- a/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseSystemTag.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.leeeyou.wanandroid.model.bean - -data class ResponseSystemTag(val data: List, - val errorCode: Int, - val errorMsg: String) \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseSystemTagArticleList.kt b/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseSystemTagArticleList.kt deleted file mode 100644 index 8f38245..0000000 --- a/app/src/main/java/com/leeeyou/wanandroid/model/bean/ResponseSystemTagArticleList.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.leeeyou.wanandroid.model.bean - -data class ResponseSystemTagArticleList(val data: SystemTagArticleList, - val errorCode: Int, - val errorMsg: String) \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt b/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt index 957bf28..ecb0db9 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt @@ -26,4 +26,9 @@ interface WanAndroidService { @GET("article/listproject/{pageIndex}/json") fun getProjectList(@Path("pageIndex") pageIndex: Int): Observable> + @GET("article/listproject/{pageIndex}/json") + fun getProjectListByCategory(@Path("pageIndex") pageIndex: Int, @Query("cid") cid: Int): Observable> + + @GET("project/tree/json") + fun getProjectCategory(): Observable>> } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_wan_android_project.xml b/app/src/main/res/layout/fragment_wan_android_project.xml index 8dfb60a..0b23332 100644 --- a/app/src/main/res/layout/fragment_wan_android_project.xml +++ b/app/src/main/res/layout/fragment_wan_android_project.xml @@ -1,11 +1,69 @@ - + android:layout_height="match_parent"> + + + + + + + + + + + + + + + + + \ No newline at end of file From bb4a256a4db650732ed94a069d6bde42459d0fbc Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Wed, 9 Jan 2019 10:27:26 +0800 Subject: [PATCH 072/150] Update ProjectPage Interaction --- .../wanandroid/WanAndroidProjectFragment.kt | 86 +++++++++++-------- .../wanandroid/model/WanAndroidRepository.kt | 4 +- .../wanandroid/service/WanAndroidService.kt | 4 +- .../layout/fragment_wan_android_project.xml | 3 +- 4 files changed, 55 insertions(+), 42 deletions(-) diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt index b6d38e7..c18e18a 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt @@ -25,8 +25,8 @@ import com.leeeyou.wanandroid.model.bean.RecommendItem import com.leeeyou.wanandroid.model.bean.RecommendList import com.leeeyou.wanandroid.model.bean.SystemTag import com.leeeyou.wanandroid.model.fetchProjectCategory -import com.leeeyou.wanandroid.model.fetchProjectList import com.leeeyou.wanandroid.model.fetchProjectListByCategory +import com.leeeyou.wanandroid.model.fetchProjectListByRecommend import com.zhy.view.flowlayout.FlowLayout import com.zhy.view.flowlayout.TagAdapter import kotlinx.android.synthetic.main.fragment_wan_android_project.* @@ -49,6 +49,8 @@ class WanAndroidProjectFragment : BaseFragment() { private var mSelectedCategoryPosition: Int = 0 private var mSelectedCategoryId: Int = 0 + private var inRecommendMode: Boolean = true //is it currently in recommended mode + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return container?.inflate(R.layout.fragment_wan_android_project) } @@ -58,7 +60,38 @@ class WanAndroidProjectFragment : BaseFragment() { initRecyclerView() initPtrFrame() initProjectCategoryUI() - fetchProjectCategoryFromServer() + fetchProjectCategoryListFromServer() + } + + private fun fetchProjectListFromServer() { + if (inRecommendMode) { + fetchProjectListByRecommendFromServer(mPageIndex) + } else { + fetchProjectListByCategoryFromServer(mPageIndex) + } + } + + private fun fetchProjectListByRecommendFromServer(pageIndex: Int) { + fetchProjectListByRecommend(pageIndex).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : DefaultHttpResultSubscriber() { + override fun onSuccess(t: RecommendList?) { + t?.let { + renderProjectList(pageIndex, t) + if (mPageIndex == 0 && t.datas.size < t.size) { + mProjectAdapter.loadMoreEnd() + } else if (mPageIndex > 0) { + mProjectAdapter.loadMoreComplete() + } + } + } + + override fun onCompleted() { + ptrFrameProject?.refreshComplete() + if (mPageIndex > 0) { + mProjectAdapter.loadMoreComplete() + } + } + }) } private fun initProjectCategoryUI() { @@ -67,7 +100,7 @@ class WanAndroidProjectFragment : BaseFragment() { } } - private fun fetchProjectCategoryFromServer() { + private fun fetchProjectCategoryListFromServer() { fetchProjectCategory().subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) .subscribe(object : DefaultHttpResultSubscriber>() { override fun onSuccess(t: List?) { @@ -87,6 +120,7 @@ class WanAndroidProjectFragment : BaseFragment() { private fun processClickEvent(categoryList: List) { flowLayout_project_category.setOnTagClickListener { _, position, parent -> + inRecommendMode = false mSelectedCategoryPosition = position mSelectedCategoryId = categoryList[mSelectedCategoryPosition].id @@ -122,12 +156,18 @@ class WanAndroidProjectFragment : BaseFragment() { flowLayout_project_category.getChildAt(mSelectedCategoryPosition)?.isClickable = false updateCategoryShow() - pullDownToRefresh() + + mPageIndex = 0 + fetchProjectListFromServer() } private fun updateCategoryShow() { - val parentTag: SystemTag = flowLayout_project_category?.adapter?.getItem(mSelectedCategoryPosition) as SystemTag - tv_project_category.text = parentTag.name + if (inRecommendMode) { + tv_project_category.text = "最新热门推荐" + } else { + val parentTag: SystemTag = flowLayout_project_category?.adapter?.getItem(mSelectedCategoryPosition) as SystemTag + tv_project_category.text = parentTag.name + } } private fun initRecyclerView() { @@ -154,7 +194,8 @@ class WanAndroidProjectFragment : BaseFragment() { if (mPageIndex + 1 == mPageCount) { mProjectAdapter.loadMoreEnd() } else { - fetchProjectListFromServer(++mPageIndex) + mPageIndex++ + fetchProjectListFromServer() } }, recyclerViewProject) mProjectAdapter.disableLoadMoreIfNotFullPage() @@ -172,7 +213,8 @@ class WanAndroidProjectFragment : BaseFragment() { ptrFrameProject.disableWhenHorizontalMove(true) ptrFrameProject.setPtrHandler(object : PtrHandler { override fun onRefreshBegin(frame: PtrFrameLayout?) { - pullDownToRefresh() + mPageIndex = 0 + fetchProjectListFromServer() } override fun checkCanDoRefresh(frame: PtrFrameLayout?, content: View?, header: View?): Boolean = @@ -183,34 +225,6 @@ class WanAndroidProjectFragment : BaseFragment() { private fun recyclerViewFirstItemCanVisible() = mLinearLayoutManager.findFirstCompletelyVisibleItemPosition() <= 0 - private fun pullDownToRefresh() { - mPageIndex = 0 - fetchProjectListFromServer(mPageIndex) - } - - private fun fetchProjectListFromServer(pageIndex: Int) { - fetchProjectList(pageIndex).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) - .subscribe(object : DefaultHttpResultSubscriber() { - override fun onSuccess(t: RecommendList?) { - t?.let { - renderProjectList(pageIndex, t) - if (mPageIndex == 0 && t.datas.size < t.size) { - mProjectAdapter.loadMoreEnd() - } else if (mPageIndex > 0) { - mProjectAdapter.loadMoreComplete() - } - } - } - - override fun onCompleted() { - ptrFrameProject?.refreshComplete() - if (mPageIndex > 0) { - mProjectAdapter.loadMoreComplete() - } - } - }) - } - private fun fetchProjectListByCategoryFromServer(pageIndex: Int) { fetchProjectListByCategory(pageIndex, mSelectedCategoryId).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) .subscribe(object : DefaultHttpResultSubscriber() { diff --git a/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt b/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt index 44c939a..bb06b47 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/model/WanAndroidRepository.kt @@ -35,9 +35,9 @@ fun fetchSystemTagArticleList(pageIndex: Int, cid: Int): Observable> { +fun fetchProjectListByRecommend(pageIndex: Int): Observable> { return ServiceFactory.createRxRetrofitService(WanAndroidService::class.java, endPoint) - .getProjectList(pageIndex) + .getProjectListByRecommend(pageIndex) } fun fetchProjectListByCategory(pageIndex: Int, categoryId: Int): Observable> { diff --git a/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt b/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt index ecb0db9..d9f56fa 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/service/WanAndroidService.kt @@ -24,9 +24,9 @@ interface WanAndroidService { fun getSystemTagArticleList(@Path("pageIndex") pageIndex: Int, @Query("cid") cid: Int): Observable> @GET("article/listproject/{pageIndex}/json") - fun getProjectList(@Path("pageIndex") pageIndex: Int): Observable> + fun getProjectListByRecommend(@Path("pageIndex") pageIndex: Int): Observable> - @GET("article/listproject/{pageIndex}/json") + @GET("project/list/{pageIndex}/json") fun getProjectListByCategory(@Path("pageIndex") pageIndex: Int, @Query("cid") cid: Int): Observable> @GET("project/tree/json") diff --git a/app/src/main/res/layout/fragment_wan_android_project.xml b/app/src/main/res/layout/fragment_wan_android_project.xml index 0b23332..778ad04 100644 --- a/app/src/main/res/layout/fragment_wan_android_project.xml +++ b/app/src/main/res/layout/fragment_wan_android_project.xml @@ -21,10 +21,9 @@ android:layout_height="match_parent" android:gravity="center_vertical" android:paddingLeft="10dp" - android:text="开源完整项目" android:textSize="14sp" android:textStyle="bold" - tools:text="开源完整项目"/> + tools:text="最新推荐项目"/> Date: Wed, 9 Jan 2019 10:50:28 +0800 Subject: [PATCH 073/150] Update the display of HTML transfer characters --- app/src/main/java/com/leeeyou/util/HtmlUtils.java | 10 ++++++++++ .../leeeyou/wanandroid/WanAndroidProjectFragment.kt | 7 ++++--- .../leeeyou/wanandroid/WanAndroidRecommendFragment.kt | 5 +++-- .../com/leeeyou/wanandroid/WanAndroidSystemFragment.kt | 9 +++++---- .../com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt | 4 ++-- 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/leeeyou/util/HtmlUtils.java b/app/src/main/java/com/leeeyou/util/HtmlUtils.java index 322d185..400ad19 100644 --- a/app/src/main/java/com/leeeyou/util/HtmlUtils.java +++ b/app/src/main/java/com/leeeyou/util/HtmlUtils.java @@ -18,4 +18,14 @@ public static String structHtml(String oriStr, List cssList) { public static String structCssLink(String css) { return ""; } + + public static String translation(String content) { + return content.replace("<", "<") + .replace(">", ">") + .replace("&", "&") + .replace(""", "\"") + .replace("—", "—") + .replace("©", "©"); + } + } diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt index c18e18a..410307a 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt @@ -18,6 +18,7 @@ import com.chad.library.adapter.base.BaseViewHolder import com.leeeyou.R import com.leeeyou.manager.BaseFragment import com.leeeyou.service.subscriber.DefaultHttpResultSubscriber +import com.leeeyou.util.HtmlUtils import com.leeeyou.util.T import com.leeeyou.util.inflate import com.leeeyou.util.startBrowserActivity @@ -146,7 +147,7 @@ class WanAndroidProjectFragment : BaseFragment() { override fun getView(parent: FlowLayout?, position: Int, systemTag: SystemTag?): View { val parentTag = layoutInflater.inflate(R.layout.item_system_tag, null) as TextView systemTag?.let { - parentTag.text = it.name + parentTag.text = HtmlUtils.translation(it.name) return parentTag } return parentTag @@ -166,7 +167,7 @@ class WanAndroidProjectFragment : BaseFragment() { tv_project_category.text = "最新热门推荐" } else { val parentTag: SystemTag = flowLayout_project_category?.adapter?.getItem(mSelectedCategoryPosition) as SystemTag - tv_project_category.text = parentTag.name + tv_project_category.text = HtmlUtils.translation(parentTag.name) } } @@ -176,7 +177,7 @@ class WanAndroidProjectFragment : BaseFragment() { override fun convert(helper: BaseViewHolder?, item: RecommendItem?) { item?.also { helper?.also { helper -> - helper.setText(R.id.tv_title, it.title) + helper.setText(R.id.tv_title, HtmlUtils.translation(it.title)) .setText(R.id.tv_author, it.author) .setText(R.id.tv_niceDate, it.niceDate) diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt index 24b5abb..aa7e2e5 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt @@ -15,6 +15,7 @@ import com.chad.library.adapter.base.BaseViewHolder import com.leeeyou.R import com.leeeyou.manager.BaseFragment import com.leeeyou.service.subscriber.DefaultHttpResultSubscriber +import com.leeeyou.util.HtmlUtils import com.leeeyou.util.inflate import com.leeeyou.util.startBrowserActivity import com.leeeyou.wanandroid.model.bean.Banner @@ -65,7 +66,7 @@ class WanAndroidRecommendFragment : BaseFragment() { mRecommendAdapter = object : BaseQuickAdapter(R.layout.item_recommend, null) { override fun convert(helper: BaseViewHolder?, item: RecommendItem?) { item?.takeIf { it.visible == 1 }?.also { - helper?.setText(R.id.tv_title, it.title) + helper?.setText(R.id.tv_title, HtmlUtils.translation(it.title)) ?.setText(R.id.tv_author, "作者:" + it.author) ?.setText(R.id.tv_category, "分类:" + it.superChapterName + " / " + it.chapterName) ?.setText(R.id.tv_niceDate, it.niceDate) @@ -142,7 +143,7 @@ class WanAndroidRecommendFragment : BaseFragment() { } override fun onCompleted() { - ptrFrameRecommend.refreshComplete() + ptrFrameRecommend?.refreshComplete() } }) } diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt index 97d0d47..92bffd5 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt @@ -17,6 +17,7 @@ import com.chad.library.adapter.base.BaseViewHolder import com.leeeyou.R import com.leeeyou.manager.BaseFragment import com.leeeyou.service.subscriber.DefaultHttpResultSubscriber +import com.leeeyou.util.HtmlUtils import com.leeeyou.util.inflate import com.leeeyou.util.startBrowserActivity import com.leeeyou.wanandroid.model.bean.RecommendItem @@ -84,7 +85,7 @@ class WanAndroidSystemFragment : BaseFragment() { mSystemTagArticleAdapter = object : BaseQuickAdapter(R.layout.item_recommend, null) { override fun convert(helper: BaseViewHolder?, item: RecommendItem?) { item?.also { - helper?.setText(R.id.tv_title, it.title) + helper?.setText(R.id.tv_title, HtmlUtils.translation(it.title)) ?.setText(R.id.tv_author, "作者:" + it.author) ?.setText(R.id.tv_category, "分类:" + it.superChapterName + " / " + it.chapterName) ?.setText(R.id.tv_niceDate, it.niceDate) @@ -227,7 +228,7 @@ class WanAndroidSystemFragment : BaseFragment() { } override fun onCompleted() { - ptrFrameSystemTag.refreshComplete() + ptrFrameSystemTag?.refreshComplete() if (mPageIndex > 0) { mSystemTagArticleAdapter.loadMoreComplete() } @@ -249,7 +250,7 @@ class WanAndroidSystemFragment : BaseFragment() { override fun getView(parent: FlowLayout?, position: Int, systemTag: SystemTag?): View { val parentTag = layoutInflater.inflate(R.layout.item_system_tag, null) as TextView systemTag?.let { - parentTag.text = it.name + parentTag.text = HtmlUtils.translation(it.name) return parentTag } return parentTag @@ -264,7 +265,7 @@ class WanAndroidSystemFragment : BaseFragment() { override fun getView(parent: FlowLayout?, position: Int, systemTag: SystemTag?): View { val childTag = layoutInflater.inflate(R.layout.item_system_tag, null) as TextView systemTag?.let { - childTag.text = it.name + childTag.text = HtmlUtils.translation(it.name) return childTag } return childTag diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt index a3e2b16..5ca3a5a 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt @@ -131,7 +131,7 @@ class ZhiHuDailyFragment : BaseFragment() { .observeOn(AndroidSchedulers.mainThread()) .subscribe(object : Subscriber() { override fun onNext(item: ZhiHuDaily?) { - ptrFrameOfZhiHuDaily.refreshComplete() + ptrFrameOfZhiHuDaily?.refreshComplete() if (item != null) { updateAdapter(item.stories) } @@ -142,7 +142,7 @@ class ZhiHuDailyFragment : BaseFragment() { } override fun onError(e: Throwable?) { - ptrFrameOfZhiHuDaily.refreshComplete() + ptrFrameOfZhiHuDaily?.refreshComplete() e?.printStackTrace() showShort(activity, "出错了:" + e?.message) } From 41b6f55582f222716f41797054751df00533d332 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Wed, 9 Jan 2019 11:53:04 +0800 Subject: [PATCH 074/150] Optimize the cache of Fragment --- .../leeeyou/wanandroid/WanAndroidFragment.kt | 1 + .../wanandroid/WanAndroidProjectFragment.kt | 7 +- .../wanandroid/WanAndroidSystemFragment.kt | 72 +++++++++++-------- 3 files changed, 48 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidFragment.kt index 8436f40..33a5af6 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidFragment.kt @@ -40,6 +40,7 @@ class WanAndroidFragment : BaseFragment() { mViewPagerAdapter = ViewPagerAdapter(activity!!.supportFragmentManager, fragmentList, titleList) + wanAndroidViewPager.offscreenPageLimit = 3 wanAndroidViewPager.adapter = mViewPagerAdapter wanAndroidTabLayout.setupWithViewPager(wanAndroidViewPager) wanAndroidTabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt index 410307a..9e7eef9 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt @@ -232,8 +232,11 @@ class WanAndroidProjectFragment : BaseFragment() { override fun onSuccess(t: RecommendList?) { t?.let { renderProjectList(pageIndex, t) - if (pageIndex == 0 && t.datas.size < t.size) { - mProjectAdapter.loadMoreEnd() + if (pageIndex == 0) { + recyclerViewProject.smoothScrollToPosition(0) + if (t.datas.size < t.size) { + mProjectAdapter.loadMoreEnd() + } } else if (pageIndex > 0) { mProjectAdapter.loadMoreComplete() } diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt index 92bffd5..6f770c1 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt @@ -63,6 +63,14 @@ class WanAndroidSystemFragment : BaseFragment() { fetchSystemTagListFromServer() } + override fun setUserVisibleHint(isVisibleToUser: Boolean) { + super.setUserVisibleHint(isVisibleToUser) + // onPause + if (!isVisibleToUser) { + hiddenDetailTagAnimation() + } + } + private fun fetchSystemTagListFromServer() { fetchSystemTagList().subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) .subscribe(object : DefaultHttpResultSubscriber>() { @@ -173,43 +181,47 @@ class WanAndroidSystemFragment : BaseFragment() { } private fun showDetailTagAnimation() { - val rotateAnimation = RotateAnimation(0f, 90f, (iv_arrow_right.width / 2).toFloat(), (iv_arrow_right.height / 2).toFloat()) - rotateAnimation.duration = 100 - rotateAnimation.fillAfter = true - rotateAnimation.interpolator = AccelerateInterpolator() - iv_arrow_right.startAnimation(rotateAnimation) - - rotateAnimation.setAnimationListener(object : Animation.AnimationListener { - override fun onAnimationRepeat(animation: Animation?) { - } + iv_arrow_right?.let { + val rotateAnimation = RotateAnimation(0f, 90f, (iv_arrow_right.width / 2).toFloat(), (iv_arrow_right.height / 2).toFloat()) + rotateAnimation.duration = 100 + rotateAnimation.fillAfter = true + rotateAnimation.interpolator = AccelerateInterpolator() + iv_arrow_right.startAnimation(rotateAnimation) + + rotateAnimation.setAnimationListener(object : Animation.AnimationListener { + override fun onAnimationRepeat(animation: Animation?) { + } - override fun onAnimationEnd(animation: Animation?) { - sv_system_tag_all.visibility = View.VISIBLE - } + override fun onAnimationEnd(animation: Animation?) { + sv_system_tag_all?.visibility = View.VISIBLE + } - override fun onAnimationStart(animation: Animation?) { - } - }) + override fun onAnimationStart(animation: Animation?) { + } + }) + } } private fun hiddenDetailTagAnimation() { - val rotateAnimation = RotateAnimation(90f, 0f, (iv_arrow_right.width / 2).toFloat(), (iv_arrow_right.height / 2).toFloat()) - rotateAnimation.duration = 100 - rotateAnimation.fillAfter = true - rotateAnimation.interpolator = AccelerateInterpolator() - iv_arrow_right.startAnimation(rotateAnimation) - - rotateAnimation.setAnimationListener(object : Animation.AnimationListener { - override fun onAnimationRepeat(animation: Animation?) { - } + iv_arrow_right?.let { + val rotateAnimation = RotateAnimation(90f, 0f, (iv_arrow_right.width / 2).toFloat(), (iv_arrow_right.height / 2).toFloat()) + rotateAnimation.duration = 100 + rotateAnimation.fillAfter = true + rotateAnimation.interpolator = AccelerateInterpolator() + iv_arrow_right.startAnimation(rotateAnimation) + + rotateAnimation.setAnimationListener(object : Animation.AnimationListener { + override fun onAnimationRepeat(animation: Animation?) { + } - override fun onAnimationEnd(animation: Animation?) { - sv_system_tag_all.visibility = View.GONE - } + override fun onAnimationEnd(animation: Animation?) { + sv_system_tag_all.visibility = View.GONE + } - override fun onAnimationStart(animation: Animation?) { - } - }) + override fun onAnimationStart(animation: Animation?) { + } + }) + } } private fun fetchSystemTagArticleList(pageIndex: Int) { From ff6cd7f7358e8283df5a0f2f9f8d1bfa369dffb5 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Wed, 9 Jan 2019 14:22:04 +0800 Subject: [PATCH 075/150] Custom loadmore view --- .../com/leeeyou/manager/MyLoadMoreView.kt | 23 +++++++ .../wanandroid/WanAndroidProjectFragment.kt | 2 + .../wanandroid/WanAndroidRecommendFragment.kt | 2 + .../wanandroid/WanAndroidSystemFragment.kt | 2 + app/src/main/res/layout/adapter_load_more.xml | 60 +++++++++++++++++++ 5 files changed, 89 insertions(+) create mode 100644 app/src/main/java/com/leeeyou/manager/MyLoadMoreView.kt create mode 100644 app/src/main/res/layout/adapter_load_more.xml diff --git a/app/src/main/java/com/leeeyou/manager/MyLoadMoreView.kt b/app/src/main/java/com/leeeyou/manager/MyLoadMoreView.kt new file mode 100644 index 0000000..83a42b0 --- /dev/null +++ b/app/src/main/java/com/leeeyou/manager/MyLoadMoreView.kt @@ -0,0 +1,23 @@ +package com.leeeyou.manager + +import com.chad.library.adapter.base.loadmore.LoadMoreView +import com.leeeyou.R + +class MyLoadMoreView : LoadMoreView() { + override fun getLayoutId(): Int { + return R.layout.adapter_load_more + } + + override fun getLoadingViewId(): Int { + return R.id.load_more_loading_view + } + + override fun getLoadEndViewId(): Int { + return R.id.load_more_load_fail_view + } + + override fun getLoadFailViewId(): Int { + return R.id.load_more_load_end_view + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt index 9e7eef9..3657764 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt @@ -17,6 +17,7 @@ import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.BaseViewHolder import com.leeeyou.R import com.leeeyou.manager.BaseFragment +import com.leeeyou.manager.MyLoadMoreView import com.leeeyou.service.subscriber.DefaultHttpResultSubscriber import com.leeeyou.util.HtmlUtils import com.leeeyou.util.T @@ -205,6 +206,7 @@ class WanAndroidProjectFragment : BaseFragment() { startBrowserActivity(context!!, item.link, item.title) } mProjectAdapter.openLoadAnimation(BaseQuickAdapter.SCALEIN) + mProjectAdapter.setLoadMoreView(MyLoadMoreView()) recyclerViewProject.layoutManager = mLinearLayoutManager recyclerViewProject.adapter = mProjectAdapter diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt index aa7e2e5..bbde7c4 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt @@ -14,6 +14,7 @@ import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.BaseViewHolder import com.leeeyou.R import com.leeeyou.manager.BaseFragment +import com.leeeyou.manager.MyLoadMoreView import com.leeeyou.service.subscriber.DefaultHttpResultSubscriber import com.leeeyou.util.HtmlUtils import com.leeeyou.util.inflate @@ -86,6 +87,7 @@ class WanAndroidRecommendFragment : BaseFragment() { startBrowserActivity(context!!, item.link, item.title) } mRecommendAdapter.openLoadAnimation(BaseQuickAdapter.SCALEIN) + mRecommendAdapter.setLoadMoreView(MyLoadMoreView()) recyclerViewRecommend.layoutManager = mLinearLayoutManager recyclerViewRecommend.adapter = mRecommendAdapter diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt index 6f770c1..1cea961 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt @@ -16,6 +16,7 @@ import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.BaseViewHolder import com.leeeyou.R import com.leeeyou.manager.BaseFragment +import com.leeeyou.manager.MyLoadMoreView import com.leeeyou.service.subscriber.DefaultHttpResultSubscriber import com.leeeyou.util.HtmlUtils import com.leeeyou.util.inflate @@ -114,6 +115,7 @@ class WanAndroidSystemFragment : BaseFragment() { startBrowserActivity(context!!, item.link, item.title) } mSystemTagArticleAdapter.openLoadAnimation(BaseQuickAdapter.SCALEIN) + mSystemTagArticleAdapter.setLoadMoreView(MyLoadMoreView()) recyclerViewSystem.layoutManager = mLinearLayoutManager recyclerViewSystem.adapter = mSystemTagArticleAdapter diff --git a/app/src/main/res/layout/adapter_load_more.xml b/app/src/main/res/layout/adapter_load_more.xml new file mode 100644 index 0000000..3de757a --- /dev/null +++ b/app/src/main/res/layout/adapter_load_more.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From c1a40bc3c11627f25e3399de00b5cf405a1999bd Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Wed, 9 Jan 2019 14:27:36 +0800 Subject: [PATCH 076/150] Extract MyAnimationListener.kt --- .../leeeyou/manager/MyAnimationListener.kt | 15 ++++ .../wanandroid/WanAndroidProjectFragment.kt | 69 ++++++++++--------- .../wanandroid/WanAndroidSystemFragment.kt | 17 +---- 3 files changed, 53 insertions(+), 48 deletions(-) create mode 100644 app/src/main/java/com/leeeyou/manager/MyAnimationListener.kt diff --git a/app/src/main/java/com/leeeyou/manager/MyAnimationListener.kt b/app/src/main/java/com/leeeyou/manager/MyAnimationListener.kt new file mode 100644 index 0000000..ce25620 --- /dev/null +++ b/app/src/main/java/com/leeeyou/manager/MyAnimationListener.kt @@ -0,0 +1,15 @@ +package com.leeeyou.manager + +import android.view.animation.Animation + +open class MyAnimationListener : Animation.AnimationListener { + override fun onAnimationRepeat(animation: Animation?) { + + } + + override fun onAnimationEnd(animation: Animation?) { + } + + override fun onAnimationStart(animation: Animation?) { + } +} \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt index 3657764..72ba2e2 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt @@ -17,6 +17,7 @@ import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.BaseViewHolder import com.leeeyou.R import com.leeeyou.manager.BaseFragment +import com.leeeyou.manager.MyAnimationListener import com.leeeyou.manager.MyLoadMoreView import com.leeeyou.service.subscriber.DefaultHttpResultSubscriber import com.leeeyou.util.HtmlUtils @@ -65,6 +66,14 @@ class WanAndroidProjectFragment : BaseFragment() { fetchProjectCategoryListFromServer() } + override fun setUserVisibleHint(isVisibleToUser: Boolean) { + super.setUserVisibleHint(isVisibleToUser) + // onPause + if (!isVisibleToUser) { + hiddenDetailTagAnimation() + } + } + private fun fetchProjectListFromServer() { if (inRecommendMode) { fetchProjectListByRecommendFromServer(mPageIndex) @@ -264,43 +273,35 @@ class WanAndroidProjectFragment : BaseFragment() { } private fun showDetailTagAnimation() { - val rotateAnimation = RotateAnimation(0f, 90f, (iv_arrow_right.width / 2).toFloat(), (iv_arrow_right.height / 2).toFloat()) - rotateAnimation.duration = 100 - rotateAnimation.fillAfter = true - rotateAnimation.interpolator = AccelerateInterpolator() - iv_arrow_right.startAnimation(rotateAnimation) - - rotateAnimation.setAnimationListener(object : Animation.AnimationListener { - override fun onAnimationRepeat(animation: Animation?) { - } - - override fun onAnimationEnd(animation: Animation?) { - sv_project_category.visibility = View.VISIBLE - } - - override fun onAnimationStart(animation: Animation?) { - } - }) + iv_arrow_right?.let { + val rotateAnimation = RotateAnimation(0f, 90f, (iv_arrow_right.width / 2).toFloat(), (iv_arrow_right.height / 2).toFloat()) + rotateAnimation.duration = 100 + rotateAnimation.fillAfter = true + rotateAnimation.interpolator = AccelerateInterpolator() + iv_arrow_right.startAnimation(rotateAnimation) + + rotateAnimation.setAnimationListener(object : MyAnimationListener() { + override fun onAnimationEnd(animation: Animation?) { + sv_project_category.visibility = View.VISIBLE + } + }) + } } private fun hiddenDetailTagAnimation() { - val rotateAnimation = RotateAnimation(90f, 0f, (iv_arrow_right.width / 2).toFloat(), (iv_arrow_right.height / 2).toFloat()) - rotateAnimation.duration = 100 - rotateAnimation.fillAfter = true - rotateAnimation.interpolator = AccelerateInterpolator() - iv_arrow_right.startAnimation(rotateAnimation) - - rotateAnimation.setAnimationListener(object : Animation.AnimationListener { - override fun onAnimationRepeat(animation: Animation?) { - } - - override fun onAnimationEnd(animation: Animation?) { - sv_project_category.visibility = View.GONE - } - - override fun onAnimationStart(animation: Animation?) { - } - }) + iv_arrow_right?.let { + val rotateAnimation = RotateAnimation(90f, 0f, (iv_arrow_right.width / 2).toFloat(), (iv_arrow_right.height / 2).toFloat()) + rotateAnimation.duration = 100 + rotateAnimation.fillAfter = true + rotateAnimation.interpolator = AccelerateInterpolator() + iv_arrow_right.startAnimation(rotateAnimation) + + rotateAnimation.setAnimationListener(object : MyAnimationListener() { + override fun onAnimationEnd(animation: Animation?) { + sv_project_category.visibility = View.GONE + } + }) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt index 1cea961..8ba25c2 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt @@ -16,6 +16,7 @@ import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.BaseViewHolder import com.leeeyou.R import com.leeeyou.manager.BaseFragment +import com.leeeyou.manager.MyAnimationListener import com.leeeyou.manager.MyLoadMoreView import com.leeeyou.service.subscriber.DefaultHttpResultSubscriber import com.leeeyou.util.HtmlUtils @@ -190,16 +191,10 @@ class WanAndroidSystemFragment : BaseFragment() { rotateAnimation.interpolator = AccelerateInterpolator() iv_arrow_right.startAnimation(rotateAnimation) - rotateAnimation.setAnimationListener(object : Animation.AnimationListener { - override fun onAnimationRepeat(animation: Animation?) { - } - + rotateAnimation.setAnimationListener(object : MyAnimationListener() { override fun onAnimationEnd(animation: Animation?) { sv_system_tag_all?.visibility = View.VISIBLE } - - override fun onAnimationStart(animation: Animation?) { - } }) } } @@ -212,16 +207,10 @@ class WanAndroidSystemFragment : BaseFragment() { rotateAnimation.interpolator = AccelerateInterpolator() iv_arrow_right.startAnimation(rotateAnimation) - rotateAnimation.setAnimationListener(object : Animation.AnimationListener { - override fun onAnimationRepeat(animation: Animation?) { - } - + rotateAnimation.setAnimationListener(object : MyAnimationListener() { override fun onAnimationEnd(animation: Animation?) { sv_system_tag_all.visibility = View.GONE } - - override fun onAnimationStart(animation: Animation?) { - } }) } } From 964b083a462583856826bcf406918730603bed2b Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Wed, 9 Jan 2019 15:25:28 +0800 Subject: [PATCH 077/150] PullToRefresh Animation --- app/src/main/java/com/leeeyou/IndexActivity.kt | 1 + .../wanandroid/WanAndroidProjectFragment.kt | 13 +++++++++++++ .../wanandroid/WanAndroidRecommendFragment.kt | 13 +++++++++++++ .../wanandroid/WanAndroidSystemFragment.kt | 13 +++++++++++++ .../leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt | 15 +++++++++++++++ 5 files changed, 55 insertions(+) diff --git a/app/src/main/java/com/leeeyou/IndexActivity.kt b/app/src/main/java/com/leeeyou/IndexActivity.kt index ac686f3..0b2932c 100644 --- a/app/src/main/java/com/leeeyou/IndexActivity.kt +++ b/app/src/main/java/com/leeeyou/IndexActivity.kt @@ -16,6 +16,7 @@ import kotlinx.android.synthetic.main.activity_index.* private const val INDEX_VIEWPAGER_WEATHER_STR = "天气" private const val INDEX_VIEWPAGER_ANDROID_STR = "安卓" private const val INDEX_VIEWPAGER_ZHIHU_STR = "知乎" +const val APP_NAME = "RsKotlin" /** * ClassName: IndexActivity diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt index 72ba2e2..1b7009f 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt @@ -2,6 +2,8 @@ package com.leeeyou.wanandroid import `in`.srain.cube.views.ptr.PtrFrameLayout import `in`.srain.cube.views.ptr.PtrHandler +import `in`.srain.cube.views.ptr.header.StoreHouseHeader +import `in`.srain.cube.views.ptr.util.PtrLocalDisplay.dp2px import android.os.Bundle import android.support.v7.widget.LinearLayoutManager import android.view.LayoutInflater @@ -15,6 +17,7 @@ import android.widget.TextView import com.bumptech.glide.Glide import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.BaseViewHolder +import com.leeeyou.APP_NAME import com.leeeyou.R import com.leeeyou.manager.BaseFragment import com.leeeyou.manager.MyAnimationListener @@ -222,6 +225,7 @@ class WanAndroidProjectFragment : BaseFragment() { } private fun initPtrFrame() { + initHeadView() ptrFrameProject.disableWhenHorizontalMove(true) ptrFrameProject.setPtrHandler(object : PtrHandler { override fun onRefreshBegin(frame: PtrFrameLayout?) { @@ -234,6 +238,15 @@ class WanAndroidProjectFragment : BaseFragment() { }) } + private fun initHeadView() { + val header = StoreHouseHeader(context) + header.setTextColor(resources.getColor(R.color.default_red)) + header.setPadding(0, dp2px(15f), 0, 0) + header.initWithString(APP_NAME, 15) + ptrFrameProject.headerView = header + ptrFrameProject.addPtrUIHandler(header) + } + private fun recyclerViewFirstItemCanVisible() = mLinearLayoutManager.findFirstCompletelyVisibleItemPosition() <= 0 diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt index bbde7c4..679f62f 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt @@ -2,6 +2,8 @@ package com.leeeyou.wanandroid import `in`.srain.cube.views.ptr.PtrFrameLayout import `in`.srain.cube.views.ptr.PtrHandler +import `in`.srain.cube.views.ptr.header.StoreHouseHeader +import `in`.srain.cube.views.ptr.util.PtrLocalDisplay.dp2px import android.content.Context import android.os.Bundle import android.support.v7.widget.LinearLayoutManager @@ -12,6 +14,7 @@ import android.widget.ImageView import com.bumptech.glide.Glide import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.BaseViewHolder +import com.leeeyou.APP_NAME import com.leeeyou.R import com.leeeyou.manager.BaseFragment import com.leeeyou.manager.MyLoadMoreView @@ -107,6 +110,7 @@ class WanAndroidRecommendFragment : BaseFragment() { } private fun initPtrFrame() { + initHeadView() ptrFrameRecommend.disableWhenHorizontalMove(true) ptrFrameRecommend.setPtrHandler(object : PtrHandler { override fun onRefreshBegin(frame: PtrFrameLayout?) { @@ -117,6 +121,15 @@ class WanAndroidRecommendFragment : BaseFragment() { }) } + private fun initHeadView() { + val header = StoreHouseHeader(context) + header.setTextColor(resources.getColor(R.color.default_red)) + header.setPadding(0, dp2px(15f), 0, 0) + header.initWithString(APP_NAME, 15) + ptrFrameRecommend.headerView = header + ptrFrameRecommend.addPtrUIHandler(header) + } + private fun recyclerViewFirstItemCanVisible() = mLinearLayoutManager.findFirstCompletelyVisibleItemPosition() <= 0 diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt index 8ba25c2..8ea65a8 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt @@ -2,6 +2,8 @@ package com.leeeyou.wanandroid import `in`.srain.cube.views.ptr.PtrFrameLayout import `in`.srain.cube.views.ptr.PtrHandler +import `in`.srain.cube.views.ptr.header.StoreHouseHeader +import `in`.srain.cube.views.ptr.util.PtrLocalDisplay.dp2px import android.annotation.SuppressLint import android.os.Bundle import android.support.v7.widget.LinearLayoutManager @@ -14,6 +16,7 @@ import android.view.animation.RotateAnimation import android.widget.TextView import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.BaseViewHolder +import com.leeeyou.APP_NAME import com.leeeyou.R import com.leeeyou.manager.BaseFragment import com.leeeyou.manager.MyAnimationListener @@ -123,6 +126,7 @@ class WanAndroidSystemFragment : BaseFragment() { } private fun initPtrFrame() { + initHeadView() ptrFrameSystemTag.disableWhenHorizontalMove(true) ptrFrameSystemTag.setPtrHandler(object : PtrHandler { override fun onRefreshBegin(frame: PtrFrameLayout?) { @@ -134,6 +138,15 @@ class WanAndroidSystemFragment : BaseFragment() { }) } + private fun initHeadView() { + val header = StoreHouseHeader(context) + header.setTextColor(resources.getColor(R.color.default_red)) + header.setPadding(0, dp2px(15f), 0, 0) + header.initWithString(APP_NAME, 15) + ptrFrameSystemTag.headerView = header + ptrFrameSystemTag.addPtrUIHandler(header) + } + private fun pullDownToRefresh() { mPageIndex = 0 fetchSystemTagArticleList(mPageIndex) diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt index 5ca3a5a..f79b68f 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt @@ -2,14 +2,18 @@ package com.leeeyou.zhihudaily.view import `in`.srain.cube.views.ptr.PtrDefaultHandler import `in`.srain.cube.views.ptr.PtrFrameLayout +import `in`.srain.cube.views.ptr.header.StoreHouseHeader +import `in`.srain.cube.views.ptr.util.PtrLocalDisplay.dp2px import android.os.Bundle import android.support.v7.widget.LinearLayoutManager import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import com.chad.library.adapter.base.BaseQuickAdapter +import com.leeeyou.APP_NAME import com.leeeyou.R import com.leeeyou.manager.BaseFragment +import com.leeeyou.manager.MyLoadMoreView import com.leeeyou.util.T.showShort import com.leeeyou.util.startBrowserActivity import com.leeeyou.zhihudaily.model.bean.ZhiHuDaily @@ -55,6 +59,7 @@ class ZhiHuDailyFragment : BaseFragment() { } private fun initPtr() { + initHeadView() ptrFrameOfZhiHuDaily.disableWhenHorizontalMove(true) ptrFrameOfZhiHuDaily.setPtrHandler(object : PtrDefaultHandler() { override fun onRefreshBegin(frame: PtrFrameLayout?) { @@ -68,9 +73,19 @@ class ZhiHuDailyFragment : BaseFragment() { }) } + private fun initHeadView() { + val header = StoreHouseHeader(context) + header.setTextColor(resources.getColor(R.color.default_red)) + header.setPadding(0, dp2px(15f), 0, 0) + header.initWithString(APP_NAME, 15) + ptrFrameOfZhiHuDaily.headerView = header + ptrFrameOfZhiHuDaily.addPtrUIHandler(header) + } + private fun initAdapter() { mAdapter = ZhiHuDailyAdapter(R.layout.item_zhihu_daily, null) mAdapter.openLoadAnimation(BaseQuickAdapter.SCALEIN) + mAdapter.setLoadMoreView(MyLoadMoreView()) mAdapter.setOnItemChildClickListener { adapter, _, position -> val item: ZhiHuDailyItem? = adapter.getItem(position) as ZhiHuDailyItem item?.let { From 6e58dd32f4c2c17ac603789d41871b1ceb95c4f0 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Thu, 10 Jan 2019 21:53:45 +0800 Subject: [PATCH 078/150] add MovieFragment --- app/build.gradle | 12 +- app/src/main/AndroidManifest.xml | 2 + .../main/java/com/leeeyou/IndexActivity.kt | 13 +- .../java/com/leeeyou/movie/MovieFragment.kt | 106 +++++ .../leeeyou/movie/model/MovieRepository.kt | 14 + .../movie/model/bean/ResponseHotMovie.java | 440 ++++++++++++++++++ .../com/leeeyou/movie/service/MovieService.kt | 10 + .../service/converter/MyGsonConverter.java | 2 +- .../com/leeeyou/weather/WeatherFragment.kt | 23 - ...ragment_weather.xml => fragment_movie.xml} | 12 +- app/src/main/res/layout/item_hot_movie.xml | 44 ++ .../res/mipmap-xhdpi/index_icon_douban.png | Bin 0 -> 1163 bytes .../res/mipmap-xhdpi/index_icon_weather.png | Bin 1046 -> 0 bytes 13 files changed, 644 insertions(+), 34 deletions(-) create mode 100644 app/src/main/java/com/leeeyou/movie/MovieFragment.kt create mode 100644 app/src/main/java/com/leeeyou/movie/model/MovieRepository.kt create mode 100644 app/src/main/java/com/leeeyou/movie/model/bean/ResponseHotMovie.java create mode 100644 app/src/main/java/com/leeeyou/movie/service/MovieService.kt delete mode 100644 app/src/main/java/com/leeeyou/weather/WeatherFragment.kt rename app/src/main/res/layout/{fragment_weather.xml => fragment_movie.xml} (51%) create mode 100644 app/src/main/res/layout/item_hot_movie.xml create mode 100644 app/src/main/res/mipmap-xhdpi/index_icon_douban.png delete mode 100644 app/src/main/res/mipmap-xhdpi/index_icon_weather.png diff --git a/app/build.gradle b/app/build.gradle index cc55e44..233ffc9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -21,7 +21,7 @@ android { ndk { //Set up a supported SO library architecture - abiFilters 'armeabi', 'x86'//, 'armeabi-v7a', 'x86_64', 'arm64-v8a' + abiFilters 'armeabi', 'x86', 'armeabi-v7a'//, 'x86_64', 'arm64-v8a' } } @@ -52,6 +52,12 @@ android { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 } + + sourceSets { + main { + jniLibs.srcDirs = ['libs'] + } + } } dependencies { @@ -82,8 +88,8 @@ dependencies { implementation 'com.github.bumptech.glide:glide:4.8.0' //okhttp - implementation 'com.squareup.okhttp3:logging-interceptor:3.1.2' - implementation("com.squareup.okhttp3:okhttp:3.12.1") + implementation 'com.squareup.okhttp3:logging-interceptor:3.8.1' + implementation 'com.squareup.okhttp3:okhttp:3.12.1' //kotlin implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ea52557..22e44fe 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -8,6 +8,8 @@ + + pages.add(FragmentPagerItem.of("", WeatherFragment::class.java)) INDEX_VIEWPAGER_ANDROID_STR -> pages.add(FragmentPagerItem.of("", WanAndroidFragment::class.java)) + INDEX_VIEWPAGER_MOVIE_STR -> pages.add(FragmentPagerItem.of("", MovieFragment::class.java)) INDEX_VIEWPAGER_ZHIHU_STR -> pages.add(FragmentPagerItem.of("", ZhiHuDailyFragment::class.java)) } } @@ -49,14 +49,15 @@ class IndexActivity : AppCompatActivity() { val res = this@IndexActivity.resources when (position) { - 0 -> icon.setImageDrawable(res.getDrawable(R.mipmap.index_icon_weather)) - 1 -> icon.setImageDrawable(res.getDrawable(R.mipmap.index_icon_android)) + 0 -> icon.setImageDrawable(res.getDrawable(R.mipmap.index_icon_android)) + 1 -> icon.setImageDrawable(res.getDrawable(R.mipmap.index_icon_douban)) 2 -> icon.setImageDrawable(res.getDrawable(R.mipmap.index_icon_zhihu)) else -> throw IllegalStateException("Invalid position: $position") } icon } + indexViewPager.offscreenPageLimit = 3 indexViewPager.adapter = FragmentPagerItemAdapter(supportFragmentManager, pages) indexTabLayout.setViewPager(indexViewPager) } diff --git a/app/src/main/java/com/leeeyou/movie/MovieFragment.kt b/app/src/main/java/com/leeeyou/movie/MovieFragment.kt new file mode 100644 index 0000000..7402086 --- /dev/null +++ b/app/src/main/java/com/leeeyou/movie/MovieFragment.kt @@ -0,0 +1,106 @@ +package com.leeeyou.movie + +import `in`.srain.cube.views.ptr.PtrFrameLayout +import `in`.srain.cube.views.ptr.PtrHandler +import `in`.srain.cube.views.ptr.header.StoreHouseHeader +import `in`.srain.cube.views.ptr.util.PtrLocalDisplay.dp2px +import android.os.Bundle +import android.support.v7.widget.GridLayoutManager +import android.support.v7.widget.LinearLayoutManager +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import com.bumptech.glide.Glide +import com.chad.library.adapter.base.BaseQuickAdapter +import com.chad.library.adapter.base.BaseViewHolder +import com.leeeyou.APP_NAME +import com.leeeyou.R +import com.leeeyou.manager.BaseFragment +import com.leeeyou.movie.model.bean.ResponseHotMovie +import com.leeeyou.movie.model.fetchHotMovieList +import com.leeeyou.util.HtmlUtils +import com.leeeyou.util.inflate +import kotlinx.android.synthetic.main.fragment_movie.* +import rx.android.schedulers.AndroidSchedulers +import rx.schedulers.Schedulers + +/** + * ClassName: MovieFragment + * Description: Movie + * + * Author: leeeyou + * Date: 2017/4/24 13:46 + */ +class MovieFragment : BaseFragment() { + private lateinit var mGridLayoutManager: LinearLayoutManager + private lateinit var mHotMovieAdapter: BaseQuickAdapter + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return container?.inflate(R.layout.fragment_movie) + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + initRecyclerView() + initPtrFrame() + fetchHotMovieListFromServer() + } + + private fun fetchHotMovieListFromServer() { + fetchHotMovieList().subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) + .doOnNext { it -> + it?.let { + mHotMovieAdapter.setNewData(ArrayList(it.subjects)) + recyclerViewMovie.smoothScrollToPosition(0) + } + }.doOnCompleted { + ptrFrameHotMovie?.refreshComplete() + }.subscribe() + } + + private fun initPtrFrame() { + initHeadView() + ptrFrameHotMovie.disableWhenHorizontalMove(true) + ptrFrameHotMovie.setPtrHandler(object : PtrHandler { + override fun onRefreshBegin(frame: PtrFrameLayout?) { + fetchHotMovieListFromServer() + } + + override fun checkCanDoRefresh(frame: PtrFrameLayout?, content: View?, header: View?): Boolean = + recyclerViewFirstItemCanVisible() + }) + } + + private fun recyclerViewFirstItemCanVisible() = + mGridLayoutManager.findFirstVisibleItemPosition() <= 0 + + private fun initHeadView() { + val header = StoreHouseHeader(context) + header.setTextColor(resources.getColor(R.color.default_red)) + header.setPadding(0, dp2px(15f), 0, 0) + header.initWithString(APP_NAME, 15) + ptrFrameHotMovie.headerView = header + ptrFrameHotMovie.addPtrUIHandler(header) + } + + private fun initRecyclerView() { + mGridLayoutManager = GridLayoutManager(context, 2) + mHotMovieAdapter = object : BaseQuickAdapter(R.layout.item_hot_movie, null) { + override fun convert(helper: BaseViewHolder?, item: ResponseHotMovie.SubjectsBean?) { + item?.also { + helper?.also { helper -> + helper.setText(R.id.tv_title, HtmlUtils.translation(it.title)) + .setText(R.id.tv_score, "评分:" + it.rating.average) + val imageView = helper.getView(R.id.iv_hot_movie) as ImageView + Glide.with(mContext).load(it.images.large).into(imageView) + } + } + } + } + mHotMovieAdapter.openLoadAnimation(BaseQuickAdapter.SCALEIN) + recyclerViewMovie.layoutManager = mGridLayoutManager + recyclerViewMovie.adapter = mHotMovieAdapter + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/movie/model/MovieRepository.kt b/app/src/main/java/com/leeeyou/movie/model/MovieRepository.kt new file mode 100644 index 0000000..ce8438d --- /dev/null +++ b/app/src/main/java/com/leeeyou/movie/model/MovieRepository.kt @@ -0,0 +1,14 @@ +package com.leeeyou.movie.model + +import com.leeeyou.movie.model.bean.ResponseHotMovie +import com.leeeyou.movie.service.MovieService +import com.leeeyou.service.ServiceFactory +import rx.Observable + +private const val endPoint = "https://api.douban.com/" + +fun fetchHotMovieList(): Observable { + return ServiceFactory + .createRxRetrofitService(MovieService::class.java, endPoint) + .getHotMovieList() +} \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/movie/model/bean/ResponseHotMovie.java b/app/src/main/java/com/leeeyou/movie/model/bean/ResponseHotMovie.java new file mode 100644 index 0000000..5566624 --- /dev/null +++ b/app/src/main/java/com/leeeyou/movie/model/bean/ResponseHotMovie.java @@ -0,0 +1,440 @@ +package com.leeeyou.movie.model.bean; + +import com.google.gson.Gson; + +import java.util.List; + +public class ResponseHotMovie { + + + /** + * count : 20 + * start : 0 + * total : 40 + * subjects : [{"rating":{"max":10,"average":7.3,"stars":"40","min":0},"genres":["动作","科幻","冒险"],"title":"大黄蜂","casts":[{"alt":"https://movie.douban.com/celebrity/1312964/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p20419.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p20419.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p20419.jpg"},"name":"海莉·斯坦菲尔德","id":"1312964"},{"alt":"https://movie.douban.com/celebrity/1376970/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1545624925.39.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1545624925.39.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1545624925.39.jpg"},"name":"小豪尔赫·兰登伯格","id":"1376970"},{"alt":"https://movie.douban.com/celebrity/1044883/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p23477.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p23477.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p23477.jpg"},"name":"约翰·塞纳","id":"1044883"}],"collect_count":131139,"original_title":"Bumblebee","subtype":"movie","directors":[{"alt":"https://movie.douban.com/celebrity/1305796/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1471358307.31.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1471358307.31.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1471358307.31.jpg"},"name":"特拉维斯·奈特","id":"1305796"}],"year":"2018","images":{"small":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2541662397.jpg","large":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2541662397.jpg","medium":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2541662397.jpg"},"alt":"https://movie.douban.com/subject/26394152/","id":"26394152"},{"rating":{"max":10,"average":7,"stars":"35","min":0},"genres":["动作","犯罪"],"title":"\u201c大\u201d人物","casts":[{"alt":"https://movie.douban.com/celebrity/1314827/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1445948736.67.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1445948736.67.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1445948736.67.jpg"},"name":"王千源","id":"1314827"},{"alt":"https://movie.douban.com/celebrity/1315866/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1545816620.37.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1545816620.37.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1545816620.37.jpg"},"name":"包贝尔","id":"1315866"},{"alt":"https://movie.douban.com/celebrity/1317139/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1371453539.51.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1371453539.51.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1371453539.51.jpg"},"name":"王迅","id":"1317139"}],"collect_count":4577,"original_title":"\u201c大\u201d人物","subtype":"movie","directors":[{"alt":"https://movie.douban.com/celebrity/1327592/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1505707565.9.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1505707565.9.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1505707565.9.jpg"},"name":"五百","id":"1327592"}],"year":"2019","images":{"small":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2544988187.jpg","large":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2544988187.jpg","medium":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2544988187.jpg"},"alt":"https://movie.douban.com/subject/26816076/","id":"26816076"},{"rating":{"max":10,"average":6,"stars":"30","min":0},"genres":["剧情","喜剧"],"title":"来电狂响","casts":[{"alt":"https://movie.douban.com/celebrity/1009179/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1542346320.44.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1542346320.44.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1542346320.44.jpg"},"name":"佟大为","id":"1009179"},{"alt":"https://movie.douban.com/celebrity/1319032/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1444800807.11.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1444800807.11.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1444800807.11.jpg"},"name":"马丽","id":"1319032"},{"alt":"https://movie.douban.com/celebrity/1000145/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p2520.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p2520.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p2520.jpg"},"name":"霍思燕","id":"1000145"}],"collect_count":92456,"original_title":"来电狂响","subtype":"movie","directors":[{"alt":"https://movie.douban.com/celebrity/1321152/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1483685290.54.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1483685290.54.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1483685290.54.jpg"},"name":"于淼","id":"1321152"}],"year":"2018","images":{"small":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2542268337.jpg","large":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2542268337.jpg","medium":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2542268337.jpg"},"alt":"https://movie.douban.com/subject/30377703/","id":"30377703"},{"rating":{"max":10,"average":7.8,"stars":"40","min":0},"genres":["动作","奇幻","冒险"],"title":"海王","casts":[{"alt":"https://movie.douban.com/celebrity/1022614/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p32853.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p32853.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p32853.jpg"},"name":"杰森·莫玛","id":"1022614"},{"alt":"https://movie.douban.com/celebrity/1044702/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p34697.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p34697.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p34697.jpg"},"name":"艾梅柏·希尔德","id":"1044702"},{"alt":"https://movie.douban.com/celebrity/1010539/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p9206.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p9206.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p9206.jpg"},"name":"威廉·达福","id":"1010539"}],"collect_count":665186,"original_title":"Aquaman","subtype":"movie","directors":[{"alt":"https://movie.douban.com/celebrity/1032122/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1509950363.8.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1509950363.8.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1509950363.8.jpg"},"name":"温子仁","id":"1032122"}],"year":"2018","images":{"small":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2541280047.jpg","large":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2541280047.jpg","medium":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2541280047.jpg"},"alt":"https://movie.douban.com/subject/3878007/","id":"3878007"},{"rating":{"max":10,"average":8.7,"stars":"45","min":0},"genres":["动作","科幻","动画"],"title":"蜘蛛侠:平行宇宙","casts":[{"alt":"https://movie.douban.com/celebrity/1350106/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1434437756.07.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1434437756.07.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1434437756.07.jpg"},"name":"沙梅克·摩尔","id":"1350106"},{"alt":"https://movie.douban.com/celebrity/1316713/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1449582908.84.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1449582908.84.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1449582908.84.jpg"},"name":"杰克·约翰逊","id":"1316713"},{"alt":"https://movie.douban.com/celebrity/1312964/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p20419.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p20419.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p20419.jpg"},"name":"海莉·斯坦菲尔德","id":"1312964"}],"collect_count":259110,"original_title":"Spider-Man: Into the Spider-Verse","subtype":"movie","directors":[{"alt":"https://movie.douban.com/celebrity/1310107/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1519064730.28.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1519064730.28.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1519064730.28.jpg"},"name":"鲍勃·佩尔西凯蒂","id":"1310107"},{"alt":"https://movie.douban.com/celebrity/1324415/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p59042.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p59042.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p59042.jpg"},"name":"彼得·拉姆齐","id":"1324415"},{"alt":"https://movie.douban.com/celebrity/1296189/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1543307159.85.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1543307159.85.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1543307159.85.jpg"},"name":"罗德尼·罗斯曼","id":"1296189"}],"year":"2018","images":{"small":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2542867516.jpg","large":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2542867516.jpg","medium":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2542867516.jpg"},"alt":"https://movie.douban.com/subject/26374197/","id":"26374197"},{"rating":{"max":10,"average":8.9,"stars":"45","min":0},"genres":["纪录片","家庭"],"title":"四个春天","casts":[{"alt":"https://movie.douban.com/celebrity/1405092/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1542942707.25.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1542942707.25.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1542942707.25.jpg"},"name":"陆运坤","id":"1405092"},{"alt":"https://movie.douban.com/celebrity/1405093/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1542942765.23.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1542942765.23.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1542942765.23.jpg"},"name":"李桂贤","id":"1405093"}],"collect_count":38439,"original_title":"四个春天","subtype":"movie","directors":[{"alt":"https://movie.douban.com/celebrity/1386569/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1533613477.28.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1533613477.28.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1533613477.28.jpg"},"name":"陆庆屹","id":"1386569"}],"year":"2017","images":{"small":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2540578887.jpg","large":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2540578887.jpg","medium":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2540578887.jpg"},"alt":"https://movie.douban.com/subject/27191492/","id":"27191492"},{"rating":{"max":10,"average":0,"stars":"00","min":0},"genres":["爱情","动画","奇幻"],"title":"白蛇:缘起","casts":[{"alt":"https://movie.douban.com/celebrity/1389748/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1520590413.89.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1520590413.89.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1520590413.89.jpg"},"name":"张喆","id":"1389748"},{"alt":"https://movie.douban.com/celebrity/1341265/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1439904943.23.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1439904943.23.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1439904943.23.jpg"},"name":"杨天翔","id":"1341265"},{"alt":"https://movie.douban.com/celebrity/1340810/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1501640829.72.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1501640829.72.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1501640829.72.jpg"},"name":"唐小喜","id":"1340810"}],"collect_count":1920,"original_title":"白蛇:缘起","subtype":"movie","directors":[{"alt":"https://movie.douban.com/celebrity/1401171/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1537807069.66.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1537807069.66.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1537807069.66.jpg"},"name":"黄家康","id":"1401171"},{"alt":"https://movie.douban.com/celebrity/1401175/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1537807088.34.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1537807088.34.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1537807088.34.jpg"},"name":"赵霁","id":"1401175"}],"year":"2019","images":{"small":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2544313786.jpg","large":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2544313786.jpg","medium":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2544313786.jpg"},"alt":"https://movie.douban.com/subject/30331149/","id":"30331149"},{"rating":{"max":10,"average":7.4,"stars":"40","min":0},"genres":["剧情","运动"],"title":"奎迪:英雄再起","casts":[{"alt":"https://movie.douban.com/celebrity/1107320/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1473330747.67.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1473330747.67.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1473330747.67.jpg"},"name":"迈克尔·B·乔丹","id":"1107320"},{"alt":"https://movie.douban.com/celebrity/1047996/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p262.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p262.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p262.jpg"},"name":"西尔维斯特·史泰龙","id":"1047996"},{"alt":"https://movie.douban.com/celebrity/1027395/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1509782172.11.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1509782172.11.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1509782172.11.jpg"},"name":"泰莎·汤普森","id":"1027395"}],"collect_count":10422,"original_title":"Creed II","subtype":"movie","directors":[{"alt":"https://movie.douban.com/celebrity/1391361/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1538121045.58.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1538121045.58.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1538121045.58.jpg"},"name":"小斯蒂芬·卡普尔","id":"1391361"}],"year":"2018","images":{"small":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2544510053.jpg","large":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2544510053.jpg","medium":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2544510053.jpg"},"alt":"https://movie.douban.com/subject/26707088/","id":"26707088"},{"rating":{"max":10,"average":6,"stars":"30","min":0},"genres":["喜剧","动作","冒险"],"title":"印度暴徒","casts":[{"alt":"https://movie.douban.com/celebrity/1031931/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p13628.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p13628.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p13628.jpg"},"name":"阿米尔·汗","id":"1031931"},{"alt":"https://movie.douban.com/celebrity/1010569/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p53718.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p53718.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p53718.jpg"},"name":"卡特莉娜·卡芙","id":"1010569"},{"alt":"https://movie.douban.com/celebrity/1027845/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p9190.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p9190.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p9190.jpg"},"name":"阿米达普·巴强","id":"1027845"}],"collect_count":10681,"original_title":"Thugs of Hindostan","subtype":"movie","directors":[{"alt":"https://movie.douban.com/celebrity/1308426/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1495324131.21.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1495324131.21.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1495324131.21.jpg"},"name":"维贾伊·克利须那·阿查里雅","id":"1308426"}],"year":"2018","images":{"small":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2541754700.jpg","large":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2541754700.jpg","medium":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2541754700.jpg"},"alt":"https://movie.douban.com/subject/27019982/","id":"27019982"},{"rating":{"max":10,"average":9.1,"stars":"45","min":0},"genres":["动画","奇幻","冒险"],"title":"龙猫","casts":[{"alt":"https://movie.douban.com/celebrity/1019382/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1455201170.02.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1455201170.02.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1455201170.02.jpg"},"name":"日高法子","id":"1019382"},{"alt":"https://movie.douban.com/celebrity/1025582/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p29537.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p29537.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p29537.jpg"},"name":"坂本千夏","id":"1025582"},{"alt":"https://movie.douban.com/celebrity/1379738/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1503457262.72.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1503457262.72.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1503457262.72.jpg"},"name":"糸井重里","id":"1379738"}],"collect_count":844146,"original_title":"となりのトトロ","subtype":"movie","directors":[{"alt":"https://movie.douban.com/celebrity/1054439/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p616.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p616.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p616.jpg"},"name":"宫崎骏","id":"1054439"}],"year":"1988","images":{"small":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2540924496.jpg","large":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2540924496.jpg","medium":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2540924496.jpg"},"alt":"https://movie.douban.com/subject/1291560/","id":"1291560"},{"rating":{"max":10,"average":3.5,"stars":"20","min":0},"genres":["动作","奇幻","冒险"],"title":"云南虫谷","casts":[{"alt":"https://movie.douban.com/celebrity/1318565/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1543907920.47.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1543907920.47.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1543907920.47.jpg"},"name":"蔡珩","id":"1318565"},{"alt":"https://movie.douban.com/celebrity/1316959/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1538706988.45.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1538706988.45.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1538706988.45.jpg"},"name":"顾璇","id":"1316959"},{"alt":"https://movie.douban.com/celebrity/1363813/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1543907688.08.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1543907688.08.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1543907688.08.jpg"},"name":"于恒","id":"1363813"}],"collect_count":20990,"original_title":"云南虫谷","subtype":"movie","directors":[{"alt":"https://movie.douban.com/celebrity/1320824/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1543204019.02.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1543204019.02.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1543204019.02.jpg"},"name":"非行","id":"1320824"}],"year":"2018","images":{"small":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2542212636.jpg","large":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2542212636.jpg","medium":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2542212636.jpg"},"alt":"https://movie.douban.com/subject/26744597/","id":"26744597"},{"rating":{"max":10,"average":7,"stars":"35","min":0},"genres":["剧情","爱情","悬疑"],"title":"地球最后的夜晚","casts":[{"alt":"https://movie.douban.com/celebrity/1025141/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1507363720.81.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1507363720.81.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1507363720.81.jpg"},"name":"汤唯","id":"1025141"},{"alt":"https://movie.douban.com/celebrity/1275273/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1534406418.87.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1534406418.87.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1534406418.87.jpg"},"name":"黄觉","id":"1275273"},{"alt":"https://movie.douban.com/celebrity/1012646/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1494561948.78.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1494561948.78.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1494561948.78.jpg"},"name":"张艾嘉","id":"1012646"}],"collect_count":135183,"original_title":"地球最后的夜晚","subtype":"movie","directors":[{"alt":"https://movie.douban.com/celebrity/1324480/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1447134443.47.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1447134443.47.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1447134443.47.jpg"},"name":"毕赣","id":"1324480"}],"year":"2018","images":{"small":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2541183610.jpg","large":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2541183610.jpg","medium":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2541183610.jpg"},"alt":"https://movie.douban.com/subject/26633257/","id":"26633257"},{"rating":{"max":10,"average":2.6,"stars":"15","min":0},"genres":["喜剧","冒险"],"title":"断片之险途夺宝","casts":[{"alt":"https://movie.douban.com/celebrity/1000905/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p46.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p46.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p46.jpg"},"name":"葛优","id":"1000905"},{"alt":"https://movie.douban.com/celebrity/1317663/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p40756.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p40756.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p40756.jpg"},"name":"岳云鹏","id":"1317663"},{"alt":"https://movie.douban.com/celebrity/1016663/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1536658358.18.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1536658358.18.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1536658358.18.jpg"},"name":"杜淳","id":"1016663"}],"collect_count":8367,"original_title":"断片之险途夺宝","subtype":"movie","directors":[{"alt":"https://movie.douban.com/celebrity/1324612/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/pbYO4zDByocwcel_avatar_uploaded1352024636.33.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/pbYO4zDByocwcel_avatar_uploaded1352024636.33.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/pbYO4zDByocwcel_avatar_uploaded1352024636.33.jpg"},"name":"罗登","id":"1324612"}],"year":"2018","images":{"small":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2541553709.jpg","large":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2541553709.jpg","medium":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2541553709.jpg"},"alt":"https://movie.douban.com/subject/26882457/","id":"26882457"},{"rating":{"max":10,"average":0,"stars":"00","min":0},"genres":["犯罪","悬疑"],"title":"沉默的雪","casts":[{"alt":"https://movie.douban.com/celebrity/1400479/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1536388455.52.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1536388455.52.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1536388455.52.jpg"},"name":"任宇","id":"1400479"},{"alt":"https://movie.douban.com/celebrity/1365297/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1506857301.82.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1506857301.82.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1506857301.82.jpg"},"name":"陈绿","id":"1365297"},{"alt":"https://movie.douban.com/celebrity/1406635/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1544683064.31.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1544683064.31.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1544683064.31.jpg"},"name":"王笙","id":"1406635"}],"collect_count":188,"original_title":"沉默的雪","subtype":"movie","directors":[{"alt":"https://movie.douban.com/celebrity/1406634/","avatars":{"small":"https://img1.doubanio.com/f/movie/ca527386eb8c4e325611e22dfcb04cc116d6b423/pics/movie/celebrity-default-small.png","large":"https://img3.doubanio.com/f/movie/63acc16ca6309ef191f0378faf793d1096a3e606/pics/movie/celebrity-default-large.png","medium":"https://img1.doubanio.com/f/movie/8dd0c794499fe925ae2ae89ee30cd225750457b4/pics/movie/celebrity-default-medium.png"},"name":"风剑","id":"1406634"}],"year":"2019","images":{"small":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2543163892.jpg","large":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2543163892.jpg","medium":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2543163892.jpg"},"alt":"https://movie.douban.com/subject/30402144/","id":"30402144"},{"rating":{"max":10,"average":6.5,"stars":"35","min":0},"genres":["喜剧","动画","奇幻"],"title":"绿毛怪格林奇","casts":[{"alt":"https://movie.douban.com/celebrity/1009405/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p41072.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p41072.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p41072.jpg"},"name":"本尼迪克特·康伯巴奇","id":"1009405"},{"alt":"https://movie.douban.com/celebrity/1387860/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1517222739.45.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1517222739.45.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1517222739.45.jpg"},"name":"卡梅伦·丝蕾","id":"1387860"},{"alt":"https://movie.douban.com/celebrity/1031815/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p32735.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p32735.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p32735.jpg"},"name":"拉什达·琼斯","id":"1031815"}],"collect_count":6954,"original_title":"The Grinch","subtype":"movie","directors":[{"alt":"https://movie.douban.com/celebrity/1280591/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1467266335.21.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1467266335.21.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1467266335.21.jpg"},"name":"亚罗·切尼","id":"1280591"},{"alt":"https://movie.douban.com/celebrity/1032291/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p34173.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p34173.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p34173.jpg"},"name":"斯科特·摩西尔","id":"1032291"}],"year":"2018","images":{"small":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2539666559.jpg","large":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2539666559.jpg","medium":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2539666559.jpg"},"alt":"https://movie.douban.com/subject/23774869/","id":"23774869"},{"rating":{"max":10,"average":5.9,"stars":"30","min":0},"genres":["剧情","动作"],"title":"叶问外传:张天志","casts":[{"alt":"https://movie.douban.com/celebrity/1318005/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1436716618.28.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1436716618.28.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1436716618.28.jpg"},"name":"张晋","id":"1318005"},{"alt":"https://movie.douban.com/celebrity/1014003/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1493202154.34.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1493202154.34.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1493202154.34.jpg"},"name":"戴夫·巴蒂斯塔","id":"1014003"},{"alt":"https://movie.douban.com/celebrity/1312846/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p39129.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p39129.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p39129.jpg"},"name":"柳岩","id":"1312846"}],"collect_count":11674,"original_title":"葉問外傳:張天志","subtype":"movie","directors":[{"alt":"https://movie.douban.com/celebrity/1275026/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p9332.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p9332.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p9332.jpg"},"name":"袁和平","id":"1275026"}],"year":"2018","images":{"small":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2542380253.jpg","large":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2542380253.jpg","medium":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2542380253.jpg"},"alt":"https://movie.douban.com/subject/26796664/","id":"26796664"},{"rating":{"max":10,"average":8.1,"stars":"40","min":0},"genres":["剧情","喜剧"],"title":"无名之辈","casts":[{"alt":"https://movie.douban.com/celebrity/1274626/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1415455964.31.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1415455964.31.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1415455964.31.jpg"},"name":"陈建斌","id":"1274626"},{"alt":"https://movie.douban.com/celebrity/1362973/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1478066140.77.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1478066140.77.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1478066140.77.jpg"},"name":"任素汐","id":"1362973"},{"alt":"https://movie.douban.com/celebrity/1316365/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1541855083.14.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1541855083.14.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1541855083.14.jpg"},"name":"潘斌龙","id":"1316365"}],"collect_count":600078,"original_title":"无名之辈","subtype":"movie","directors":[{"alt":"https://movie.douban.com/celebrity/1326752/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1541992522.36.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1541992522.36.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1541992522.36.jpg"},"name":"饶晓志","id":"1326752"}],"year":"2018","images":{"small":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2539661066.jpg","large":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2539661066.jpg","medium":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2539661066.jpg"},"alt":"https://movie.douban.com/subject/27110296/","id":"27110296"},{"rating":{"max":10,"average":4,"stars":"20","min":0},"genres":["喜剧","奇幻"],"title":"天气预爆","casts":[{"alt":"https://movie.douban.com/celebrity/1274979/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1518431956.11.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1518431956.11.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1518431956.11.jpg"},"name":"肖央","id":"1274979"},{"alt":"https://movie.douban.com/celebrity/1323516/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1368850348.93.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1368850348.93.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1368850348.93.jpg"},"name":"杜鹃","id":"1323516"},{"alt":"https://movie.douban.com/celebrity/1327084/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1363597076.12.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1363597076.12.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1363597076.12.jpg"},"name":"常远","id":"1327084"}],"collect_count":21304,"original_title":"天气预爆","subtype":"movie","directors":[{"alt":"https://movie.douban.com/celebrity/1274979/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1518431956.11.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1518431956.11.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1518431956.11.jpg"},"name":"肖央","id":"1274979"}],"year":"2018","images":{"small":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2543353290.jpg","large":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2543353290.jpg","medium":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2543353290.jpg"},"alt":"https://movie.douban.com/subject/26994789/","id":"26994789"},{"rating":{"max":10,"average":6.9,"stars":"35","min":0},"genres":["剧情"],"title":"神探狗笨吉","casts":[{"alt":"https://movie.douban.com/celebrity/1358708/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/pkgttz5tui54cel_avatar_uploaded1464968611.11.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/pkgttz5tui54cel_avatar_uploaded1464968611.11.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/pkgttz5tui54cel_avatar_uploaded1464968611.11.jpg"},"name":"加布里埃尔·贝特曼","id":"1358708"},{"alt":"https://movie.douban.com/celebrity/1369479/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1488088653.09.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1488088653.09.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1488088653.09.jpg"},"name":"达比·坎普","id":"1369479"},{"alt":"https://movie.douban.com/celebrity/1027256/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p19702.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p19702.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p19702.jpg"},"name":"基拉·桑切斯","id":"1027256"}],"collect_count":2417,"original_title":"Benji","subtype":"movie","directors":[{"alt":"https://movie.douban.com/celebrity/1369948/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1522748236.29.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1522748236.29.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1522748236.29.jpg"},"name":"布兰登·坎普","id":"1369948"}],"year":"2018","images":{"small":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2541725145.jpg","large":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2541725145.jpg","medium":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2541725145.jpg"},"alt":"https://movie.douban.com/subject/26895438/","id":"26895438"},{"rating":{"max":10,"average":0,"stars":"00","min":0},"genres":["剧情"],"title":"大微商","casts":[{"alt":"https://movie.douban.com/celebrity/1406780/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1544880033.03.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1544880033.03.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1544880033.03.jpg"},"name":"刘东浒","id":"1406780"},{"alt":"https://movie.douban.com/celebrity/1313238/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p15699.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p15699.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p15699.jpg"},"name":"程媛媛","id":"1313238"},{"alt":"https://movie.douban.com/celebrity/1037662/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1357290860.44.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1357290860.44.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1357290860.44.jpg"},"name":"李子雄","id":"1037662"}],"collect_count":385,"original_title":"大微商","subtype":"movie","directors":[{"alt":"https://movie.douban.com/celebrity/1406781/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1544880983.71.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1544880983.71.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1544880983.71.jpg"},"name":"李锐","id":"1406781"}],"year":"2019","images":{"small":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2544995150.jpg","large":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2544995150.jpg","medium":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2544995150.jpg"},"alt":"https://movie.douban.com/subject/30400471/","id":"30400471"}] + * title : 正在上映的电影-北京 + */ + + private int count; + private int start; + private int total; + private String title; + private List subjects; + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + public int getStart() { + return start; + } + + public void setStart(int start) { + this.start = start; + } + + public int getTotal() { + return total; + } + + public void setTotal(int total) { + this.total = total; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public List getSubjects() { + return subjects; + } + + public void setSubjects(List subjects) { + this.subjects = subjects; + } + + public static class SubjectsBean { + /** + * rating : {"max":10,"average":7.3,"stars":"40","min":0} + * genres : ["动作","科幻","冒险"] + * title : 大黄蜂 + * casts : [{"alt":"https://movie.douban.com/celebrity/1312964/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p20419.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p20419.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p20419.jpg"},"name":"海莉·斯坦菲尔德","id":"1312964"},{"alt":"https://movie.douban.com/celebrity/1376970/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1545624925.39.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1545624925.39.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1545624925.39.jpg"},"name":"小豪尔赫·兰登伯格","id":"1376970"},{"alt":"https://movie.douban.com/celebrity/1044883/","avatars":{"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p23477.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p23477.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p23477.jpg"},"name":"约翰·塞纳","id":"1044883"}] + * collect_count : 131139 + * original_title : Bumblebee + * subtype : movie + * directors : [{"alt":"https://movie.douban.com/celebrity/1305796/","avatars":{"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1471358307.31.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1471358307.31.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1471358307.31.jpg"},"name":"特拉维斯·奈特","id":"1305796"}] + * year : 2018 + * images : {"small":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2541662397.jpg","large":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2541662397.jpg","medium":"https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2541662397.jpg"} + * alt : https://movie.douban.com/subject/26394152/ + * id : 26394152 + */ + + private RatingBean rating; + private String title; + private int collect_count; + private String original_title; + private String subtype; + private String year; + private ImagesBean images; + private String alt; + private String id; + private List genres; + private List casts; + private List directors; + + public RatingBean getRating() { + return rating; + } + + public void setRating(RatingBean rating) { + this.rating = rating; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public int getCollect_count() { + return collect_count; + } + + public void setCollect_count(int collect_count) { + this.collect_count = collect_count; + } + + public String getOriginal_title() { + return original_title; + } + + public void setOriginal_title(String original_title) { + this.original_title = original_title; + } + + public String getSubtype() { + return subtype; + } + + public void setSubtype(String subtype) { + this.subtype = subtype; + } + + public String getYear() { + return year; + } + + public void setYear(String year) { + this.year = year; + } + + public ImagesBean getImages() { + return images; + } + + public void setImages(ImagesBean images) { + this.images = images; + } + + public String getAlt() { + return alt; + } + + public void setAlt(String alt) { + this.alt = alt; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public List getGenres() { + return genres; + } + + public void setGenres(List genres) { + this.genres = genres; + } + + public List getCasts() { + return casts; + } + + public void setCasts(List casts) { + this.casts = casts; + } + + public List getDirectors() { + return directors; + } + + public void setDirectors(List directors) { + this.directors = directors; + } + + public static class RatingBean { + /** + * max : 10 + * average : 7.3 + * stars : 40 + * min : 0 + */ + + private int max; + private double average; + private String stars; + private int min; + + public int getMax() { + return max; + } + + public void setMax(int max) { + this.max = max; + } + + public double getAverage() { + return average; + } + + public void setAverage(double average) { + this.average = average; + } + + public String getStars() { + return stars; + } + + public void setStars(String stars) { + this.stars = stars; + } + + public int getMin() { + return min; + } + + public void setMin(int min) { + this.min = min; + } + } + + public static class ImagesBean { + /** + * small : https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2541662397.jpg + * large : https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2541662397.jpg + * medium : https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2541662397.jpg + */ + + private String small; + private String large; + private String medium; + + public String getSmall() { + return small; + } + + public void setSmall(String small) { + this.small = small; + } + + public String getLarge() { + return large; + } + + public void setLarge(String large) { + this.large = large; + } + + public String getMedium() { + return medium; + } + + public void setMedium(String medium) { + this.medium = medium; + } + } + + public static class CastsBean { + /** + * alt : https://movie.douban.com/celebrity/1312964/ + * avatars : {"small":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p20419.jpg","large":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p20419.jpg","medium":"https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p20419.jpg"} + * name : 海莉·斯坦菲尔德 + * id : 1312964 + */ + + private String alt; + private AvatarsBean avatars; + private String name; + private String id; + + public String getAlt() { + return alt; + } + + public void setAlt(String alt) { + this.alt = alt; + } + + public AvatarsBean getAvatars() { + return avatars; + } + + public void setAvatars(AvatarsBean avatars) { + this.avatars = avatars; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public static class AvatarsBean { + /** + * small : https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p20419.jpg + * large : https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p20419.jpg + * medium : https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p20419.jpg + */ + + private String small; + private String large; + private String medium; + + public String getSmall() { + return small; + } + + public void setSmall(String small) { + this.small = small; + } + + public String getLarge() { + return large; + } + + public void setLarge(String large) { + this.large = large; + } + + public String getMedium() { + return medium; + } + + public void setMedium(String medium) { + this.medium = medium; + } + } + } + + public static class DirectorsBean { + /** + * alt : https://movie.douban.com/celebrity/1305796/ + * avatars : {"small":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1471358307.31.jpg","large":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1471358307.31.jpg","medium":"https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1471358307.31.jpg"} + * name : 特拉维斯·奈特 + * id : 1305796 + */ + + private String alt; + private AvatarsBeanX avatars; + private String name; + private String id; + + public String getAlt() { + return alt; + } + + public void setAlt(String alt) { + this.alt = alt; + } + + public AvatarsBeanX getAvatars() { + return avatars; + } + + public void setAvatars(AvatarsBeanX avatars) { + this.avatars = avatars; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public static class AvatarsBeanX { + /** + * small : https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1471358307.31.jpg + * large : https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1471358307.31.jpg + * medium : https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1471358307.31.jpg + */ + + private String small; + private String large; + private String medium; + + public String getSmall() { + return small; + } + + public void setSmall(String small) { + this.small = small; + } + + public String getLarge() { + return large; + } + + public void setLarge(String large) { + this.large = large; + } + + public String getMedium() { + return medium; + } + + public void setMedium(String medium) { + this.medium = medium; + } + } + } + } + + @Override + public String toString() { + return new Gson().toJson(this); + } +} diff --git a/app/src/main/java/com/leeeyou/movie/service/MovieService.kt b/app/src/main/java/com/leeeyou/movie/service/MovieService.kt new file mode 100644 index 0000000..a39c00e --- /dev/null +++ b/app/src/main/java/com/leeeyou/movie/service/MovieService.kt @@ -0,0 +1,10 @@ +package com.leeeyou.movie.service + +import com.leeeyou.movie.model.bean.ResponseHotMovie +import retrofit2.http.GET +import rx.Observable + +interface MovieService { + @GET("v2/movie/in_theaters") + fun getHotMovieList(): Observable +} \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/service/converter/MyGsonConverter.java b/app/src/main/java/com/leeeyou/service/converter/MyGsonConverter.java index 5c592a4..a885635 100644 --- a/app/src/main/java/com/leeeyou/service/converter/MyGsonConverter.java +++ b/app/src/main/java/com/leeeyou/service/converter/MyGsonConverter.java @@ -28,7 +28,7 @@ public MyGsonConverter(Gson gson, Type type) { @Override public T convert(@NonNull ResponseBody responseBody) throws IOException { String responseStr = responseBody.string(); - Timber.d("The responseStr is %s ", responseStr); +// Timber.d("The responseStr is %s ", responseStr); if (TextUtils.isEmpty(responseStr)) { HttpErrorResponseEntity errorResponse = new HttpErrorResponseEntity(-200, "The result of the request is returned as null"); HttpResultException resultException = new HttpResultException(errorResponse.getErrorCode(), errorResponse.getErrorMsg()); diff --git a/app/src/main/java/com/leeeyou/weather/WeatherFragment.kt b/app/src/main/java/com/leeeyou/weather/WeatherFragment.kt deleted file mode 100644 index e06073e..0000000 --- a/app/src/main/java/com/leeeyou/weather/WeatherFragment.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.leeeyou.weather - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import com.leeeyou.R -import com.leeeyou.manager.BaseFragment -import com.leeeyou.util.inflate - -/** - * ClassName: WeatherFragment - * Description: Show Weather - * - * Author: leeeyou - * Date: 2017/4/24 13:46 - */ -class WeatherFragment : BaseFragment() { - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return container?.inflate(R.layout.fragment_weather) - } - -} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_weather.xml b/app/src/main/res/layout/fragment_movie.xml similarity index 51% rename from app/src/main/res/layout/fragment_weather.xml rename to app/src/main/res/layout/fragment_movie.xml index e45aee9..df7e655 100644 --- a/app/src/main/res/layout/fragment_weather.xml +++ b/app/src/main/res/layout/fragment_movie.xml @@ -1,7 +1,17 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_hot_movie.xml b/app/src/main/res/layout/item_hot_movie.xml new file mode 100644 index 0000000..9658130 --- /dev/null +++ b/app/src/main/res/layout/item_hot_movie.xml @@ -0,0 +1,44 @@ + + + + + + + + + + diff --git a/app/src/main/res/mipmap-xhdpi/index_icon_douban.png b/app/src/main/res/mipmap-xhdpi/index_icon_douban.png new file mode 100644 index 0000000000000000000000000000000000000000..705707ad5922c51dcec770d987da4b523507def6 GIT binary patch literal 1163 zcmV;61a$j}P)MR;SY$~>k)49*vSitOhkf=pd(X^1`+Ob21>eKRUTe+z?U`A#W^Hkd zi;nU5ISvq;K{J~RoL77HD{w&4FMZB>FEe0fbAX$Gn}HjEb6bM^7I+WX3ha>d?__{F z1DKiHt^(Ermv;=}Yv6g{1xY`5@zDvu%&ratU(sdIh|L)A81Rgwze{`;0hrl|z|+7w zn34qWF>t%2A9EqH0nF@l;0@r$T<0D2z6X{{`Ygvj3m|OL_kl}uoc5se2XL#T4^zI9 z0A@A|_ym}ja@Oo1e^c72Q{fGxniEdhN4+}~rsZvkf{{B4)CGzk#W<_`^P zabUk!()_*v%*@9-E8*`S*Qr;tLo;Az%Yj!C&L#ku*?oYQ8M$&;(whV2OaND3F6p)E zATfYVz}i9pKRIXQMi14zos>Uo70CEnps*iD}X6DtagS5##l3wpPR@Onb0(iM#23&QGq!&X_9|6}j z*zX4}^JbQrodfv)QwzpgA!$OH6War40$yAd)i%IfNk5s{Er4G`W3o=ta{+WS;5AgP z{0Ypio&j#yR8D&U9!QC7l=N`8M<1x&ZQYM&4o`t&9q$`kBn<&K0o(=*T^@i#UWheN z9g^ggtS5p80RL6x9Z64x=WBqK5kE~=N&^;18oFe)T`B$ETffG=Bx!ZYw3O&Zx)KBP zZIbSY`Dz1L417>C@}>1eNl=BluL5V+Z2t1*u_WK{Ly~H%c)DwBX%q(6Regh`$D52( z0A8K$0WRn|`XufA(DOd2?}4b~v=%P`{B$05dEq^&MfJ2XtZ{wF?InlKWL~~! zn$!X~k!9F=U3F)*;%u|Y1_%(|`tVFtQtV~Kd{o8P`Ln!9No@KD98CIbdCdz d;w`t0aRe9A*Fj002ovPDHLkV1if*B-sD} literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/index_icon_weather.png b/app/src/main/res/mipmap-xhdpi/index_icon_weather.png deleted file mode 100644 index 7952ab4b23c2bf3246dd72bd328ffca2832e3e96..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1046 zcmV+x1nK*UP)zb#I&SESxJaeEpt)05rq~NT^2%%F1jcz!4w09 zD5;<*i=>-GrJ)dokVH4ru4+B;pWY+yH_gm9=VNrd=ZFCp4LE*A z3G~~7qZSw#3q-^W;Gm>``VBgNe^)LP5!-+}fUkh*lKyT*A|mDiGl6ZA{x};%yCv`! zFg^jAE9s+Va1pTpcr*R~lBC;8BJgaozyV-hD+@%#QsCtTdbgw-D*_R5DPTf30seg< zZ~^cu@B{EI@D{K`(&u%EcV&TY4vYv}=zd@p@R+0n5pf;x5HLTT5zw~wRM)-)9tO5b z@_!wrHi3v31Iz`^1AYg-kn~&rmK5+C09)ZCaL#Z*vg?kou|5~LSJK;^p6!}IL@WmG z1a1Zio)B)a%^AuoZt&{Y4I})b}M8xyJBAZ;&)0zKT)0=_YJ808d z^I6{jmjRtzrG_z1-?|-GCCSNTh%^X9#2nzmbmf?&hK3`;rrZrI?BKg20aW)HD`<

)GVY?pL2A}$8L1}5}b`#D~B z0ar@;topO9W+TGdUk^;IsiiY{yItuuNvGg>4wSCErO3XyASIa8` ztAIxUr=}H>PDX@_+5^C~rKvyRaXnc4zaWkX4;pTs+}M>WZWcF7x_bzLh&UJUMC6Xr zt!$~{u5^Q>_00s_)2}QvaC2okQ@XL+l&8_Wr7l(TIj&129mxsU?{6Id?VH4YNwbHv z5)tup+7y(oefL5xVjlee>xCj>3h-0u$P>O}fZeCDNT>*SS95p(2za1bBk73>Yeirj z;M7!d>hv(PADAP_twcleAb#Ilw?eI8&Hng_QPAjy^_4`t|h$!RO_X^ym^#BFSR+6vqmj260P;}nSr;!zotDiK*rpn QssI2007*qoM6N<$f=x8*4*&oF From ea7f713f86567114a969e1e409531a98d2eecf8f Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Thu, 10 Jan 2019 22:03:18 +0800 Subject: [PATCH 079/150] Update HeadView Text --- .../main/java/com/leeeyou/IndexActivity.kt | 1 - .../java/com/leeeyou/movie/MovieFragment.kt | 3 +-- .../com/leeeyou/movie/service/MovieService.kt | 19 +++++++++++++++++++ .../wanandroid/WanAndroidProjectFragment.kt | 3 +-- .../wanandroid/WanAndroidRecommendFragment.kt | 3 +-- .../wanandroid/WanAndroidSystemFragment.kt | 3 +-- .../zhihudaily/view/ZhiHuDailyFragment.kt | 3 +-- 7 files changed, 24 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/leeeyou/IndexActivity.kt b/app/src/main/java/com/leeeyou/IndexActivity.kt index c6929da..e7b954b 100644 --- a/app/src/main/java/com/leeeyou/IndexActivity.kt +++ b/app/src/main/java/com/leeeyou/IndexActivity.kt @@ -16,7 +16,6 @@ import kotlinx.android.synthetic.main.activity_index.* private const val INDEX_VIEWPAGER_MOVIE_STR = "天气" private const val INDEX_VIEWPAGER_ANDROID_STR = "安卓" private const val INDEX_VIEWPAGER_ZHIHU_STR = "知乎" -const val APP_NAME = "RsKotlin" /** * ClassName: IndexActivity diff --git a/app/src/main/java/com/leeeyou/movie/MovieFragment.kt b/app/src/main/java/com/leeeyou/movie/MovieFragment.kt index 7402086..b01f2b1 100644 --- a/app/src/main/java/com/leeeyou/movie/MovieFragment.kt +++ b/app/src/main/java/com/leeeyou/movie/MovieFragment.kt @@ -14,7 +14,6 @@ import android.widget.ImageView import com.bumptech.glide.Glide import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.BaseViewHolder -import com.leeeyou.APP_NAME import com.leeeyou.R import com.leeeyou.manager.BaseFragment import com.leeeyou.movie.model.bean.ResponseHotMovie @@ -79,7 +78,7 @@ class MovieFragment : BaseFragment() { val header = StoreHouseHeader(context) header.setTextColor(resources.getColor(R.color.default_red)) header.setPadding(0, dp2px(15f), 0, 0) - header.initWithString(APP_NAME, 15) + header.initWithString("Being Hot", 15) ptrFrameHotMovie.headerView = header ptrFrameHotMovie.addPtrUIHandler(header) } diff --git a/app/src/main/java/com/leeeyou/movie/service/MovieService.kt b/app/src/main/java/com/leeeyou/movie/service/MovieService.kt index a39c00e..580a460 100644 --- a/app/src/main/java/com/leeeyou/movie/service/MovieService.kt +++ b/app/src/main/java/com/leeeyou/movie/service/MovieService.kt @@ -2,9 +2,28 @@ package com.leeeyou.movie.service import com.leeeyou.movie.model.bean.ResponseHotMovie import retrofit2.http.GET +import retrofit2.http.Path +import retrofit2.http.Query import rx.Observable interface MovieService { @GET("v2/movie/in_theaters") fun getHotMovieList(): Observable + + /** + * 获取电影详情 + * + * @param id 电影bean里的id + */ + @GET("v2/movie/subject/{id}") + fun fetchMovieDetail(@Path("id") id: String): Observable + + /** + * 获取豆瓣电影top250 + * + * @param start 从多少开始,如从"0"开始 + * @param count 一次请求的数目,如"10"条,最多100 + */ + @GET("v2/movie/top250") + fun fetchMovieTop250(@Query("start") start: Int, @Query("count") count: Int): Observable } \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt index 1b7009f..fafdc60 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt @@ -17,7 +17,6 @@ import android.widget.TextView import com.bumptech.glide.Glide import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.BaseViewHolder -import com.leeeyou.APP_NAME import com.leeeyou.R import com.leeeyou.manager.BaseFragment import com.leeeyou.manager.MyAnimationListener @@ -242,7 +241,7 @@ class WanAndroidProjectFragment : BaseFragment() { val header = StoreHouseHeader(context) header.setTextColor(resources.getColor(R.color.default_red)) header.setPadding(0, dp2px(15f), 0, 0) - header.initWithString(APP_NAME, 15) + header.initWithString("Play Android", 15) ptrFrameProject.headerView = header ptrFrameProject.addPtrUIHandler(header) } diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt index 679f62f..62b5635 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt @@ -14,7 +14,6 @@ import android.widget.ImageView import com.bumptech.glide.Glide import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.BaseViewHolder -import com.leeeyou.APP_NAME import com.leeeyou.R import com.leeeyou.manager.BaseFragment import com.leeeyou.manager.MyLoadMoreView @@ -125,7 +124,7 @@ class WanAndroidRecommendFragment : BaseFragment() { val header = StoreHouseHeader(context) header.setTextColor(resources.getColor(R.color.default_red)) header.setPadding(0, dp2px(15f), 0, 0) - header.initWithString(APP_NAME, 15) + header.initWithString("Play Android", 15) ptrFrameRecommend.headerView = header ptrFrameRecommend.addPtrUIHandler(header) } diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt index 8ea65a8..28419ca 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt @@ -16,7 +16,6 @@ import android.view.animation.RotateAnimation import android.widget.TextView import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.BaseViewHolder -import com.leeeyou.APP_NAME import com.leeeyou.R import com.leeeyou.manager.BaseFragment import com.leeeyou.manager.MyAnimationListener @@ -142,7 +141,7 @@ class WanAndroidSystemFragment : BaseFragment() { val header = StoreHouseHeader(context) header.setTextColor(resources.getColor(R.color.default_red)) header.setPadding(0, dp2px(15f), 0, 0) - header.initWithString(APP_NAME, 15) + header.initWithString("Play Android", 15) ptrFrameSystemTag.headerView = header ptrFrameSystemTag.addPtrUIHandler(header) } diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt index f79b68f..ba875a2 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt @@ -10,7 +10,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import com.chad.library.adapter.base.BaseQuickAdapter -import com.leeeyou.APP_NAME import com.leeeyou.R import com.leeeyou.manager.BaseFragment import com.leeeyou.manager.MyLoadMoreView @@ -77,7 +76,7 @@ class ZhiHuDailyFragment : BaseFragment() { val header = StoreHouseHeader(context) header.setTextColor(resources.getColor(R.color.default_red)) header.setPadding(0, dp2px(15f), 0, 0) - header.initWithString(APP_NAME, 15) + header.initWithString("ZhiHu Daily", 15) ptrFrameOfZhiHuDaily.headerView = header ptrFrameOfZhiHuDaily.addPtrUIHandler(header) } From a3483c734f38371f39c5d23ad96a7c218153c6ab Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Fri, 11 Jan 2019 20:14:17 +0800 Subject: [PATCH 080/150] Import StatusBar --- app/build.gradle | 3 + app/src/main/AndroidManifest.xml | 8 ++- .../main/java/com/leeeyou/IndexActivity.kt | 9 ++- .../manager/sonic/BrowserActivity.java | 3 +- app/src/main/res/layout/activity_index.xml | 59 ++++++++++++------- app/src/main/res/values-v19/dimens.xml | 5 -- app/src/main/res/values-v19/styles.xml | 16 ----- app/src/main/res/values-v21/dimens.xml | 5 -- app/src/main/res/values-v21/styles.xml | 17 ------ app/src/main/res/values/styles.xml | 13 +++- 10 files changed, 66 insertions(+), 72 deletions(-) delete mode 100644 app/src/main/res/values-v19/dimens.xml delete mode 100644 app/src/main/res/values-v19/styles.xml delete mode 100644 app/src/main/res/values-v21/dimens.xml delete mode 100644 app/src/main/res/values-v21/styles.xml diff --git a/app/build.gradle b/app/build.gradle index 233ffc9..851b93f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -111,4 +111,7 @@ dependencies { //smarttablayout implementation 'com.ogaclejapan.smarttablayout:library:1.6.1@aar' implementation 'com.ogaclejapan.smarttablayout:utils-v4:1.6.1@aar' + + //statusbar + implementation 'com.jaeger.statusbarutil:library:1.5.1' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 22e44fe..3abcf03 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -18,7 +18,9 @@ android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> - + @@ -43,7 +45,9 @@ + android:launchMode="singleTop" + android:screenOrientation="portrait" + android:theme="@style/ActivityTransitionTheme"/> \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/IndexActivity.kt b/app/src/main/java/com/leeeyou/IndexActivity.kt index e7b954b..70d6e9f 100644 --- a/app/src/main/java/com/leeeyou/IndexActivity.kt +++ b/app/src/main/java/com/leeeyou/IndexActivity.kt @@ -1,10 +1,11 @@ package com.leeeyou +import android.graphics.Color import android.os.Bundle import android.support.v7.app.AppCompatActivity import android.view.LayoutInflater -import android.view.Window import android.widget.ImageView +import com.jaeger.library.StatusBarUtil import com.leeeyou.movie.MovieFragment import com.leeeyou.wanandroid.WanAndroidFragment import com.leeeyou.zhihudaily.view.ZhiHuDailyFragment @@ -13,7 +14,7 @@ import com.ogaclejapan.smarttablayout.utils.v4.FragmentPagerItemAdapter import com.ogaclejapan.smarttablayout.utils.v4.FragmentPagerItems import kotlinx.android.synthetic.main.activity_index.* -private const val INDEX_VIEWPAGER_MOVIE_STR = "天气" +private const val INDEX_VIEWPAGER_MOVIE_STR = "电影" private const val INDEX_VIEWPAGER_ANDROID_STR = "安卓" private const val INDEX_VIEWPAGER_ZHIHU_STR = "知乎" @@ -27,9 +28,11 @@ class IndexActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - requestWindowFeature(Window.FEATURE_NO_TITLE) + setSupportActionBar(toolbar) + supportActionBar?.setDisplayShowTitleEnabled(false) setContentView(R.layout.activity_index) initViewPager() + StatusBarUtil.setColor(this@IndexActivity, Color.WHITE) } private fun initViewPager() { diff --git a/app/src/main/java/com/leeeyou/manager/sonic/BrowserActivity.java b/app/src/main/java/com/leeeyou/manager/sonic/BrowserActivity.java index ed1436b..684f70b 100644 --- a/app/src/main/java/com/leeeyou/manager/sonic/BrowserActivity.java +++ b/app/src/main/java/com/leeeyou/manager/sonic/BrowserActivity.java @@ -27,6 +27,7 @@ import android.webkit.WebViewClient; import android.widget.Toast; +import com.jaeger.library.StatusBarUtil; import com.leeeyou.R; import com.leeeyou.manager.BaseActivity; import com.tencent.sonic.sdk.SonicCacheInterceptor; @@ -70,6 +71,7 @@ public class BrowserActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + StatusBarUtil.setColor(BrowserActivity.this, getResources().getColor(R.color.default_gray)); Intent intent = getIntent(); String url = intent.getStringExtra(PARAM_URL); int mode = intent.getIntExtra(PARAM_MODE, -1); @@ -78,7 +80,6 @@ protected void onCreate(Bundle savedInstanceState) { return; } - getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); // init sonic engine if necessary, or maybe u can do this when application created diff --git a/app/src/main/res/layout/activity_index.xml b/app/src/main/res/layout/activity_index.xml index 03c514f..3c40b56 100644 --- a/app/src/main/res/layout/activity_index.xml +++ b/app/src/main/res/layout/activity_index.xml @@ -1,29 +1,44 @@ - + - + + + + + + + + - - + android:layout_height="match_parent" + app:layout_behavior="@string/appbar_scrolling_view_behavior"/> + diff --git a/app/src/main/res/values-v19/dimens.xml b/app/src/main/res/values-v19/dimens.xml deleted file mode 100644 index 8684353..0000000 --- a/app/src/main/res/values-v19/dimens.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - 25dp - - diff --git a/app/src/main/res/values-v19/styles.xml b/app/src/main/res/values-v19/styles.xml deleted file mode 100644 index e670fb0..0000000 --- a/app/src/main/res/values-v19/styles.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - diff --git a/app/src/main/res/values-v21/dimens.xml b/app/src/main/res/values-v21/dimens.xml deleted file mode 100644 index 8684353..0000000 --- a/app/src/main/res/values-v21/dimens.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - 25dp - - diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml deleted file mode 100644 index 20dd961..0000000 --- a/app/src/main/res/values-v21/styles.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index f024ce6..94acf9d 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,11 +1,22 @@ - + + From 8b38adbf1ba4cd1c0f13c4dfee4e8c294117979c Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Fri, 11 Jan 2019 21:17:22 +0800 Subject: [PATCH 081/150] Import DrawLayout --- app/src/main/AndroidManifest.xml | 6 +- .../main/java/com/leeeyou/IndexActivity.kt | 13 ++- .../manager/sonic/BrowserActivity.java | 3 +- .../java/com/leeeyou/util/ToolbarHelper.java | 5 +- app/src/main/res/anim/slide_in_left.xml | 7 ++ app/src/main/res/anim/slide_in_right.xml | 8 ++ app/src/main/res/anim/slide_out_left.xml | 8 ++ app/src/main/res/anim/slide_out_right.xml | 7 ++ app/src/main/res/drawable/ic_avatar.png | Bin 0 -> 35413 bytes app/src/main/res/drawable/ic_favorite.png | Bin 0 -> 981 bytes app/src/main/res/drawable/ic_gavel.png | Bin 0 -> 372 bytes app/src/main/res/drawable/ic_grade.png | Bin 0 -> 676 bytes app/src/main/res/drawable/ic_group_work.png | Bin 0 -> 778 bytes app/src/main/res/drawable/ic_menu_camera.xml | 12 +++ app/src/main/res/drawable/ic_menu_gallery.xml | 9 ++ app/src/main/res/drawable/ic_menu_manage.xml | 9 ++ app/src/main/res/drawable/ic_menu_send.xml | 9 ++ app/src/main/res/drawable/ic_menu_share.xml | 9 ++ .../main/res/drawable/ic_menu_slideshow.xml | 9 ++ app/src/main/res/drawable/nav_header_bg.jpg | Bin 0 -> 43689 bytes app/src/main/res/layout/activity_index.xml | 88 +++++++++++------- app/src/main/res/layout/nav_header.xml | 38 ++++++++ .../main/res/menu/activity_main_drawer.xml | 36 +++++++ app/src/main/res/menu/bottom_bar_items.xml | 21 +++++ app/src/main/res/values/colors.xml | 6 +- app/src/main/res/values/strings.xml | 3 + app/src/main/res/values/styles.xml | 34 ++++--- 27 files changed, 275 insertions(+), 65 deletions(-) create mode 100644 app/src/main/res/anim/slide_in_left.xml create mode 100644 app/src/main/res/anim/slide_in_right.xml create mode 100644 app/src/main/res/anim/slide_out_left.xml create mode 100644 app/src/main/res/anim/slide_out_right.xml create mode 100644 app/src/main/res/drawable/ic_avatar.png create mode 100644 app/src/main/res/drawable/ic_favorite.png create mode 100644 app/src/main/res/drawable/ic_gavel.png create mode 100644 app/src/main/res/drawable/ic_grade.png create mode 100644 app/src/main/res/drawable/ic_group_work.png create mode 100644 app/src/main/res/drawable/ic_menu_camera.xml create mode 100644 app/src/main/res/drawable/ic_menu_gallery.xml create mode 100644 app/src/main/res/drawable/ic_menu_manage.xml create mode 100644 app/src/main/res/drawable/ic_menu_send.xml create mode 100644 app/src/main/res/drawable/ic_menu_share.xml create mode 100644 app/src/main/res/drawable/ic_menu_slideshow.xml create mode 100644 app/src/main/res/drawable/nav_header_bg.jpg create mode 100644 app/src/main/res/layout/nav_header.xml create mode 100644 app/src/main/res/menu/activity_main_drawer.xml create mode 100644 app/src/main/res/menu/bottom_bar_items.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3abcf03..1e33ffc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -19,8 +19,7 @@ android:supportsRtl="true" android:theme="@style/AppTheme"> + android:name=".IndexActivity"> @@ -46,8 +45,7 @@ + android:screenOrientation="portrait"/> \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/IndexActivity.kt b/app/src/main/java/com/leeeyou/IndexActivity.kt index 70d6e9f..9b17ee5 100644 --- a/app/src/main/java/com/leeeyou/IndexActivity.kt +++ b/app/src/main/java/com/leeeyou/IndexActivity.kt @@ -1,11 +1,10 @@ package com.leeeyou -import android.graphics.Color import android.os.Bundle +import android.support.v7.app.ActionBarDrawerToggle import android.support.v7.app.AppCompatActivity import android.view.LayoutInflater import android.widget.ImageView -import com.jaeger.library.StatusBarUtil import com.leeeyou.movie.MovieFragment import com.leeeyou.wanandroid.WanAndroidFragment import com.leeeyou.zhihudaily.view.ZhiHuDailyFragment @@ -25,14 +24,18 @@ private const val INDEX_VIEWPAGER_ZHIHU_STR = "知乎" * Date: 2018/12/21 18:02 */ class IndexActivity : AppCompatActivity() { - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + + setContentView(R.layout.activity_index) + setSupportActionBar(toolbar) supportActionBar?.setDisplayShowTitleEnabled(false) - setContentView(R.layout.activity_index) + val toggle = ActionBarDrawerToggle(this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) + drawer_layout.setDrawerListener(toggle) + toggle.syncState() + initViewPager() - StatusBarUtil.setColor(this@IndexActivity, Color.WHITE) } private fun initViewPager() { diff --git a/app/src/main/java/com/leeeyou/manager/sonic/BrowserActivity.java b/app/src/main/java/com/leeeyou/manager/sonic/BrowserActivity.java index 684f70b..527df09 100644 --- a/app/src/main/java/com/leeeyou/manager/sonic/BrowserActivity.java +++ b/app/src/main/java/com/leeeyou/manager/sonic/BrowserActivity.java @@ -71,7 +71,7 @@ public class BrowserActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - StatusBarUtil.setColor(BrowserActivity.this, getResources().getColor(R.color.default_gray)); + StatusBarUtil.setTranslucent(BrowserActivity.this, getResources().getColor(R.color.colorPrimaryDark)); Intent intent = getIntent(); String url = intent.getStringExtra(PARAM_URL); int mode = intent.getIntExtra(PARAM_MODE, -1); @@ -80,6 +80,7 @@ protected void onCreate(Bundle savedInstanceState) { return; } + getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); // init sonic engine if necessary, or maybe u can do this when application created diff --git a/app/src/main/java/com/leeeyou/util/ToolbarHelper.java b/app/src/main/java/com/leeeyou/util/ToolbarHelper.java index 68a10f1..07cff22 100644 --- a/app/src/main/java/com/leeeyou/util/ToolbarHelper.java +++ b/app/src/main/java/com/leeeyou/util/ToolbarHelper.java @@ -15,7 +15,7 @@ /** * ClassName: ToolbarHelper * Description: Toolbar helper class to extract public methods from Original and Center - * + *

* Author: leeeyou * Date: 2016/5/10 15:18 */ @@ -40,11 +40,8 @@ public static void setContentView(AppCompatActivity activity, int layoutResID) { public static void setContentView(AppCompatActivity activity, View view) { LinearLayout rootLayout = activity.findViewById(R.id.rootLayout); - if (rootLayout == null) return; - rootLayout.addView(view, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); - initToolbar(activity); } diff --git a/app/src/main/res/anim/slide_in_left.xml b/app/src/main/res/anim/slide_in_left.xml new file mode 100644 index 0000000..06938c3 --- /dev/null +++ b/app/src/main/res/anim/slide_in_left.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_in_right.xml b/app/src/main/res/anim/slide_in_right.xml new file mode 100644 index 0000000..98f2313 --- /dev/null +++ b/app/src/main/res/anim/slide_in_right.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_out_left.xml b/app/src/main/res/anim/slide_out_left.xml new file mode 100644 index 0000000..eb5eda8 --- /dev/null +++ b/app/src/main/res/anim/slide_out_left.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_out_right.xml b/app/src/main/res/anim/slide_out_right.xml new file mode 100644 index 0000000..b9c942b --- /dev/null +++ b/app/src/main/res/anim/slide_out_right.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_avatar.png b/app/src/main/res/drawable/ic_avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..d6fe418f3b9eeefb8c9b5918138cdc46293bd09c GIT binary patch literal 35413 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\Hr|Knej)w;TUJ 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 SPb@Y70000LTbNM2H{@gF-3{^57w~4t7fl zN(f8BB*PBfBrHmVEG1B)%ycS#Lrk2y&F$I$*|T7uj}#Xd_g^5Ne8mzT(5BeIR=iA; zp;*Bc7St&=kjz&W43n%_z)6;rDi-jXC9mW>a`ClKPNNlHcjYX$@CRR$Y?hO_z-qN} z4v7r0+Gi5w6prCfk(@#o{&dP2?7_czcFGAf6G)Sy4>uD8@{=@08|Mk8TG2%U9|`8Y zq6rsetmg!&GL2+1@lZeoH8jx5Q{FPj1fiN>kUpN!LIX8aP=JR_k`yWmsiK}{+Ua3{ zaptkZJYx*dLp#mXQ$?WyA&(KFZG=1p#t!<4rhc|7INWp*EiZ6ueWY-oXlNl>q2e<3 zn&*Lg%top@Kna6%cvEm!KvIo6b(JgzhfoZImBt>@MAXeqe4qU{lTG@dP zta>c-NMIbRzRNsvh(xwbqmoFRlWDXOiF-1QL4uiLieNs-EVdC$2U%p%K``kui82Bi zqFDb>%n*Sbmq|3?&otL?$pLgo!kj-<}>XSL7F~>?@C{YlUGR#U| zTr!0Me9dr!jamn3++qe_M`Q|DS@x3M3K2PUv#d_0(8Z!}lq*bBFv_B5GJ_;0fLU&{ zNfzMd4s*Z{5@iAhfFAZL0(j^JJTie(oKeI`;4CGIi;Ihk3)f#EI?}L6ho$}i0000< KMNUMnLSTYk8z!;< literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/ic_group_work.png b/app/src/main/res/drawable/ic_group_work.png new file mode 100644 index 0000000000000000000000000000000000000000..dae7f56083ee948a330ef64d4f1ab60c019debe9 GIT binary patch literal 778 zcmV+l1NHogP)6B9tfo4d#*h9bRifCcqfiG&5ph(|Mez?%rxt3Vo&2B`Qe6}s3JOt!L5g&! zbPbN`HApve6`yXUL(a|n-g7Q#Aj!vkL6T*^kv>U z53kHZP5AmUug}ZtM;*u7GH;#F1~uPgW}V_u4XVmG^0_v<=$TmU*lEcIACp zT3hC=@-HM?>6~Smm*=yxy?u{WnV07u>5?ADY*>_ed45fPKGepow#=*ZMUt8$y%KZT96PgHy*7Utl*nKPo`8;S5&3uh7NwAx(0G;`p1uoAY{Q*oAY#T#O7 zF7SrA#g-yNF0VLKd?q}PtdVqo37qDLFl6bD?wY)t9qy6hvrSj@eY1u{ccYVzyJUM07*qo IM6N<$g0I48rT_o{ literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/ic_menu_camera.xml b/app/src/main/res/drawable/ic_menu_camera.xml new file mode 100644 index 0000000..7d1c583 --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_camera.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_menu_gallery.xml b/app/src/main/res/drawable/ic_menu_gallery.xml new file mode 100644 index 0000000..2f2ca2a --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_gallery.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_menu_manage.xml b/app/src/main/res/drawable/ic_menu_manage.xml new file mode 100644 index 0000000..065d9fa --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_manage.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_menu_send.xml b/app/src/main/res/drawable/ic_menu_send.xml new file mode 100644 index 0000000..a554657 --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_send.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_menu_share.xml b/app/src/main/res/drawable/ic_menu_share.xml new file mode 100644 index 0000000..8151b38 --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_share.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_menu_slideshow.xml b/app/src/main/res/drawable/ic_menu_slideshow.xml new file mode 100644 index 0000000..e750991 --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_slideshow.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/nav_header_bg.jpg b/app/src/main/res/drawable/nav_header_bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4d736f893ba0ce7ee8ae18f5b834f501706d02c8 GIT binary patch literal 43689 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%0A4mCCTgiU_0d;VIX~l0rtCP1 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 - + android:layout_height="match_parent" + android:background="@color/white" + android:fitsSystemWindows="true"> - + android:layout_height="match_parent"> - - - - - - - - + + + + + + + + + + + + + + android:layout_gravity="start" + android:background="@color/white" + app:headerLayout="@layout/nav_header" + app:menu="@menu/activity_main_drawer"/> - + diff --git a/app/src/main/res/layout/nav_header.xml b/app/src/main/res/layout/nav_header.xml new file mode 100644 index 0000000..bfd251c --- /dev/null +++ b/app/src/main/res/layout/nav_header.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + diff --git a/app/src/main/res/menu/activity_main_drawer.xml b/app/src/main/res/menu/activity_main_drawer.xml new file mode 100644 index 0000000..ecb6c21 --- /dev/null +++ b/app/src/main/res/menu/activity_main_drawer.xml @@ -0,0 +1,36 @@ + +

+ + + + + + + + + + + + + + + + diff --git a/app/src/main/res/menu/bottom_bar_items.xml b/app/src/main/res/menu/bottom_bar_items.xml new file mode 100644 index 0000000..86ca9be --- /dev/null +++ b/app/src/main/res/menu/bottom_bar_items.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index ce03ce4..e9a3a8d 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -1,8 +1,8 @@ - #34495E - #000000 - #EEEEEE + #146e6e + #083939 + #FF4081 #5DA0A2 #142E3C diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0fcce56..4ec61c5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,6 @@ 阅读精选 + navigation_drawer_open + navigation_drawer_close + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 94acf9d..4e27b36 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,22 +1,28 @@ - - + + - From 10162b5d751bd0f64f68905ae4a596c091b961fa Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Fri, 11 Jan 2019 21:41:23 +0800 Subject: [PATCH 082/150] Import DrawLayout , Update StatusBar Color --- .../com/leeeyou/manager/sonic/BrowserActivity.java | 2 +- app/src/main/res/layout/activity_index.xml | 2 +- .../main/res/layout/fragment_wan_android_project.xml | 1 + .../main/res/layout/fragment_wan_android_system.xml | 1 + app/src/main/res/values/colors.xml | 10 ++++++++-- app/src/main/res/values/styles.xml | 4 ++++ 6 files changed, 16 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/leeeyou/manager/sonic/BrowserActivity.java b/app/src/main/java/com/leeeyou/manager/sonic/BrowserActivity.java index 527df09..679351e 100644 --- a/app/src/main/java/com/leeeyou/manager/sonic/BrowserActivity.java +++ b/app/src/main/java/com/leeeyou/manager/sonic/BrowserActivity.java @@ -71,7 +71,7 @@ public class BrowserActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - StatusBarUtil.setTranslucent(BrowserActivity.this, getResources().getColor(R.color.colorPrimaryDark)); + StatusBarUtil.setColor(BrowserActivity.this, getResources().getColor(R.color.colorPrimaryDark)); Intent intent = getIntent(); String url = intent.getStringExtra(PARAM_URL); int mode = intent.getIntExtra(PARAM_MODE, -1); diff --git a/app/src/main/res/layout/activity_index.xml b/app/src/main/res/layout/activity_index.xml index caca0f2..8e073b6 100644 --- a/app/src/main/res/layout/activity_index.xml +++ b/app/src/main/res/layout/activity_index.xml @@ -26,7 +26,7 @@ android:layout_height="?attr/actionBarSize" app:layout_scrollFlags="scroll|enterAlways|snap" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" - app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> + app:theme="@style/ToolbarColoredBackArrow"> diff --git a/app/src/main/res/layout/fragment_wan_android_system.xml b/app/src/main/res/layout/fragment_wan_android_system.xml index 5e9c9ef..03c30d5 100644 --- a/app/src/main/res/layout/fragment_wan_android_system.xml +++ b/app/src/main/res/layout/fragment_wan_android_system.xml @@ -23,6 +23,7 @@ android:paddingLeft="10dp" android:text="开发环境 / gradle" android:textSize="14sp" + android:textColor="@color/default_white" android:textStyle="bold" tools:text="开发环境 / gradle" /> diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index e9a3a8d..a3c7bfe 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -1,9 +1,14 @@ - #146e6e - #083939 + + + + + @color/default_white + @color/default_gray #FF4081 + #5DA0A2 #142E3C #F4F7F7 @@ -44,6 +49,7 @@ #DC4037 #FF63727B #ffffff + #7fffffff #f9f900 #c5c5c5 diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 4e27b36..1a88609 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -25,4 +25,8 @@ @anim/slide_out_right + + From 3c2d6d54ec7a2eeacd2fc3e2ba874150cae2b241 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Fri, 11 Jan 2019 21:43:06 +0800 Subject: [PATCH 083/150] Import DrawLayout , Update StatusBar Color --- app/src/main/res/layout/activity_base_original.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/layout/activity_base_original.xml b/app/src/main/res/layout/activity_base_original.xml index 14b3598..f22b9ff 100644 --- a/app/src/main/res/layout/activity_base_original.xml +++ b/app/src/main/res/layout/activity_base_original.xml @@ -12,6 +12,6 @@ android:minHeight="?attr/actionBarSize" android:paddingTop="@dimen/toolbar_padding_top" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" - app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" /> + app:theme="@style/ToolbarColoredBackArrow" /> From 8deeddc7aed254ef3a515894545fc8cfd488f240 Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Fri, 11 Jan 2019 23:07:31 +0800 Subject: [PATCH 084/150] Organize code --- .../com/leeeyou/manager/MyLoadMoreView.kt | 4 +- .../subscriber/HttpResultSubscriber.kt | 2 +- .../wanandroid/WanAndroidProjectFragment.kt | 194 +++++++++--------- .../wanandroid/WanAndroidRecommendFragment.kt | 4 +- .../wanandroid/WanAndroidSystemFragment.kt | 11 +- 5 files changed, 108 insertions(+), 107 deletions(-) diff --git a/app/src/main/java/com/leeeyou/manager/MyLoadMoreView.kt b/app/src/main/java/com/leeeyou/manager/MyLoadMoreView.kt index 83a42b0..7cf6c4e 100644 --- a/app/src/main/java/com/leeeyou/manager/MyLoadMoreView.kt +++ b/app/src/main/java/com/leeeyou/manager/MyLoadMoreView.kt @@ -13,11 +13,11 @@ class MyLoadMoreView : LoadMoreView() { } override fun getLoadEndViewId(): Int { - return R.id.load_more_load_fail_view + return R.id.load_more_load_end_view } override fun getLoadFailViewId(): Int { - return R.id.load_more_load_end_view + return R.id.load_more_load_fail_view } } \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/service/subscriber/HttpResultSubscriber.kt b/app/src/main/java/com/leeeyou/service/subscriber/HttpResultSubscriber.kt index d8ca712..8093f1e 100644 --- a/app/src/main/java/com/leeeyou/service/subscriber/HttpResultSubscriber.kt +++ b/app/src/main/java/com/leeeyou/service/subscriber/HttpResultSubscriber.kt @@ -37,7 +37,7 @@ abstract class HttpResultSubscriber : Subscriber>() { } ?: _onError(httpResult.errorCode, "") } - abstract fun onSuccess(t: T?) + abstract fun onSuccess(data: T?) abstract fun _onError(status: Int, msg: String?) } diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt index fafdc60..4c043b3 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt @@ -60,6 +60,13 @@ class WanAndroidProjectFragment : BaseFragment() { return container?.inflate(R.layout.fragment_wan_android_project) } + override fun setUserVisibleHint(isVisibleToUser: Boolean) { + super.setUserVisibleHint(isVisibleToUser) + if (!isVisibleToUser) { // onPause + hiddenDetailTagAnimation() + } + } + override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) initRecyclerView() @@ -68,11 +75,71 @@ class WanAndroidProjectFragment : BaseFragment() { fetchProjectCategoryListFromServer() } - override fun setUserVisibleHint(isVisibleToUser: Boolean) { - super.setUserVisibleHint(isVisibleToUser) - // onPause - if (!isVisibleToUser) { - hiddenDetailTagAnimation() + private fun initRecyclerView() { + mLinearLayoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) + mProjectAdapter = object : BaseQuickAdapter(R.layout.item_project, null) { + override fun convert(helper: BaseViewHolder?, item: RecommendItem?) { + if (item == null || helper == null) return + + helper.setText(R.id.tv_title, HtmlUtils.translation(item.title)) + .setText(R.id.tv_author, item.author) + .setText(R.id.tv_niceDate, item.niceDate) + + Glide.with(mContext).load(item.envelopePic).into(helper.getView(R.id.iv_project) as ImageView) + + helper.setOnClickListener(R.id.tv_view_similar_projects) { + T.showShort(mContext, "显示同类项目") + TODO("显示同类项目") + } + } + } + mProjectAdapter.setOnLoadMoreListener({ + if (mPageIndex + 1 == mPageCount) { + mProjectAdapter.loadMoreEnd() + } else { + mPageIndex++ + fetchProjectListFromServer() + } + }, recyclerViewProject) + mProjectAdapter.disableLoadMoreIfNotFullPage() + mProjectAdapter.setOnItemClickListener { adapter, _, position -> + (adapter.getItem(position) as RecommendItem) + .also { startBrowserActivity(context!!, it.link, it.title) } + } + mProjectAdapter.openLoadAnimation(BaseQuickAdapter.SCALEIN) + mProjectAdapter.setLoadMoreView(MyLoadMoreView()) + + recyclerViewProject.layoutManager = mLinearLayoutManager + recyclerViewProject.adapter = mProjectAdapter + } + + private fun initPtrFrame() { + initHeadView() + ptrFrameProject.disableWhenHorizontalMove(true) + ptrFrameProject.setPtrHandler(object : PtrHandler { + override fun onRefreshBegin(frame: PtrFrameLayout?) { + mPageIndex = 0 + fetchProjectListFromServer() + } + + override fun checkCanDoRefresh(frame: PtrFrameLayout?, content: View?, header: View?): Boolean { + return recyclerViewFirstItemCanVisible() + } + }) + } + + private fun initHeadView() { + val header = StoreHouseHeader(context) + header.setTextColor(resources.getColor(R.color.default_red)) + header.setPadding(0, dp2px(15f), 0, 0) + header.initWithString("Play Android", 15) + ptrFrameProject.headerView = header + ptrFrameProject.addPtrUIHandler(header) + } + + private fun initProjectCategoryUI() { + rl_project_category.setOnClickListener { + if (sv_project_category.visibility == View.VISIBLE) hiddenDetailTagAnimation() else showDetailTagAnimation() } } @@ -85,12 +152,14 @@ class WanAndroidProjectFragment : BaseFragment() { } private fun fetchProjectListByRecommendFromServer(pageIndex: Int) { - fetchProjectListByRecommend(pageIndex).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) + fetchProjectListByRecommend(pageIndex) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) .subscribe(object : DefaultHttpResultSubscriber() { - override fun onSuccess(t: RecommendList?) { - t?.let { - renderProjectList(pageIndex, t) - if (mPageIndex == 0 && t.datas.size < t.size) { + override fun onSuccess(data: RecommendList?) { + data?.let { + renderProjectList(pageIndex, data) + if (mPageIndex == 0 && data.datas.size < data.size) { mProjectAdapter.loadMoreEnd() } else if (mPageIndex > 0) { mProjectAdapter.loadMoreComplete() @@ -107,17 +176,14 @@ class WanAndroidProjectFragment : BaseFragment() { }) } - private fun initProjectCategoryUI() { - rl_project_category.setOnClickListener { - if (sv_project_category.visibility == View.VISIBLE) hiddenDetailTagAnimation() else showDetailTagAnimation() - } - } private fun fetchProjectCategoryListFromServer() { - fetchProjectCategory().subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) + fetchProjectCategory() + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) .subscribe(object : DefaultHttpResultSubscriber>() { - override fun onSuccess(t: List?) { - t?.let { + override fun onSuccess(data: List?) { + data?.also { renderProjectCategory(it) } } @@ -158,10 +224,8 @@ class WanAndroidProjectFragment : BaseFragment() { flowLayout_project_category.adapter = object : TagAdapter(categoryList) { override fun getView(parent: FlowLayout?, position: Int, systemTag: SystemTag?): View { val parentTag = layoutInflater.inflate(R.layout.item_system_tag, null) as TextView - systemTag?.let { - parentTag.text = HtmlUtils.translation(it.name) - return parentTag - } + if (systemTag == null) return parentTag + parentTag.text = HtmlUtils.translation(systemTag.name) return parentTag } } @@ -183,86 +247,24 @@ class WanAndroidProjectFragment : BaseFragment() { } } - private fun initRecyclerView() { - mLinearLayoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) - mProjectAdapter = object : BaseQuickAdapter(R.layout.item_project, null) { - override fun convert(helper: BaseViewHolder?, item: RecommendItem?) { - item?.also { - helper?.also { helper -> - helper.setText(R.id.tv_title, HtmlUtils.translation(it.title)) - .setText(R.id.tv_author, it.author) - .setText(R.id.tv_niceDate, it.niceDate) - - val imageView = helper.getView(R.id.iv_project) as ImageView - Glide.with(mContext).load(item.envelopePic).into(imageView) - - helper.setOnClickListener(R.id.tv_view_similar_projects) { - T.showShort(mContext, "显示同类项目") - } - } - } - } - } - mProjectAdapter.setOnLoadMoreListener({ - if (mPageIndex + 1 == mPageCount) { - mProjectAdapter.loadMoreEnd() - } else { - mPageIndex++ - fetchProjectListFromServer() - } - }, recyclerViewProject) - mProjectAdapter.disableLoadMoreIfNotFullPage() - mProjectAdapter.setOnItemClickListener { adapter, _, position -> - val item: RecommendItem = adapter.getItem(position) as RecommendItem - startBrowserActivity(context!!, item.link, item.title) - } - mProjectAdapter.openLoadAnimation(BaseQuickAdapter.SCALEIN) - mProjectAdapter.setLoadMoreView(MyLoadMoreView()) - - recyclerViewProject.layoutManager = mLinearLayoutManager - recyclerViewProject.adapter = mProjectAdapter - } - - private fun initPtrFrame() { - initHeadView() - ptrFrameProject.disableWhenHorizontalMove(true) - ptrFrameProject.setPtrHandler(object : PtrHandler { - override fun onRefreshBegin(frame: PtrFrameLayout?) { - mPageIndex = 0 - fetchProjectListFromServer() - } - - override fun checkCanDoRefresh(frame: PtrFrameLayout?, content: View?, header: View?): Boolean = - recyclerViewFirstItemCanVisible() - }) - } - - private fun initHeadView() { - val header = StoreHouseHeader(context) - header.setTextColor(resources.getColor(R.color.default_red)) - header.setPadding(0, dp2px(15f), 0, 0) - header.initWithString("Play Android", 15) - ptrFrameProject.headerView = header - ptrFrameProject.addPtrUIHandler(header) - } - private fun recyclerViewFirstItemCanVisible() = mLinearLayoutManager.findFirstCompletelyVisibleItemPosition() <= 0 private fun fetchProjectListByCategoryFromServer(pageIndex: Int) { - fetchProjectListByCategory(pageIndex, mSelectedCategoryId).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) + fetchProjectListByCategory(pageIndex, mSelectedCategoryId) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) .subscribe(object : DefaultHttpResultSubscriber() { - override fun onSuccess(t: RecommendList?) { - t?.let { - renderProjectList(pageIndex, t) - if (pageIndex == 0) { - recyclerViewProject.smoothScrollToPosition(0) - if (t.datas.size < t.size) { - mProjectAdapter.loadMoreEnd() - } - } else if (pageIndex > 0) { - mProjectAdapter.loadMoreComplete() + override fun onSuccess(data: RecommendList?) { + if (data == null) return + renderProjectList(pageIndex, data) + if (pageIndex == 0) { + recyclerViewProject.smoothScrollToPosition(0) + if (data.datas.size < data.size) { + mProjectAdapter.loadMoreEnd() } + } else if (pageIndex > 0) { + mProjectAdapter.loadMoreComplete() } } diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt index 62b5635..49d3d24 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt @@ -145,8 +145,8 @@ class WanAndroidRecommendFragment : BaseFragment() { private fun fetchRecommendListFromServer(pageIndex: Int) { fetchRecommendList(pageIndex).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) .subscribe(object : DefaultHttpResultSubscriber() { - override fun onSuccess(t: RecommendList?) { - t?.let { + override fun onSuccess(data: RecommendList?) { + data?.let { renderRecommendList(pageIndex, it) if (mPageIndex == 0 && it.datas.size < it.size) { mRecommendAdapter.loadMoreEnd() diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt index 28419ca..9256d6e 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt @@ -69,8 +69,7 @@ class WanAndroidSystemFragment : BaseFragment() { override fun setUserVisibleHint(isVisibleToUser: Boolean) { super.setUserVisibleHint(isVisibleToUser) - // onPause - if (!isVisibleToUser) { + if (!isVisibleToUser) { // onPause hiddenDetailTagAnimation() } } @@ -231,10 +230,10 @@ class WanAndroidSystemFragment : BaseFragment() { Timber.d("fetchSystemTagArticleList , parent id is %s , child id is %s", mSelectedParentTagId, mSelectedChildTagId) fetchSystemTagArticleList(pageIndex, mSelectedChildTagId).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()) .subscribe(object : DefaultHttpResultSubscriber() { - override fun onSuccess(t: SystemTagArticleList?) { - t?.let { - renderSystemTagArticleList(pageIndex, t) - if (mPageIndex == 0 && t.datas.size < t.size) { + override fun onSuccess(data: SystemTagArticleList?) { + data?.let { + renderSystemTagArticleList(pageIndex, data) + if (mPageIndex == 0 && data.datas.size < data.size) { mSystemTagArticleAdapter.loadMoreEnd() } else if (mPageIndex > 0) { mSystemTagArticleAdapter.loadMoreComplete() From 65ecf6ddd49230254c4a924e0234c84c8c7d7a86 Mon Sep 17 00:00:00 2001 From: leeeyou Date: Sat, 12 Jan 2019 11:12:45 +0800 Subject: [PATCH 085/150] Optimize the nested scrolling problem of the toolbar when the pulldown is refreshed --- app/src/main/java/com/leeeyou/IndexActivity.kt | 10 ++++++++++ app/src/main/java/com/leeeyou/movie/MovieFragment.kt | 8 ++++++-- .../leeeyou/wanandroid/WanAndroidProjectFragment.kt | 3 ++- .../leeeyou/wanandroid/WanAndroidRecommendFragment.kt | 5 ++++- .../com/leeeyou/wanandroid/WanAndroidSystemFragment.kt | 7 +++++-- .../com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt | 2 +- app/src/main/res/layout/activity_index.xml | 8 ++++---- 7 files changed, 32 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/leeeyou/IndexActivity.kt b/app/src/main/java/com/leeeyou/IndexActivity.kt index 9b17ee5..fc57e5a 100644 --- a/app/src/main/java/com/leeeyou/IndexActivity.kt +++ b/app/src/main/java/com/leeeyou/IndexActivity.kt @@ -12,6 +12,9 @@ import com.ogaclejapan.smarttablayout.utils.v4.FragmentPagerItem import com.ogaclejapan.smarttablayout.utils.v4.FragmentPagerItemAdapter import com.ogaclejapan.smarttablayout.utils.v4.FragmentPagerItems import kotlinx.android.synthetic.main.activity_index.* +import android.support.design.widget.AppBarLayout +import timber.log.Timber + private const val INDEX_VIEWPAGER_MOVIE_STR = "电影" private const val INDEX_VIEWPAGER_ANDROID_STR = "安卓" @@ -24,6 +27,9 @@ private const val INDEX_VIEWPAGER_ZHIHU_STR = "知乎" * Date: 2018/12/21 18:02 */ class IndexActivity : AppCompatActivity() { + + var appBarLayoutVerticalOffset: Int = 0 + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -35,6 +41,10 @@ class IndexActivity : AppCompatActivity() { drawer_layout.setDrawerListener(toggle) toggle.syncState() + + appBarLayout.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { appBarLayout, verticalOffset -> + appBarLayoutVerticalOffset = verticalOffset + }) initViewPager() } diff --git a/app/src/main/java/com/leeeyou/movie/MovieFragment.kt b/app/src/main/java/com/leeeyou/movie/MovieFragment.kt index b01f2b1..9d71c08 100644 --- a/app/src/main/java/com/leeeyou/movie/MovieFragment.kt +++ b/app/src/main/java/com/leeeyou/movie/MovieFragment.kt @@ -14,15 +14,18 @@ import android.widget.ImageView import com.bumptech.glide.Glide import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.BaseViewHolder +import com.leeeyou.IndexActivity import com.leeeyou.R import com.leeeyou.manager.BaseFragment import com.leeeyou.movie.model.bean.ResponseHotMovie import com.leeeyou.movie.model.fetchHotMovieList import com.leeeyou.util.HtmlUtils import com.leeeyou.util.inflate +import kotlinx.android.synthetic.main.activity_index.* import kotlinx.android.synthetic.main.fragment_movie.* import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers +import timber.log.Timber /** * ClassName: MovieFragment @@ -66,8 +69,9 @@ class MovieFragment : BaseFragment() { fetchHotMovieListFromServer() } - override fun checkCanDoRefresh(frame: PtrFrameLayout?, content: View?, header: View?): Boolean = - recyclerViewFirstItemCanVisible() + override fun checkCanDoRefresh(frame: PtrFrameLayout?, content: View?, header: View?): Boolean { + return recyclerViewFirstItemCanVisible() && (activity as IndexActivity).appBarLayoutVerticalOffset >= 0 + } }) } diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt index 4c043b3..ff3bc9f 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidProjectFragment.kt @@ -17,6 +17,7 @@ import android.widget.TextView import com.bumptech.glide.Glide import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.BaseViewHolder +import com.leeeyou.IndexActivity import com.leeeyou.R import com.leeeyou.manager.BaseFragment import com.leeeyou.manager.MyAnimationListener @@ -123,7 +124,7 @@ class WanAndroidProjectFragment : BaseFragment() { } override fun checkCanDoRefresh(frame: PtrFrameLayout?, content: View?, header: View?): Boolean { - return recyclerViewFirstItemCanVisible() + return recyclerViewFirstItemCanVisible() && (activity as IndexActivity).appBarLayoutVerticalOffset >= 0 } }) } diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt index 49d3d24..c235202 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidRecommendFragment.kt @@ -14,6 +14,7 @@ import android.widget.ImageView import com.bumptech.glide.Glide import com.chad.library.adapter.base.BaseQuickAdapter import com.chad.library.adapter.base.BaseViewHolder +import com.leeeyou.IndexActivity import com.leeeyou.R import com.leeeyou.manager.BaseFragment import com.leeeyou.manager.MyLoadMoreView @@ -116,7 +117,9 @@ class WanAndroidRecommendFragment : BaseFragment() { pullDownToRefresh() } - override fun checkCanDoRefresh(frame: PtrFrameLayout?, content: View?, header: View?): Boolean = recyclerViewFirstItemCanVisible() + override fun checkCanDoRefresh(frame: PtrFrameLayout?, content: View?, header: View?): Boolean { + return recyclerViewFirstItemCanVisible() && (activity as IndexActivity).appBarLayoutVerticalOffset >= 0 + } }) } diff --git a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt index 9256d6e..72b7668 100644 --- a/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt +++ b/app/src/main/java/com/leeeyou/wanandroid/WanAndroidSystemFragment.kt @@ -131,8 +131,11 @@ class WanAndroidSystemFragment : BaseFragment() { pullDownToRefresh() } - override fun checkCanDoRefresh(frame: PtrFrameLayout?, content: View?, header: View?): Boolean = - sv_system_tag_all.visibility != View.VISIBLE && recyclerViewFirstItemCanVisible() + override fun checkCanDoRefresh(frame: PtrFrameLayout?, content: View?, header: View?): Boolean { + return sv_system_tag_all.visibility != View.VISIBLE + && recyclerViewFirstItemCanVisible() + && (activity as com.leeeyou.IndexActivity).appBarLayoutVerticalOffset >= 0 + } }) } diff --git a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt index ba875a2..a05ca0a 100644 --- a/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt +++ b/app/src/main/java/com/leeeyou/zhihudaily/view/ZhiHuDailyFragment.kt @@ -67,7 +67,7 @@ class ZhiHuDailyFragment : BaseFragment() { } override fun checkCanDoRefresh(frame: PtrFrameLayout?, content: View?, header: View?): Boolean { - return !recyclerViewRiBao.canScrollVertically(-1) + return !recyclerViewRiBao.canScrollVertically(-1) && (activity as com.leeeyou.IndexActivity).appBarLayoutVerticalOffset >= 0 } }) } diff --git a/app/src/main/res/layout/activity_index.xml b/app/src/main/res/layout/activity_index.xml index 8e073b6..4ed4fc7 100644 --- a/app/src/main/res/layout/activity_index.xml +++ b/app/src/main/res/layout/activity_index.xml @@ -9,13 +9,13 @@ android:fitsSystemWindows="true"> - @@ -39,7 +39,7 @@ app:stl_indicatorColor="@color/transparent" app:stl_indicatorThickness="0dp" app:stl_underlineColor="@color/transparent" - app:stl_underlineThickness="0dp"/> + app:stl_underlineThickness="0dp" /> @@ -48,7 +48,7 @@ android:id="@+id/indexViewPager" android:layout_width="match_parent" android:layout_height="match_parent" - app:layout_behavior="@string/appbar_scrolling_view_behavior"/> + app:layout_behavior="@string/appbar_scrolling_view_behavior" /> From 0da9e8f7d9ebdb7d3c2aca63e6418ce1d2e3f42c Mon Sep 17 00:00:00 2001 From: LeeeYou Date: Mon, 14 Jan 2019 17:02:55 +0800 Subject: [PATCH 086/150] Add theme colors, organize color files --- app/build.gradle | 2 +- app/src/main/AndroidManifest.xml | 19 ++++- .../main/java/com/leeeyou/IndexActivity.kt | 52 +++++++++--- .../java/com/leeeyou/login/LoginActivity.java | 18 +++++ .../com/leeeyou/manager/BaseActivity.java | 4 +- .../leeeyou/movie/MovieDetailActivity.java | 16 ++++ .../java/com/leeeyou/movie/MovieFragment.kt | 9 ++- .../opensource/OpenSourceActivity.java | 16 ++++ .../com/leeeyou/setting/SettingActivity.java | 16 ++++ .../com/leeeyou/skin/ChangeSkinActivity.java | 17 ++++ .../leeeyou/wanandroid/WanAndroidFragment.kt | 2 +- .../wanandroid/WanAndroidProjectFragment.kt | 2 +- .../wanandroid/WanAndroidRecommendFragment.kt | 2 +- .../wanandroid/WanAndroidSystemFragment.kt | 2 +- .../zhihudaily/view/ZhiHuDailyFragment.kt | 2 +- .../index_custom_tab_icon_color_selector.xml | 4 +- .../color/system_tag_text_color_selector.xml | 4 +- app/src/main/res/drawable/list_selector.xml | 4 +- .../res/drawable/system_tag_selected_bg.xml | 2 +- .../main/res/layout/activity_change_skin.xml | 10 +++ app/src/main/res/layout/activity_index.xml | 21 +++-- app/src/main/res/layout/activity_login.xml | 10 +++ app/src/main/res/layout/activity_movie.xml | 10 +++ .../main/res/layout/activity_open_source.xml | 10 +++ app/src/main/res/layout/activity_setting.xml | 10 +++ app/src/main/res/layout/adapter_load_more.xml | 4 +- .../main/res/layout/fragment_wan_android.xml | 9 ++- .../layout/fragment_wan_android_project.xml | 8 +- .../layout/fragment_wan_android_system.xml | 34 ++++---- app/src/main/res/layout/item_hot_movie.xml | 4 +- app/src/main/res/layout/item_project.xml | 12 +-- app/src/main/res/layout/item_recommend.xml | 14 ++-- app/src/main/res/layout/item_zhihu_daily.xml | 4 +- app/src/main/res/layout/nav_header.xml | 80 +++++++++++++------ .../main/res/menu/activity_main_drawer.xml | 29 ++----- app/src/main/res/values/colors.xml | 65 ++++----------- app/src/main/res/values/dimens.xml | 1 + app/src/main/res/values/strings.xml | 1 + app/src/main/res/values/styles.xml | 7 +- 39 files changed, 353 insertions(+), 183 deletions(-) create mode 100644 app/src/main/java/com/leeeyou/login/LoginActivity.java create mode 100644 app/src/main/java/com/leeeyou/movie/MovieDetailActivity.java create mode 100644 app/src/main/java/com/leeeyou/opensource/OpenSourceActivity.java create mode 100644 app/src/main/java/com/leeeyou/setting/SettingActivity.java create mode 100644 app/src/main/java/com/leeeyou/skin/ChangeSkinActivity.java create mode 100644 app/src/main/res/layout/activity_change_skin.xml create mode 100644 app/src/main/res/layout/activity_login.xml create mode 100644 app/src/main/res/layout/activity_movie.xml create mode 100644 app/src/main/res/layout/activity_open_source.xml create mode 100644 app/src/main/res/layout/activity_setting.xml diff --git a/app/build.gradle b/app/build.gradle index 851b93f..412468e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -114,4 +114,4 @@ dependencies { //statusbar implementation 'com.jaeger.statusbarutil:library:1.5.1' -} \ No newline at end of file +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1e33ffc..ec6a98b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -18,15 +18,13 @@ android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> - + - + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/leeeyou/IndexActivity.kt b/app/src/main/java/com/leeeyou/IndexActivity.kt index fc57e5a..7c6f88d 100644 --- a/app/src/main/java/com/leeeyou/IndexActivity.kt +++ b/app/src/main/java/com/leeeyou/IndexActivity.kt @@ -1,19 +1,27 @@ package com.leeeyou +import android.content.Intent import android.os.Bundle +import android.support.design.widget.AppBarLayout +import android.support.design.widget.NavigationView +import android.support.v4.view.GravityCompat import android.support.v7.app.ActionBarDrawerToggle import android.support.v7.app.AppCompatActivity import android.view.LayoutInflater +import android.view.MenuItem +import android.widget.Button import android.widget.ImageView +import com.leeeyou.login.LoginActivity import com.leeeyou.movie.MovieFragment +import com.leeeyou.opensource.OpenSourceActivity +import com.leeeyou.setting.SettingActivity +import com.leeeyou.skin.ChangeSkinActivity import com.leeeyou.wanandroid.WanAndroidFragment import com.leeeyou.zhihudaily.view.ZhiHuDailyFragment import com.ogaclejapan.smarttablayout.utils.v4.FragmentPagerItem import com.ogaclejapan.smarttablayout.utils.v4.FragmentPagerItemAdapter import com.ogaclejapan.smarttablayout.utils.v4.FragmentPagerItems import kotlinx.android.synthetic.main.activity_index.* -import android.support.design.widget.AppBarLayout -import timber.log.Timber private const val INDEX_VIEWPAGER_MOVIE_STR = "电影" @@ -26,26 +34,34 @@ private const val INDEX_VIEWPAGER_ZHIHU_STR = "知乎" * Author: leeeyou * Date: 2018/12/21 18:02 */ -class IndexActivity : AppCompatActivity() { - +class IndexActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener { var appBarLayoutVerticalOffset: Int = 0 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_index) + initDrawLayout() + initViewPager() + } + private fun initDrawLayout() { setSupportActionBar(toolbar) supportActionBar?.setDisplayShowTitleEnabled(false) + val toggle = ActionBarDrawerToggle(this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) - drawer_layout.setDrawerListener(toggle) + drawer_layout.addDrawerListener(toggle) toggle.syncState() - - appBarLayout.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { appBarLayout, verticalOffset -> + appBarLayout.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { _, verticalOffset -> appBarLayoutVerticalOffset = verticalOffset }) - initViewPager() + + navigation.setNavigationItemSelectedListener(this) + + navigation.getHeaderView(0).findViewById