diff --git a/202014040130tangjiefeng_Reader/.idea/.gitignore b/202014040130tangjiefeng_Reader/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/202014040130tangjiefeng_Reader/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/202014040130tangjiefeng_Reader/.idea/compiler.xml b/202014040130tangjiefeng_Reader/.idea/compiler.xml new file mode 100644 index 0000000..fb7f4a8 --- /dev/null +++ b/202014040130tangjiefeng_Reader/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/202014040130tangjiefeng_Reader/.idea/dbnavigator.xml b/202014040130tangjiefeng_Reader/.idea/dbnavigator.xml new file mode 100644 index 0000000..70f212e --- /dev/null +++ b/202014040130tangjiefeng_Reader/.idea/dbnavigator.xml @@ -0,0 +1,414 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/202014040130tangjiefeng_Reader/.idea/gradle.xml b/202014040130tangjiefeng_Reader/.idea/gradle.xml new file mode 100644 index 0000000..a2d7c21 --- /dev/null +++ b/202014040130tangjiefeng_Reader/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/202014040130tangjiefeng_Reader/.idea/jarRepositories.xml b/202014040130tangjiefeng_Reader/.idea/jarRepositories.xml new file mode 100644 index 0000000..7d192c5 --- /dev/null +++ b/202014040130tangjiefeng_Reader/.idea/jarRepositories.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/202014040130tangjiefeng_Reader/.idea/misc.xml b/202014040130tangjiefeng_Reader/.idea/misc.xml new file mode 100644 index 0000000..bdd9278 --- /dev/null +++ b/202014040130tangjiefeng_Reader/.idea/misc.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/202014040130tangjiefeng_Reader/AAD b/202014040130tangjiefeng_Reader/AAD new file mode 160000 index 0000000..aec645b --- /dev/null +++ b/202014040130tangjiefeng_Reader/AAD @@ -0,0 +1 @@ +Subproject commit aec645b6d670e75be67c525ebe11c562f66ff1f7 diff --git a/202014040130tangjiefeng_Reader/NovelReader.plantuml b/202014040130tangjiefeng_Reader/NovelReader.plantuml new file mode 100644 index 0000000..87efd16 --- /dev/null +++ b/202014040130tangjiefeng_Reader/NovelReader.plantuml @@ -0,0 +1,29 @@ +@startuml + +title __NOVELREADER's Component Diagram__\n + + component "NovelReader.app.unitTest" { + [NovelReader.app.main] + component "NovelReader.app.main" { + [NovelReader.app.androidTest] + component "NovelReader.app.androidTest" { + [NovelReader.app] + } + + + } + + + } + + + + +right footer + + +PlantUML diagram generated by SketchIt! (https://bitbucket.org/pmesmeur/sketch.it) +For more information about this tool, please contact philippe.mesmeur@gmail.com +endfooter + +@enduml diff --git a/202014040130tangjiefeng_Reader/app/build.gradle b/202014040130tangjiefeng_Reader/app/build.gradle new file mode 100644 index 0000000..fe8d4b9 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/build.gradle @@ -0,0 +1,41 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 28 + defaultConfig { + applicationId "fte.finalproject" + minSdkVersion 22 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + implementation 'com.android.support:cardview-v7:28.0.0' + implementation 'com.android.support:recyclerview-v7:28.0.0' + implementation 'de.hdodenhof:circleimageview:2.2.0' + implementation 'com.android.support:cardview-v7:28.0.0' + implementation 'com.squareup.retrofit2:retrofit:2.0.2' + implementation 'com.squareup.retrofit2:converter-scalars:2.0.0' + implementation 'com.squareup.retrofit2:converter-gson:2.1.0' + implementation 'com.squareup.retrofit2:adapter-rxjava:2.1.0' + implementation 'io.reactivex:rxandroid:1.2.1' + implementation 'io.reactivex:rxjava:1.2.1' + implementation 'com.squareup.okhttp3:okhttp:3.2.0' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + implementation 'io.reactivex.rxjava2:rxandroid:2.1.0' + implementation 'io.reactivex.rxjava2:rxjava:2.1.0' +} diff --git a/202014040130tangjiefeng_Reader/app/proguard-rules.pro b/202014040130tangjiefeng_Reader/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/202014040130tangjiefeng_Reader/app/release/output.json b/202014040130tangjiefeng_Reader/app/release/output.json new file mode 100644 index 0000000..9f0c959 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/release/output.json @@ -0,0 +1 @@ +[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] \ No newline at end of file diff --git a/202014040130tangjiefeng_Reader/app/src/androidTest/java/com/example/ExampleInstrumentedTest.java b/202014040130tangjiefeng_Reader/app/src/androidTest/java/com/example/ExampleInstrumentedTest.java new file mode 100644 index 0000000..d6fcbc7 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/androidTest/java/com/example/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.example; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("fte.finalproject", appContext.getPackageName()); + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/AndroidManifest.xml b/202014040130tangjiefeng_Reader/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..351cb93 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/AndroidManifest.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/BookDetailActivity.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/BookDetailActivity.java new file mode 100644 index 0000000..174a7c8 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/BookDetailActivity.java @@ -0,0 +1,409 @@ +package com.example.Activity; + +import android.content.Context; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Matrix; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.os.Handler; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.TextView; +import android.widget.Toast; + +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import com.example.DataBase.DatabaseControl; +import com.example.Object.BookObj; +import com.example.Object.CategoryObj; +import com.example.Object.ChapterLinkObj; +import com.example.Object.RecomListObj; +import com.example.Object.ShelfBookObj; +import com.example.R; +import com.example.Service.BookService; + +public class BookDetailActivity extends AppCompatActivity { + + RadioButton addButton; + RadioButton readButton; +// RadioButton downloadButton; + Button moreButton; + Button recom1; + Button recom2; + Button recom3; + + ImageView back; + TextView pageTitle; + ImageView bookCover; + TextView bookTitle; + TextView bookInfo; + TextView updateTime; + TextView follower; + TextView retentionRatio; + TextView bookIntro; + RadioGroup recomRG; + + // 书籍对象 + private BookObj bookObj; + + // 同类书籍 + private CategoryObj categoryObj; + + private List bookObjs = new ArrayList<>(); + + private Bitmap cover; + + private List linkList; + + private StringBuilder stringBuilder = new StringBuilder(); + + Handler mHandler = new Handler(); + + private SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-mm'T'HH:MM:SS"); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_book_detail); + + // 获取控件 + back = findViewById(R.id.detail_back); + pageTitle = findViewById(R.id.detail_title); + addButton = findViewById(R.id.detail_bottom_add); + readButton = findViewById(R.id.detail_bottom_read); +// downloadButton = findViewById(R.id.detail_bottom_download); + moreButton = findViewById(R.id.detail_more); + bookCover = findViewById(R.id.detail_cover); + bookTitle = findViewById(R.id.detail_bookTitle); + bookInfo = findViewById(R.id.detail_TV); + updateTime = findViewById(R.id.detail_update); + follower = findViewById(R.id.detail_follower2); + retentionRatio = findViewById(R.id.detail_retentionRatio2); + bookIntro = findViewById(R.id.detail_longIntro); + recomRG = findViewById(R.id.detail_recomRG); + recom1 = findViewById(R.id.detail_recom1); + recom2 = findViewById(R.id.detail_recom2); + recom3 = findViewById(R.id.detail_recom3); + + Intent intent = getIntent(); + final Bundle bundle = intent.getExtras(); + bookObj = (BookObj) bundle.getSerializable("bookobj"); + + // 获取封面图片 + final String iconURL = BookService.StaticsUrl + bookObj.getCover(); + final Matrix largeMatrix = new Matrix(); + final Matrix littleMatrix = new Matrix(); + largeMatrix.postScale((float) 2, (float) 2); + littleMatrix.postScale((float) 0.4, (float) 0.4); + + if (!isNetWorkConnected(BookDetailActivity.this)) { + Toast.makeText(BookDetailActivity.this, "未连接网络", Toast.LENGTH_SHORT).show(); + } else { + new Thread(new Runnable() { + @Override + public void run() { + try { + URL url = new URL(iconURL); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + connection.setConnectTimeout(10000); + if (connection.getResponseCode() == 200) { + InputStream inputStream = connection.getInputStream(); + cover = BitmapFactory.decodeStream(inputStream); + if (cover != null) { + mHandler.post(new Runnable() { + @Override + public void run() { + Log.d("width", String.valueOf(cover.getWidth())); + Log.d("height", String.valueOf(cover.getHeight())); + littleMatrix.postScale((float) 0.5, (float) 0.5); + } + }); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }).start(); + new Thread(new Runnable() { + @Override + public void run() { + try { + URL url = new URL(iconURL); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + connection.setConnectTimeout(10000); + if (connection.getResponseCode() == 200) { + InputStream inputStream = connection.getInputStream(); + cover = BitmapFactory.decodeStream(inputStream); + mHandler.post(new Runnable() { + @Override + public void run() { + Log.d("width", String.valueOf(cover.getWidth())); + Log.d("height", String.valueOf(cover.getHeight())); + /*if (cover.getWidth() <= 150 && cover.getHeight() <= 200) { + bookCover.setImageBitmap(Bitmap.createBitmap(cover, 0, 0, cover.getWidth(), cover.getHeight(), largeMatrix, true)); + } else if (cover.getWidth() > 300 && cover.getHeight() > 400) { + bookCover.setImageBitmap(Bitmap.createBitmap(cover, 0, 0, cover.getWidth(), cover.getHeight(), littleMatrix, true)); + } else { + bookCover.setImageBitmap(cover); + }*/ + bookCover.setImageBitmap(cover); + } + }); + bookCover.setImageBitmap(cover); + } + } catch (Exception e) { + System.err.println(e.getMessage()); + } + } + }).start(); + + if (!isNetWorkConnected(BookDetailActivity.this)) { + Toast.makeText(BookDetailActivity.this, "未连接网络", Toast.LENGTH_SHORT).show(); + } else { + // 获取书籍相关信息 + new Thread(new Runnable() { + @Override + public void run() { + bookObj = BookService.getBookService().getBookById(bookObj.getId()); + mHandler.post(new Runnable() { + @Override + public void run() { + bookTitle.setText(bookObj.getTitle()); + pageTitle.setText(bookObj.getTitle()); + int wordNum = bookObj.getWordCount() / 10000; + bookInfo.setText(bookObj.getAuthor() + " | " + bookObj.getMinorCate() + " | " + String.valueOf(wordNum) + "万字"); + String updateStr = ""; + try { + Date date = format.parse(bookObj.getUpdated()); + Date now = new Date(System.currentTimeMillis()); + long period = now.getTime() - date.getTime(); + Log.d("period", String.valueOf(period)); + if (period / 86400000 < 1) { + updateStr = "上次更新: 今天"; + } else if (period / 86400000 > 1) { + updateStr = "上次更新: " + String.valueOf(period / 86400000) + "天前"; + } + } catch (ParseException e) { + e.printStackTrace(); + } + updateTime.setText(updateStr); + // int followerNum = bookObj.getLatelyFollower() / 10000; + follower.setText(String.valueOf(bookObj.getLatelyFollower()) + "人"); + retentionRatio.setText(bookObj.getRetentionRatio() + "%"); + String intro = bookObj.getLongIntro(); + if (intro.length() > 80) intro = intro.substring(0, 80); + intro += "..."; + bookIntro.setText(intro); + + new Thread(new Runnable() { + @Override + public void run() { + categoryObj = BookService.getBookService().getBooksByCategoty("reputation", bookObj.getMajorCate(), 0, 10, bookObj.getGender()[0]); + Log.d("size", String.valueOf(categoryObj.getBooks().size())); + for (int i = 0; i < categoryObj.getBooks().size(); i++) { + final int j = i; + final BookObj temp = BookService.getBookService().getBookById(categoryObj.getBooks().get(j).getId()); + mHandler.post(new Runnable() { + @Override + public void run() { + bookObjs.add(temp); + if (j < 3) { + final String iconURL = BookService.StaticsUrl + temp.getCover(); + final Button button = (Button) recomRG.getChildAt(j); + button.setText(bookObjs.get(j).getTitle()); + new Thread(new Runnable() { + @Override + public void run() { + try { + URL url = new URL(iconURL); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + connection.setConnectTimeout(10000); + if (connection.getResponseCode() == 200) { + InputStream inputStream = connection.getInputStream(); + final Bitmap bitmap = BitmapFactory.decodeStream(inputStream); + mHandler.post(new Runnable() { + @Override + public void run() { + Drawable drawable = null; + drawable = new BitmapDrawable(Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), littleMatrix, true)); + drawable.setBounds(0, 0, 270, 360); + button.setCompoundDrawables(null, drawable, null, null); + } + }); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }).start(); + } + } + }); + + + } + } + }).start(); + } + }); + } + }).start(); + } + + recom1.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(BookDetailActivity.this, BookDetailActivity.class); + Bundle bundle = new Bundle(); + bundle.putSerializable("bookobj", bookObjs.get(0)); + intent.putExtras(bundle); + startActivity(intent); + } + }); + + recom2.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(BookDetailActivity.this, BookDetailActivity.class); + Bundle bundle = new Bundle(); + bundle.putSerializable("bookobj", bookObjs.get(1)); + intent.putExtras(bundle); + startActivity(intent); + } + }); + + recom3.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(BookDetailActivity.this, BookDetailActivity.class); + Bundle bundle = new Bundle(); + bundle.putSerializable("bookobj", bookObjs.get(2)); + intent.putExtras(bundle); + startActivity(intent); + } + }); + + // 返回 + back.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + + if (DatabaseControl.getInstance(BookDetailActivity.this).judgeBookExist(bookObj.getId())) { + // 已存在 + setButtonToDelete(); + } else { + // 不存在 + setButtonToAdd(); + } + + // 阅读 + readButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(BookDetailActivity.this, ReadPageActivity.class); + Bundle bundle = new Bundle(); + bundle.putString("bookid", bookObj.getId()); + intent.putExtras(bundle); + startActivity(intent); + } + }); + + // 下载 + /*downloadButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + *//*new Thread(new Runnable() { + @Override + public void run() { + for (int i = 0; i < linkList.size(); i++) { + ChapterObj chapterObj = BookService.getBookService().getChapterByLink(linkList.get(i).getLink()); + stringBuilder.append(chapterObj.getIchapter().getTitle()); + stringBuilder.append("\n"); + stringBuilder.append(chapterObj.getIchapter().getBody()); + } + + } + }).start();*//* + Toast.makeText(BookDetailActivity.this, "功能开发中,敬请期待", Toast.LENGTH_SHORT).show(); + } + });*/ + + // 查看更多同类书籍 + moreButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(BookDetailActivity.this, RecomActivity.class); + Bundle bundle = new Bundle(); + RecomListObj recomListObj = new RecomListObj(bookObjs); + bundle.putSerializable("list", recomListObj); + intent.putExtras(bundle); + startActivity(intent); + } + }); + } + } + + private void setButtonToAdd() { + addButton.setText("加入书架"); + addButton.setTextColor(getResources().getColor(R.color.colorRed)); + addButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + DatabaseControl.getInstance(BookDetailActivity.this).addShelfBook(new ShelfBookObj(bookObj.getId(), bookObj.getTitle(), cover, bookObj.getCover(),0, "online", 0, bookObj.getLongIntro(), bookObj.getAuthor(), bookObj.getMajorCate())); + Toast.makeText(BookDetailActivity.this, "已添加《" + bookObj.getTitle() + "》", Toast.LENGTH_SHORT).show(); + setButtonToDelete(); + } + }); + } + + private void setButtonToDelete() { + addButton.setText("移除书架"); + addButton.setTextColor(getResources().getColor(R.color.colorGrey)); + addButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + DatabaseControl.getInstance(BookDetailActivity.this).deleteShelfBook(bookObj.getId()); + Toast.makeText(BookDetailActivity.this, "已移除《" + bookObj.getTitle() + "》", Toast.LENGTH_SHORT).show(); + setButtonToAdd(); + } + }); + } + + // 辅助函数:判断网络是否连接 + private boolean isNetWorkConnected(Context context) { + if (context != null) { + ConnectivityManager mConnectivityManager = (ConnectivityManager) context + .getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo(); + if (mNetworkInfo != null) { + return mNetworkInfo.isConnected(); + } + } + return false; + } + +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/CategoryActivity.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/CategoryActivity.java new file mode 100644 index 0000000..1995587 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/CategoryActivity.java @@ -0,0 +1,171 @@ +package com.example.Activity; + +import android.support.v4.app.Fragment; +import android.support.v4.view.ViewPager; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.View; +import android.widget.ImageView; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.List; + +import com.example.Fragment.DetailCategoryFragment; +import com.example.Fragment.TabFragmentPagerAdapter; +import com.example.R; + +//这个Activity可用于榜单和具体分类 +public class CategoryActivity extends AppCompatActivity { + private boolean isRanking; //排行榜/分类 + private boolean isMale; //男生/女生 + + private TextView title; + private ImageView backImage; + + private RadioGroup RG; + private RadioButton RB1; + private RadioButton RB2; + private RadioButton RB3; + private RadioButton RB4; + + private ViewPager viewPager; + private List fragmentList = new ArrayList<>(); + private TabFragmentPagerAdapter pagerAdapter; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_category); + //获取传递的参数 + Bundle bundle = this.getIntent().getExtras(); + isRanking = bundle.getBoolean("isRanking"); + isMale = bundle.getBoolean("isMale"); + + //初始化控件 + title = findViewById(R.id.category_activity_title); + backImage = findViewById(R.id.category_activity_back); + RG = findViewById(R.id.category_activity_RG); + RB1 = findViewById(R.id.category_activity_RB1); + RB2 = findViewById(R.id.category_activity_RB2); + RB3 = findViewById(R.id.category_activity_RB3); + RB4 = findViewById(R.id.category_activity_RB4); + viewPager = findViewById(R.id.category_activity_viewPager); + + //设置显示内容 + title.setText(bundle.getString("title")); + if (isRanking) { + RB1.setText("周榜"); + RB2.setText("月榜"); + RB3.setText("总榜"); + RB4.setVisibility(View.GONE); + } + else { + RB1.setText("热门"); + RB2.setText("新书"); + RB3.setText("好评"); + RB4.setVisibility(View.VISIBLE); + } + + //设置返回事件 + backImage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onBackPressed(); + } + }); + + //添加Fragment + if (isRanking) { + //排行榜的Fragment + for (int i = 0; i < 3; ++i) { + DetailCategoryFragment fragment = new DetailCategoryFragment(); + Bundle bundle1 = new Bundle(); + bundle1.putString("title", bundle.getString("title")); + bundle1.putBoolean("isRanking", isRanking); + bundle1.putBoolean("isMale", isMale); + if (i == 0) bundle1.putString("type", "周榜"); + else if (i == 1) bundle1.putString("type", "月榜"); + else bundle1.putString("type", "总榜"); + fragment.setArguments(bundle1); + fragmentList.add(fragment); + } + } + else { + //具体分类的Fragment + for (int i = 0; i < 4; ++i) { + DetailCategoryFragment fragment = new DetailCategoryFragment(); + Bundle bundle1 = new Bundle(); + bundle1.putString("title", bundle.getString("title")); + bundle1.putBoolean("isRanking", isRanking); + bundle1.putBoolean("isMale", isMale); + if (i == 0) bundle1.putString("type", "热门"); + else if (i == 1) bundle1.putString("type", "新书"); + else if (i == 2) bundle1.putString("type", "好评"); + else bundle1.putString("type", "完结"); + fragment.setArguments(bundle1); + fragmentList.add(fragment); + } + } + viewPager.setOnPageChangeListener(new MyPagerChangeListener()); + pagerAdapter = new TabFragmentPagerAdapter(getSupportFragmentManager(), fragmentList); + viewPager.setAdapter(pagerAdapter); + viewPager.setCurrentItem(0); + if (isRanking) viewPager.setOffscreenPageLimit(2); + else viewPager.setOffscreenPageLimit(3); + + //设置RadioGroup响应事件 + RG.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(RadioGroup group, int checkedId) { + switch (checkedId){ + case R.id.category_activity_RB1: + viewPager.setCurrentItem(0); + break; + case R.id.category_activity_RB2: + viewPager.setCurrentItem(1); + break; + case R.id.category_activity_RB3: + viewPager.setCurrentItem(2); + break; + case R.id.category_activity_RB4: + viewPager.setCurrentItem(3); + break; + } + } + }); + + } + + //设置一个ViewPager的监听事件,左右滑动ViewPager时进行处理 + public class MyPagerChangeListener implements ViewPager.OnPageChangeListener { + @Override + public void onPageScrollStateChanged(int arg0) { + } + + @Override + public void onPageScrolled(int arg0, float arg1, int arg2) { + } + + @Override + public void onPageSelected(int arg0) { + switch (arg0) { + case 0: + RB1.setChecked(true); + break; + case 1: + RB2.setChecked(true); + break; + case 2: + RB3.setChecked(true); + break; + case 3: + RB4.setChecked(true); + break; + } + } + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/MainActivity.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/MainActivity.java new file mode 100644 index 0000000..8b4622a --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/MainActivity.java @@ -0,0 +1,228 @@ +package com.example.Activity; + +import android.content.Context; +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.support.v4.app.Fragment; +import android.support.v4.view.ViewPager; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.View; +import android.widget.ImageView; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.List; + +import com.example.Fragment.BookShelfFragment; +import com.example.Fragment.CategoryFragment; +import com.example.Fragment.RankingFragment; +import com.example.Fragment.TabFragmentStatePagerAdapter; +import com.example.R; + +//总体界面,包含书架、排行榜、分类 +public class MainActivity extends AppCompatActivity { + private RadioGroup radioGroup; + private TextView title; + private ImageView search; + + private RadioGroup bottomRG; + private RadioButton bookshelfRB; + private RadioButton rankingRB; + private RadioButton categoryRB; + + private RadioGroup topRG; + private RadioButton maleRB; + private RadioButton femaleRB; + private static Context context = null; + + private ViewPager viewPager; + private List fragmentList = new ArrayList<>(); + private TabFragmentStatePagerAdapter fragmentPagerAdapter; + + public static Context getContext() { + return context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + context = this.getBaseContext(); + //初始化控件 + radioGroup = findViewById(R.id.main_top_RG); + title = findViewById(R.id.main_title); + search = findViewById(R.id.main_search); + bottomRG = findViewById(R.id.main_bottomRG); + bookshelfRB = findViewById(R.id.main_bottom_bookshelf); + rankingRB = findViewById(R.id.main_bottom_ranking); + categoryRB = findViewById(R.id.main_bottom_category); + topRG = findViewById(R.id.main_top_RG); + maleRB = findViewById(R.id.main_top_male); + femaleRB = findViewById(R.id.main_top_female); + viewPager = findViewById(R.id.main_viewPager); + + //初始化Fragment + BookShelfFragment bookShelfFragment = new BookShelfFragment(); + RankingFragment rankingFragment = new RankingFragment(); + Bundle bundle = new Bundle(); + bundle.putBoolean("isMale", true); + rankingFragment.setArguments(bundle); + CategoryFragment categoryFragment = new CategoryFragment(); + fragmentList.add(bookShelfFragment); + fragmentList.add(rankingFragment); + fragmentList.add(categoryFragment); + + viewPager.setOnPageChangeListener(new MyPagerChangeListener()); + fragmentPagerAdapter = new TabFragmentStatePagerAdapter(getSupportFragmentManager(), fragmentList); + viewPager.setAdapter(fragmentPagerAdapter); + viewPager.setCurrentItem(0); + viewPager.setOffscreenPageLimit(2); + + //设置底部按钮图标大小 + Drawable drawable = getResources().getDrawable(R.mipmap.bookshelf_red); + drawable.setBounds(0, 0, 70, 70); + bookshelfRB.setCompoundDrawables(null, drawable , null,null); + drawable = getResources().getDrawable(R.mipmap.ranking); + drawable.setBounds(0, 0, 70, 70); + rankingRB.setCompoundDrawables(null, drawable, null,null); + drawable = getResources().getDrawable(R.mipmap.category); + drawable.setBounds(0, 0, 70, 70); + categoryRB.setCompoundDrawables(null, drawable,null, null); + + //设置顶部按钮图标大小 + drawable = getResources().getDrawable(R.mipmap.male_blue); + drawable.setBounds(0, 0, 70, 70); + maleRB.setCompoundDrawables(null, drawable, null, null); + drawable = getResources().getDrawable(R.mipmap.female_black); + drawable.setBounds(0, 0, 70, 70); + femaleRB.setCompoundDrawables(null, drawable, null, null); + + //处理顶部RG事件 + topRG.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(RadioGroup group, int checkedId) { + switch (checkedId) { + case R.id.main_top_male: + Drawable drawable = getResources().getDrawable(R.mipmap.male_blue); + drawable.setBounds(0, 0, 70, 70); + maleRB.setCompoundDrawables(null, drawable, null, null); + drawable = getResources().getDrawable(R.mipmap.female_black); + drawable.setBounds(0, 0, 70, 70); + femaleRB.setCompoundDrawables(null, drawable, null, null); + RankingFragment rankingFragment1 = new RankingFragment(); + Bundle bundle = new Bundle(); + bundle.putBoolean("isMale", true); + rankingFragment1.setArguments(bundle); + fragmentList.set(1, rankingFragment1); + fragmentPagerAdapter.notifyDataSetChanged(); + viewPager.setCurrentItem(1); + break; + case R.id.main_top_female: + drawable = getResources().getDrawable(R.mipmap.male_black); + drawable.setBounds(0, 0, 70, 70); + maleRB.setCompoundDrawables(null, drawable, null, null); + drawable = getResources().getDrawable(R.mipmap.female_red); + drawable.setBounds(0, 0, 70, 70); + femaleRB.setCompoundDrawables(null, drawable, null, null); + RankingFragment rankingFragment2 = new RankingFragment(); + bundle = new Bundle(); + bundle.putBoolean("isMale", false); + rankingFragment2.setArguments(bundle); + fragmentList.set(1, rankingFragment2); + fragmentPagerAdapter.notifyDataSetChanged(); + viewPager.setCurrentItem(1); + break; + } + } + }); + + //处理底部RG事件 + bottomRG.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(RadioGroup group, int checkedId) { + int index = 0; + switch (checkedId) { + case R.id.main_bottom_bookshelf: + index = 0; + Drawable drawable = getResources().getDrawable(R.mipmap.bookshelf_red); + drawable.setBounds(0, 0, 70, 70); + bookshelfRB.setCompoundDrawables(null, drawable , null,null); + drawable = getResources().getDrawable(R.mipmap.ranking); + drawable.setBounds(0, 0, 70, 70); + rankingRB.setCompoundDrawables(null, drawable, null,null); + drawable = getResources().getDrawable(R.mipmap.category); + drawable.setBounds(0, 0, 70, 70); + categoryRB.setCompoundDrawables(null, drawable,null, null); + break; + case R.id.main_bottom_ranking: + index = 1; + drawable = getResources().getDrawable(R.mipmap.bookshelf); + drawable.setBounds(0, 0, 70, 70); + bookshelfRB.setCompoundDrawables(null, drawable , null,null); + drawable = getResources().getDrawable(R.mipmap.ranking_red); + drawable.setBounds(0, 0, 70, 70); + rankingRB.setCompoundDrawables(null, drawable, null,null); + drawable = getResources().getDrawable(R.mipmap.category); + drawable.setBounds(0, 0, 70, 70); + categoryRB.setCompoundDrawables(null, drawable,null, null); + break; + case R.id.main_bottom_category: + index = 2; + drawable = getResources().getDrawable(R.mipmap.bookshelf); + drawable.setBounds(0, 0, 70, 70); + bookshelfRB.setCompoundDrawables(null, drawable , null,null); + drawable = getResources().getDrawable(R.mipmap.ranking); + drawable.setBounds(0, 0, 70, 70); + rankingRB.setCompoundDrawables(null, drawable, null,null); + drawable = getResources().getDrawable(R.mipmap.category_red); + drawable.setBounds(0, 0, 70, 70); + categoryRB.setCompoundDrawables(null, drawable,null, null); + break; + } + viewPager.setCurrentItem(index); + } + }); + + //搜索按钮点击事件 + search.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + startActivity(new Intent(MainActivity.this, SearchActivity.class)); + } + }); + + } + + //设置一个ViewPager的监听事件,左右滑动ViewPager时进行处理 + public class MyPagerChangeListener implements ViewPager.OnPageChangeListener { + @Override + public void onPageScrollStateChanged(int arg0) { + } + @Override + public void onPageScrolled(int arg0, float arg1, int arg2) { + } + @Override + public void onPageSelected(int arg0) { + switch (arg0) { + case 0: + title.setText("书架"); + radioGroup.setVisibility(View.GONE); + bookshelfRB.setChecked(true); + break; + case 1: + title.setText("排行榜"); + radioGroup.setVisibility(View.VISIBLE); + rankingRB.setChecked(true); + break; + case 2: + title.setText("分类"); + radioGroup.setVisibility(View.GONE); + categoryRB.setChecked(true); + break; + } + } + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/ReadPageActivity.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/ReadPageActivity.java new file mode 100644 index 0000000..22fbc4c --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/ReadPageActivity.java @@ -0,0 +1,1118 @@ +package com.example.Activity; + +import android.app.Dialog; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.os.Bundle; +import android.os.Looper; +import android.support.v4.app.Fragment; +import android.support.v4.view.ViewPager; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.ProgressBar; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import com.example.Fragment.ReadPageFragment; +import com.example.Fragment.TabFragmentStatePagerAdapter; +import com.example.DataBase.DatabaseControl; +import com.example.R; +import com.example.RecyclerView.MyRecyclerViewAdapter; +import com.example.RecyclerView.MyViewHolder; +import com.example.Object.ChapterLinkObj; +import com.example.Object.ChapterObj; +import com.example.Object.CptListObj; +import com.example.Object.UserStatusObj; +import com.example.Service.BookService; +import io.reactivex.Observable; +import io.reactivex.ObservableEmitter; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.observers.DisposableObserver; +import io.reactivex.schedulers.Schedulers; + +import static android.content.Intent.ACTION_TIME_TICK; + + +public class ReadPageActivity extends AppCompatActivity { + private List fragmentList = new ArrayList<>(); //存储所有页面Fragment + private TabFragmentStatePagerAdapter fragmentAdapter; + private ViewPager viewPager; + + private String bookid; // 书籍id + private String bookname; // 书籍名 + private CptListObj cptListObj; //章节列表 + List chapterLinks; // 章节查询链接List + List chapterObjs; // 章节内容OBJ队列 + private int currChapter; //当前阅读到的章节 zero-based + List> chaptersContent; // 每一章每一页的内容 + int totalChapter; // 该书总共的章节数 + int cache_chapter_range_min; // 当前缓冲存储的章节数范围下界 zero-based + int cache_chapter_range_max; // 当前缓冲存储的章节数范围上界 zero-based + + // 处理点击的坐标变量 + private float DownX; + private float DownY; + private float UpX; + private float UpY; + + // 页面控件处理 + private RadioGroup rg_control; + private RadioButton day_and_night_rb_control; + private RadioButton horizontal_and_vertical_rb_control; + private RadioButton setting_rb_control; + //private RadioButton download_rb_control; + private RadioButton catalog_rb_control; + private ProgressBar progressBar; + private RelativeLayout bottom_layout_control; + private TextView battery_percent_control; + private TextView time_control; + private TextView read_page_process_control; + private RelativeLayout whole_layout_control; + + // 屏幕宽高 + float SCREEN_HEIGHT; + float SCREEN_WIDTH; + + // 功能栏是否显示 + boolean show_functional_button = false; + + // 活动上下文 + Context context; + + // 广播 + MyReceiver myReceiver; + IntentFilter intentFilter; + + // 用户阅读状态 + UserStatusObj userStatusObj; + boolean is_vertical_screen; + int day_or_night_status; + int textSize; + + // 目录弹窗 + MyRecyclerViewAdapter adapter; + List myCategory; + + // 设置功能按钮是否可点击 + boolean clickable = false; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_read_page); + System.out.println("onCreate创建"); + + //从传递的参数中获取章节相关信息 + Intent intent = this.getIntent(); + Bundle bundle = intent.getExtras(); + bookid = bundle.getString("bookid"); + bookname = bundle.getString("bookname"); + currChapter = bundle.getInt("currentChapter"); + //System.out.println("bookid: " + bookid + " currentChapter: " + currChapter); + + + // 获取页面控件 + init_page_control(); + + // 设置用户阅读习惯状态与界面适配 + set_Reading_Status(); + + // 获取页面宽高 + get_screen_info(); + + // 注册底部信息栏的系统接收广播 + init_info_broadcast(); + + // 设置功能按键 + set_functional_button(); + + // 获取上下文 + context = this; + // 全屏阅读,去除手机状态栏 + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + + // 初始化底部信息栏显示 + init_bottom_info_layout(); + + //初始化 Fragment + init_fragment(); + } + + // 从数据库中获取用户的阅读习惯 + private void set_Reading_Status() { + // 获取用户状态(默认用户状态) + userStatusObj = DatabaseControl.getInstance(this).get_User_Status_Obj(0); + // 获取默认用户下的横竖屏状态 + int hor_or_ver_screen = userStatusObj.getHor_or_ver_screen(); + //System.out.println("从数据库中获取到的横竖屏状态: " + hor_or_ver_screen); + if(hor_or_ver_screen == 1) { + is_vertical_screen = true; + System.out.println("新建Activity:数据库中是竖屏状态"); + } + else { + is_vertical_screen = false; + System.out.println("新建Activity:数据库中是横屏状态"); + // 切换成横屏 + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + } + + day_or_night_status = userStatusObj.getDay_or_night_status(); + if(day_or_night_status == 1) whole_layout_control.setBackgroundColor(getResources().getColor(R.color.nightBackGround)); + + textSize = userStatusObj.getTextSize(); + } + + // 初始化底部信息栏显示 + private void init_bottom_info_layout() { + // 设置当前时间 + // 设置时间格式 + SimpleDateFormat formatter = new SimpleDateFormat("HH:mm"); + // 获取当前时间 + Date curdate = new Date(System.currentTimeMillis()); + // 按照格式将Date 时间转化成格式字符串 + String time = formatter.format(curdate); + // UI设置显示 + time_control.setText(time); + } + + // 注册底部信息栏的系统接收广播 + private void init_info_broadcast() { + //注册广播接受者java代码 + intentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); // 电量变化广播 + intentFilter.addAction(ACTION_TIME_TICK); + //创建广播接受者对象 + myReceiver = new MyReceiver(); + //注册receiver + registerReceiver(myReceiver, intentFilter); + } + + // 阅读帧初始化 + private void init_fragment() { + // 设置等待进度条 + progressBar.setVisibility(View.VISIBLE); + viewPager.setVisibility(View.GONE); + clickable = false; + // 清空当前的FragmentList + fragmentList.clear(); + System.out.println("上次看到的章节数为:(zero-based)" + currChapter); + // 用线程进行帧初始化,避免进入阅读界面阻塞 + Thread init_fragment_thread = new Thread(new Runnable() { + @Override + public void run() { + // 判断是否联网了 + Boolean isNetworkConnected = isNetWorkConnected(context); + // 未联网的响应处理 + if(!isNetworkConnected) { + Looper.prepare(); + // 弹出Toast提示 + Toast.makeText(ReadPageActivity.this, "网络未连接,书籍获取失败", Toast.LENGTH_SHORT).show(); + ReadPageActivity.this.finish(); + Looper.loop(); + // ProgressBar等待框消失 + progressBar.setVisibility(View.GONE); + } + // 已经联网,获取书籍信息进行阅读 + else { + //获取到:章节总页数totalPage、章节title、每页的内容content + Thread initContentThread = new Thread(new Runnable() { + @Override + public void run() { + // 获取所有章节信息 + cptListObj = BookService.getBookService().getChaptersByBookId(bookid); + if(cptListObj != null) { + chapterLinks = cptListObj.getImixToc().getChapterLinks(); + totalChapter = chapterLinks.size(); + System.out.println("共有章节数目: " + totalChapter); + /*for(int i = 0; i < chapterLinks.size(); i++) { + System.out.println(chapterLinks.get(i).getTitle() + ": " + chapterLinks.get(i).getLink()); + }*/ + chaptersContent = new ArrayList<>(totalChapter); + + // 缓存当前章节以及上下10章的数据 + chapterObjs = new ArrayList(totalChapter) { + }; + cache_chapter_range_min = currChapter - 10; + cache_chapter_range_max = currChapter + 10; + for (int i = cache_chapter_range_min; i <= cache_chapter_range_max; i++) { + System.out.println("正在下载(zero-based): i---" + i + " min---" + cache_chapter_range_min + "---max---" + cache_chapter_range_max); + //超出章节范围 + if (i > totalChapter - 1) { + //cache_chapter_range_max--; + cache_chapter_range_max = totalChapter - 1; + break; + //continue; + } + if (i < 0) { + cache_chapter_range_min++; + continue; + } + ChapterObj c = BookService.getBookService().getChapterByLink(chapterLinks.get(i).getLink()); + //System.out.println(chapterLinks.get(i).getLink()); + chapterObjs.add(i - cache_chapter_range_min, c); + //System.out.println(i); + } + System.out.println(cache_chapter_range_min + "----" + cache_chapter_range_max); + //System.out.println(chapterLinks.size()); + + //currentChapterContent.append(c.getIchapter().getBody()); + //System.out.println(c.getIchapter().getTitle() + "\n" + c.getIchapter().getBody()); + } + else { + Looper.prepare(); + // 弹出Toast提示 + Toast.makeText(ReadPageActivity.this, "无法获取书籍源", Toast.LENGTH_SHORT).show(); + ReadPageActivity.this.finish(); + Looper.loop(); + } + } + }); + initContentThread.start(); + + try { + initContentThread.join(); + } catch (InterruptedException e) { + Log.d("[Error] ", "线程获取信息失败"); + e.printStackTrace(); + } + + // 将章节内容分页 + // 512字节长度一页 + /*currTotalPage = content.length()/pageLen + 1; + System.out.println("分成了" + currTotalPage + "页"); + List pages = getStrList(content, pageLen); + System.out.println("已经分割成: " + pages.size() + "页"); + System.out.println(pages.get(0));*/ + + /*System.out.println("Test: "); + int len1 = "l".length(); + int len2 = "好".length(); + int len3 = ",".length(); + int len4 = ",".length(); + int len5 = "\n".length(); + String test = "\u3000\u3000大漠。\r\n\u3000\u3000YES"; + System.out.println(test); + int len6 = test.length(); + System.out.println("长度:" + len1 + " " + len2 + " " + len3 + " " + len4 + " " + len5 + " " + len6);*/ + + // 根据内容适配各帧 + int count =(cache_chapter_range_max-cache_chapter_range_min+1); + System.out.println(count); + for (int i = cache_chapter_range_min; i <= cache_chapter_range_max; ++i) { + // 解析章节内容 + //String title = chapterObjs.get(0).getIchapter().getTitle(); // 这种获取Title的内容错误的(API问题) + String title = chapterLinks.get(i).getTitle(); + String content; + if(chapterObjs.get(i-cache_chapter_range_min) == null) { + content = "章节获取失败了呢!客官"; + } + else content = chapterObjs.get(i-cache_chapter_range_min).getIchapter().getBody(); + // 为段首添加缩进 + content = "\u3000\u3000" + content; + content = content.replaceAll("\n", "\n\u3000\u3000"); + // 新建对应章节内容帧 + ReadPageFragment fragment = new ReadPageFragment(); + // 给帧传数据 + Bundle bundle = new Bundle(); + bundle.putString("title", title); + bundle.putString("content", content); + bundle.putInt("day_or_night_status", day_or_night_status); + bundle.putInt("textSize", textSize); + fragment.setArguments(bundle); + // 将新加的帧放入队列中 + fragmentList.add(fragment); + } + + viewPager.setOnPageChangeListener(new MyPagerChangeListener()); + fragmentAdapter = new TabFragmentStatePagerAdapter(getSupportFragmentManager(), fragmentList); + + // 用rxjava更新主线程 + rxjava_update_page(0); + + } + } + }); + init_fragment_thread.start(); + + } + + // 获取屏幕宽高等信息 + private void get_screen_info() { + DisplayMetrics dm = getResources().getDisplayMetrics(); + SCREEN_HEIGHT = dm.heightPixels; + SCREEN_WIDTH = dm.widthPixels; + /*String str = "屏幕宽高:" + SCREEN_WIDTH + ":" + SCREEN_HEIGHT; + Toast.makeText(ReadPageActivity.this, str, Toast.LENGTH_SHORT).show();*/ + } + + @Override + protected void onPause() { + System.out.println("onPause"); + // 将阅读到的当前章节存入数据库 + DatabaseControl.getInstance(this).updateProgress(currChapter, bookid); + // 将当前设置的用户习惯存入数据库(报错) + userStatusObj.setDay_or_night_status(day_or_night_status); + userStatusObj.setHor_or_ver_screen((is_vertical_screen?1:0)); + userStatusObj.setTextSize(textSize); + DatabaseControl.getInstance(this).updateStatus(0,userStatusObj); + super.onPause(); + } + + @Override + protected void onDestroy() { + System.out.println("onDestroy"); + System.out.println("横竖屏状况:" + ((is_vertical_screen) ? "竖屏":"横屏")); + // todo:注销广播 + unregisterReceiver(myReceiver); + super.onDestroy(); + } + + // 屏幕点击处理 + // 处理屏幕滑动翻页和点击中部弹出功能按键底框 + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + if(!clickable) return false; + if (MotionEvent.ACTION_DOWN == event.getAction()) { + DownX = event.getX(); + DownY = event.getY(); + } + else if (MotionEvent.ACTION_UP == event.getAction()) { + UpX = event.getX(); + UpY = event.getY(); + } + + // 滑动事件 + if(Math.abs(UpX-DownX) > 10 || Math.abs(UpY-DownY)>10) { + + } + // 点击事件 + else { + System.out.println("点击位置:" + DownX + ":" + DownY); + System.out.println("屏幕宽高:" + SCREEN_WIDTH + " " + SCREEN_HEIGHT); + if (DownX > SCREEN_WIDTH / 3 && DownX < SCREEN_WIDTH * 2 / 3 && DownY > SCREEN_HEIGHT / 5 && DownY < SCREEN_HEIGHT * 4 / 5) { + if (show_functional_button) { + rg_control.setVisibility(View.GONE); + bottom_layout_control.setVisibility(View.VISIBLE); + show_functional_button = false; + } else { + bottom_layout_control.setVisibility(View.GONE); + rg_control.setVisibility(View.VISIBLE); + show_functional_button = true; + } + + } /*else if (DownX <= SCREEN_WIDTH / 3) { + // todo:翻页有bug + Toast.makeText(ReadPageActivity.this, "向上翻页", Toast.LENGTH_SHORT).show(); + System.out.println("当前阅读到的章节: " + (currChapter+1)); + if(currChapter-1 >= cache_chapter_range_min) + viewPager.setCurrentItem((currChapter-1-cache_chapter_range_min), false); + } else { + // todo:翻页有bug + Toast.makeText(ReadPageActivity.this, "向下翻页", Toast.LENGTH_SHORT).show(); + System.out.println("当前阅读到的章节:" + (currChapter+1)); + if(currChapter+1 <= cache_chapter_range_max) + viewPager.setCurrentItem((currChapter+1-cache_chapter_range_min), false); + }*/ + } + + + return super.dispatchTouchEvent(event); + } + + // 设置功能按键 + // 图标样式&&点击处理 + private void set_functional_button() { + // 设置底部功能按钮的大小 + Drawable drawable; + // 根据当前阅读日间/夜间模式设置图标 + + if(day_or_night_status == 0) { + drawable = getResources().getDrawable(R.mipmap.nighttime); + drawable.setBounds(0, 0, 70, 70); + day_and_night_rb_control.setCompoundDrawables(null, drawable, null, null); + day_and_night_rb_control.setText("夜间"); + } + else { + drawable = getResources().getDrawable(R.mipmap.daytime); + drawable.setBounds(0, 0, 70, 70); + day_and_night_rb_control.setCompoundDrawables(null, drawable, null, null); + day_and_night_rb_control.setText("日间"); + } + // 根据当前横竖屏状况设置图标 + if(is_vertical_screen) { + drawable = getResources().getDrawable(R.mipmap.horizontal_screen); + drawable.setBounds(0, 0, 70, 70); + horizontal_and_vertical_rb_control.setCompoundDrawables(null, drawable, null,null); + horizontal_and_vertical_rb_control.setText("横屏"); + horizontal_and_vertical_rb_control.setTextColor(Color.BLACK); + } + else { + drawable = getResources().getDrawable(R.mipmap.vertical_screen); + drawable.setBounds(0, 0, 70, 70); + horizontal_and_vertical_rb_control.setCompoundDrawables(null, drawable, null,null); + horizontal_and_vertical_rb_control.setText("竖屏"); + horizontal_and_vertical_rb_control.setTextColor(Color.BLACK); + } + drawable = getResources().getDrawable(R.mipmap.textsize); + drawable.setBounds(0, 0, 70, 70); + setting_rb_control.setCompoundDrawables(null, drawable,null, null); + /*drawable = getResources().getDrawable(R.mipmap.download); + drawable.setBounds(0, 0, 70, 70); + download_rb_control.setCompoundDrawables(null, drawable,null, null);*/ + drawable = getResources().getDrawable(R.mipmap.catalog); + drawable.setBounds(0, 0, 70, 70); + catalog_rb_control.setCompoundDrawables(null, drawable,null, null); + // 设置功能按钮的点击响应处理 + // 夜间/白日功能切换 + day_and_night_rb_control.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if(day_or_night_status == 0) { + whole_layout_control.setBackgroundColor(getResources().getColor(R.color.nightBackGround)); + day_or_night_status = 1; + //userStatusObj.setDay_or_night_status(day_or_night_status); + //DatabaseControl.getInstance(context).updateStatus(0, userStatusObj); + changeFrameStyle(); + day_and_night_rb_control.setTextColor(Color.BLACK); + Drawable drawable = getResources().getDrawable(R.mipmap.daytime); + drawable.setBounds(0, 0, 70, 70); + day_and_night_rb_control.setCompoundDrawables(null, drawable, null, null); + day_and_night_rb_control.setText("日间"); + } + else { + whole_layout_control.setBackgroundColor(getResources().getColor(R.color.PapayaWhip)); + day_or_night_status = 0; + //userStatusObj.setDay_or_night_status(day_or_night_status); + //DatabaseControl.getInstance(context).updateStatus(0, userStatusObj); + //init_fragment(); + changeFrameStyle(); + day_and_night_rb_control.setTextColor(Color.BLACK); + Drawable drawable = getResources().getDrawable(R.mipmap.nighttime); + drawable.setBounds(0, 0, 70, 70); + day_and_night_rb_control.setCompoundDrawables(null, drawable, null, null); + day_and_night_rb_control.setText("夜间"); + } + } + }); + + // 横屏竖屏功能切换 + horizontal_and_vertical_rb_control.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + // 当前竖屏状态 + if(is_vertical_screen) { + // 记录状态数据转变,更新默认用户 + is_vertical_screen = false; + //userStatusObj.setHor_or_ver_screen(0); + horizontal_and_vertical_rb_control.setTextColor(Color.BLACK); + //DatabaseControl.getInstance(context).updateStatus(0,0); + //DatabaseControl.getInstance(context).updateStatus(0, userStatusObj); + // 切换成横屏 + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + Drawable drawable = getResources().getDrawable(R.mipmap.vertical_screen); + drawable.setBounds(0, 0, 70, 70); + horizontal_and_vertical_rb_control.setCompoundDrawables(null, drawable, null,null); + horizontal_and_vertical_rb_control.setText("竖屏"); + horizontal_and_vertical_rb_control.setTextColor(Color.BLACK); + } + // 当前横屏状态 + else { + // 记录状态数据转变 + is_vertical_screen = true; + //userStatusObj.setHor_or_ver_screen(1); + horizontal_and_vertical_rb_control.setTextColor(Color.BLACK); + //DatabaseControl.getInstance(context).updateStatus(0,1); + //DatabaseControl.getInstance(context).updateStatus(0, userStatusObj); + System.out.println("改成竖屏"); + System.out.println(DatabaseControl.getInstance(context).get_Hor_Or_Ver_Screen_Status(0)); + // 切换成竖屏状态 + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + Drawable drawable = getResources().getDrawable(R.mipmap.horizontal_screen); + drawable.setBounds(0, 0, 70, 70); + horizontal_and_vertical_rb_control.setCompoundDrawables(null, drawable, null,null); + horizontal_and_vertical_rb_control.setText("横屏"); + horizontal_and_vertical_rb_control.setTextColor(Color.BLACK); + } + } + }); + // 字体样式和大小设置功能 + setting_rb_control.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + // 弹出一个字体样式大小设置框 + final Dialog dialog = new Dialog(context); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(R.layout.dialog_text_setting); + // 字体不变红色 + setting_rb_control.setTextColor(Color.BLACK); + + final WindowManager.LayoutParams params = dialog.getWindow().getAttributes(); + params.width = (int)(SCREEN_WIDTH * 2 / 3); + /*params.height = (int)(SCREEN_HEIGHT * 2 / 3);*/ + dialog.getWindow().setAttributes(params); + ImageView textSize_plus_control = dialog.findViewById(R.id.dialog_text_setting_plus_imageview); + final ImageView textSize_minus_control = dialog.findViewById(R.id.dialog_text_setting_minus_imageview); + final TextView textSize_textView = dialog.findViewById(R.id.dialog_text_setting_textSize); + textSize_textView.setText(Integer.toString(textSize)); + textSize_minus_control.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if(textSize > 10) textSize-=2; + textSize_textView.setText(Integer.toString(textSize)); + changeFrameStyle(); + } + }); + textSize_plus_control.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if(textSize < 50) textSize+=2; + textSize_textView.setText(Integer.toString(textSize)); + changeFrameStyle(); + } + }); + // 设置 dialog 属性并显示 + dialog.setCancelable(true); + dialog.show(); + + dialog.setOnCancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + changeFrameStyle(); + } + }); + } + }); + // 下载功能 + /*download_rb_control.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Toast.makeText(ReadPageActivity.this, "文本下载功能还没实现呢!客官", Toast.LENGTH_LONG).show(); + } + });*/ + // 目录功能 + catalog_rb_control.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + // 弹出一个目录选择框 + final Dialog dialog = new Dialog(context); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(R.layout.catalog_dialog); + // 隐藏功能按钮控件框 + rg_control.setVisibility(View.GONE); + show_functional_button = false; + bottom_layout_control.setVisibility(View.VISIBLE); + // 字体不变红色 + catalog_rb_control.setTextColor(Color.BLACK); + // 设置dialog标题为书名 + TextView title = dialog.findViewById(R.id.catalog_title); + title.setText(bookname); + // 书籍目录RecyclerView + RecyclerView dialog_catalog = dialog.findViewById(R.id.catalog_recylerView); + // 书籍目录数据初始化 + myCategory = new ArrayList<>(); + for(int i = 0; i < chapterLinks.size(); i++) + myCategory.add(chapterLinks.get(i).getTitle()); + + // 设置 Adapter + adapter = new MyRecyclerViewAdapter(context, R.layout.item_catalog, myCategory) { + @Override + public void convert(MyViewHolder holder, String s) { + TextView title = holder.getView(R.id.catalog_title); + title.setText(s); + } + }; + // 设置点击目录跳转到相应章节 + adapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() { + @Override + public void onClick(int position) { + // dialog目录框消失 + dialog.dismiss(); + // 设置等待进度条 + viewPager.setVisibility(View.GONE); + progressBar.setVisibility(View.VISIBLE); + clickable = false; + // 清空当前的FragmentList + fragmentList.clear(); + // 设置跳转章节数 + currChapter = position; + // 加载帧 + init_fragment(); + // 更新UI + //rxjava_update_page(2); + } + + @Override + public void onLongClick(int position) { + + } + }); + + final WindowManager.LayoutParams params = dialog.getWindow().getAttributes(); + params.width = (int)(SCREEN_WIDTH * 2 / 3); + params.height = (int)(SCREEN_HEIGHT * 2 / 3); + dialog.getWindow().setAttributes(params); + + // 适配 Adapter + dialog_catalog.setAdapter(adapter); + + // 设置 RecyclerView 布局 + dialog_catalog.setLayoutManager(new LinearLayoutManager(context)); + + // 设置 dialog 属性并显示 + dialog.setCancelable(true); + dialog.show(); + } + }); + } + + // 获取页面控件 + private void init_page_control() { + rg_control = findViewById(R.id.read_page_bottom_rg); + day_and_night_rb_control = findViewById(R.id.read_page_day_and_night_rb); + horizontal_and_vertical_rb_control = findViewById(R.id.read_page_horizontal_and_vertical_rb); + setting_rb_control = findViewById(R.id.read_page_setting_rb); + //download_rb_control = findViewById(R.id.read_page_download_rb); + catalog_rb_control = findViewById(R.id.read_page_catalog_rb); + viewPager = findViewById(R.id.read_page_viewPager); + progressBar = findViewById(R.id.read_page_progressbar); + bottom_layout_control = findViewById(R.id.activity_read_page_bottom_layout); + battery_percent_control = findViewById(R.id.activity_read_page_battery_percent); + time_control = findViewById(R.id.activity_read_page_time); + read_page_process_control = findViewById(R.id.activity_read_page_process); + whole_layout_control = findViewById(R.id.read_page_whole_layout); + } + + //设置一个ViewPager的监听事件,左右滑动ViewPager时进行处理 + //当滑动到当前缓存的倒数第M章的时候,进行网络资源访问,获取新的N章的资源 + public class MyPagerChangeListener implements ViewPager.OnPageChangeListener { + int from; + @Override + public void onPageScrollStateChanged(int arg0) { + + } + @Override + public void onPageScrolled(int arg0, float arg1, int arg2) { + from = arg0; + } + + @Override + public void onPageSelected(final int arg0) { + Log.d("跳转", arg0 + ", " + from); + + int cache_left = 5; // 设置当缓存剩余多少章节时,重新开始进行资源获取 + final int cache_num = 10; // 设置一次获取资源的章节数 + // 帧界面向右滑动了一次 + if (arg0 == from + 1) { + // 当前章节数+1 + currChapter++; + // 设置进度显示 + read_page_process_control.setText(Integer.toString(currChapter+1) + "/" + Integer.toString(totalChapter)); + // 滑动到当前缓存剩余量不多时,当前再访问剩余量设置是五章节(不包括当前章节) + if(arg0 == (cache_chapter_range_max-cache_chapter_range_min) - cache_left) { + + // 已经缓存到网络上的最后一章了,没有更新 + if(cache_chapter_range_max == totalChapter) { + //Toast.makeText(ReadPageActivity.this, "已经是最后一章了!客官", Toast.LENGTH_LONG).show(); + } + else { + // 隐藏ViewPager避免添加帧的时候滑动ViewPager报错 + // 等待后台适配阅读帧 + viewPager.setVisibility(View.GONE); + progressBar.setVisibility(View.VISIBLE); + clickable = false; + //使用子线程进行缓存更新 + Thread update_cache_thread = new Thread(new Runnable() { + @Override + public void run() { + // 再使用子线程进行网络访问,获取下面N个章节的内容(当前N设置为10) + /*final int newChapterNum = arg0 + 1;*/ + Thread getNewChapterThread = new Thread(new Runnable() { + @Override + public void run() { + if(isNetWorkConnected(context)) { + for (int i = 1; i <= cache_num; i++) { + int newChapterNum = cache_chapter_range_max + i; + // 非法章节数(已超出网络给出的章节数) + if (newChapterNum >= totalChapter) continue; + // 合法章节则获取新章节 + ChapterObj c = BookService.getBookService().getChapterByLink(chapterLinks.get(newChapterNum).getLink()); + System.out.println("正在下载(zero-based): newChapterNum---" + newChapterNum + " min---" + cache_chapter_range_min + "---max---" + cache_chapter_range_max); + System.out.println("获取章节: " + newChapterNum + "------" + chapterLinks.get(newChapterNum).getLink()); + chapterObjs.add(newChapterNum - cache_chapter_range_min, c); + } + } + else { + Log.e("ERROR", "网络连接状况:未连接"); + } + } + }); + getNewChapterThread.start(); + + // 等待网络访问子线程完成 + try { + getNewChapterThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + System.out.println("子线程更新完毕"); + // 新增N个帧 + for(int i = 1; i <= cache_num; i++) { + int newChapterNum = cache_chapter_range_max + 1; + // 已经超出总章节数 + if(newChapterNum >= totalChapter) continue; + // 网络连接故障,要获取的章节未缓存成功,不添加新帧 + if(newChapterNum - cache_chapter_range_min >= chapterObjs.size()) break; + // 合法的章节数 + cache_chapter_range_max++; + // 解析章节内容 + //String title = chapterObjs.get(0).getIchapter().getTitle(); // 这种获取Title的内容错误的(API问题) + String title = chapterLinks.get(newChapterNum).getTitle(); + String content; + if(chapterObjs.get(newChapterNum-cache_chapter_range_min) == null) { + content = "章节获取失败了呢!客官"; + } + else content = chapterObjs.get(newChapterNum-cache_chapter_range_min).getIchapter().getBody(); + // 为段首添加缩进 + content = "\u3000\u3000" + content; + content = content.replaceAll("\n", "\n\u3000\u3000"); + // 新建对应章节内容帧 + ReadPageFragment fragment = new ReadPageFragment(); + // 给帧传数据 + Bundle bundle = new Bundle(); + bundle.putString("title", title); + bundle.putString("content", content); + bundle.putInt("day_or_night_status", day_or_night_status); + bundle.putInt("textSize", textSize); + fragment.setArguments(bundle); + // 将新加的帧放入队列中 + fragmentList.add(fragment); + } + // 使用rxjava进行主界面UI更新 + rxjava_update_page(1); + System.out.println("更新章节: "); + } + }); + update_cache_thread.start(); + } + + } + } + // 向左滑动一页 + else if (arg0 == from) { + // 当前章节数-1 + currChapter--; + // 设置进度显示 + read_page_process_control.setText(Integer.toString(currChapter+1) + "/" + Integer.toString(totalChapter)); + // 滑动到当前缓存剩余量不多时,当前再访问剩余量设置是五章节(不包括当前章节) + System.out.println("arg0-currChapter-min-max: " + arg0 + " " + currChapter + " " + cache_chapter_range_min + " " + cache_chapter_range_max); + if((currChapter-cache_chapter_range_min) == cache_left) { + // 已经是网络上的第一章了 + if(cache_chapter_range_min == 0) { + //Toast.makeText(ReadPageActivity.this, "已经是第一章了!客官", Toast.LENGTH_LONG).show(); + } + else { + // 隐藏ViewPager避免添加帧的时候滑动ViewPager报错 + // 等待后台适配阅读帧 + viewPager.setVisibility(View.GONE); + progressBar.setVisibility(View.VISIBLE); + clickable = false; + //使用子线程进行缓存更新 + Thread update_cache_thread = new Thread(new Runnable() { + @Override + public void run() { + // 再使用子线程进行网络访问,获取下面N个章节的内容(当前N设置为10) + /*final int newChapterNum = arg0 + 1;*/ + Thread getNewChapterThread = new Thread(new Runnable() { + @Override + public void run() { + if(isNetWorkConnected(context)) { + for (int i = 1; i <= cache_num; i++) { + int newChapterNum = cache_chapter_range_min - i; + // 非法章节数(已经到第一章了) + if (newChapterNum < 0) continue; + // 合法章节则获取新章节 + ChapterObj c = BookService.getBookService().getChapterByLink(chapterLinks.get(newChapterNum).getLink()); + System.out.println(chapterLinks.get(newChapterNum).getLink()); + // 在队列头插入章节信息 + chapterObjs.add(0, c); + } + } + } + }); + getNewChapterThread.start(); + + // 等待网络访问子线程完成 + try { + getNewChapterThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + // 新增N个帧 + for(int i = 1; i <= cache_num; i++) { + int newChapterNum = cache_chapter_range_min - 1; + // 比第一章还小,非法章节数 + if(newChapterNum < 0) continue; + // 因网络故障未缓存到所要章节 + if(cache_chapter_range_max - cache_chapter_range_min + 1 >= chapterObjs.size()) break; + // 合法的章节数 + cache_chapter_range_min--; + // 解析章节内容 + //String title = chapterObjs.get(0).getIchapter().getTitle(); // 这种获取Title的内容错误的(API问题) + String title = chapterLinks.get(newChapterNum).getTitle(); + String content; + if(chapterObjs.get(newChapterNum-cache_chapter_range_min) == null) { + content = "章节获取失败了呢!客官"; + } + else content = chapterObjs.get(newChapterNum-cache_chapter_range_min).getIchapter().getBody(); + // 为段首添加缩进 + content = "\u3000\u3000" + content; + content = content.replaceAll("\n", "\n\u3000\u3000"); + // 新建对应章节内容帧 + ReadPageFragment fragment = new ReadPageFragment(); + // 给帧传数据 + Bundle bundle = new Bundle(); + bundle.putString("title", title); + bundle.putString("content", content); + bundle.putInt("day_or_night_status", day_or_night_status); + bundle.putInt("textSize", textSize); + fragment.setArguments(bundle); + // 将新加的帧放入队列中 + fragmentList.add(0,fragment); + } + // 使用rxjava进行主界面UI更新 + rxjava_update_page(2); + System.out.println("更新章节: "); + } + }); + update_cache_thread.start(); + } + + } + } + } + } + + // 辅助函数:判断网络是否连接 + public boolean isNetWorkConnected(Context context) { + if (context != null) { + ConnectivityManager mConnectivityManager = (ConnectivityManager) context + .getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo(); + if (mNetworkInfo != null) { + return mNetworkInfo.isConnected(); + } + } + return false; + } + + // RXJAVA2 更新主界面UI + private void rxjava_update_page(final int type) { + final Observable observable = Observable.create(new ObservableOnSubscribe() { + + @Override + public void subscribe(ObservableEmitter e) throws Exception { + e.onNext(type); + e.onComplete(); + } + + }); + + CompositeDisposable mCompositeDisposable = new CompositeDisposable(); + + DisposableObserver disposableObserver = new DisposableObserver() { + @Override + public void onNext(Integer value) { + Log.d("BackgroundActivity", "onNext"); + // type = 0 界面初始化更新 + if(type == 0) { + // 初始化适配阅读帧 + fragmentAdapter.notifyDataSetChanged(); + viewPager.setAdapter(fragmentAdapter); + // 跳到上次阅读到的章节 + viewPager.setCurrentItem(currChapter-cache_chapter_range_min); + // 适配完毕,取消ProgressBar, 隐藏功能按键,显示底部信息栏 + progressBar.setVisibility(View.GONE); + rg_control.setVisibility(View.GONE); + viewPager.setVisibility(View.VISIBLE); + clickable = true; + read_page_process_control.setText(Integer.toString(currChapter+1) + "/" + Integer.toString(totalChapter)); + bottom_layout_control.setVisibility(View.VISIBLE); + } + // type == 1 界面获取下N章节更新 + else if(type == 1) { + fragmentAdapter.notifyDataSetChanged(); + // 适配完毕,取消ProgressBar, 隐藏功能按键 + progressBar.setVisibility(View.GONE); + viewPager.setVisibility(View.VISIBLE); + clickable = true; + } + // type == 2 界面获取上N章节更新 + else if(type == 2) { + // 适配Adapter + fragmentAdapter.notifyDataSetChanged(); + // 跳回到刚才阅读到的章节 + viewPager.setCurrentItem((currChapter-cache_chapter_range_min), false); + // 适配完毕,取消ProgressBar, 隐藏功能按键 + progressBar.setVisibility(View.GONE); + viewPager.setVisibility(View.VISIBLE); + clickable = true; + } + } + + @Override + public void onError(Throwable e) { + Log.d("BackgroundActivity", "onError=" + e); + } + + @Override + public void onComplete() { + Log.d("BackgroundActivity", "onComplete"); + } + }; + + observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(disposableObserver); + mCompositeDisposable.add(disposableObserver); + + } + + // 辅助函数 : 将字符串按指定长度分割 + public static List getStrList(String inputString, int length) { + int size = inputString.length() / length; + if (inputString.length() % length != 0) { + size += 1; + } + List res = new ArrayList<>(); + for(int i = 0; i < size - 1; i++) { + String s = inputString.substring(i*length, (i+1)*length-1); + res.add(s); + } + String s = inputString.substring((size-1)*length); + res.add(s); + return res; + } + + // 注册获取系统广播 + // 广播获取系统电量和时间 + class MyReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + // TODO Auto-generated method stub + // 判断它是否是为电量变化的Broadcast Action + // 电量变化广播 + if(Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())){ + //获取当前电量 + int level = intent.getIntExtra("level", 0); + //电量的总刻度 + int scale = intent.getIntExtra("scale", 100); + //把它转成百分比 + int percent = level*100/scale; + battery_percent_control.setText(Integer.toString(percent)); + } + else if (Intent.ACTION_TIME_TICK.equals(intent.getAction())) { + // 设置时间格式 + SimpleDateFormat formatter = new SimpleDateFormat("HH:mm"); + // 获取当前时间 + Date curdate = new Date(System.currentTimeMillis()); + // 按照格式将Date 时间转化成格式字符串 + String time = formatter.format(curdate); + // UI设置显示 + time_control.setText(time); + } + } + + } + + + // 当使用功能按键切换阅读界面阅读习惯时 + // 不必要重新进行网络访问 + // 直接改变阅读帧的样式 + public void changeFrameStyle() { + System.out.println("---------[changeFrameStyle]-----------"); + // 设置等待进度条 + progressBar.setVisibility(View.VISIBLE); + viewPager.setVisibility(View.GONE); + // 清空当前的FragmentList + fragmentList.clear(); + for(int i = cache_chapter_range_min; i<= cache_chapter_range_max; i++) { + // 解析章节内容 + //String title = chapterObjs.get(0).getIchapter().getTitle(); // 这种获取Title的内容错误的(API问题) + String title = chapterLinks.get(i).getTitle(); + String content; + if(chapterObjs.get(i-cache_chapter_range_min) == null) { + content = "章节获取失败了呢!客官"; + } + else content = chapterObjs.get(i-cache_chapter_range_min).getIchapter().getBody(); + // 为段首添加缩进 + content = "\u3000\u3000" + content; + content = content.replaceAll("\n", "\n\u3000\u3000"); + // 新建对应章节内容帧 + ReadPageFragment fragment = new ReadPageFragment(); + // 给帧传数据 + Bundle bundle = new Bundle(); + bundle.putString("title", title); + bundle.putString("content", content); + bundle.putInt("day_or_night_status", day_or_night_status); + bundle.putInt("textSize", textSize); + fragment.setArguments(bundle); + // 将新加的帧放入队列中 + fragmentList.add(fragment); + } + rxjava_update_page(2); + } + + + // 重载onConfigurationChanged函数处理横竖屏切换 + // 使得不必重新回调Activity整个生命周期 + @Override + public void onConfigurationChanged(Configuration newConfig) { + + if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { + //text_screen.append("\n 当前屏幕为横屏"); + System.out.println("当前屏幕为横屏"); + } else { + //text_screen.append("\n 当前屏幕为竖屏"); + System.out.println("当前屏幕为竖屏"); + } + if(is_vertical_screen == true) { + + System.out.println("数据库中是竖屏"); + } else { + System.out.println("数据库中是横屏"); + } + // 重新设置屏幕宽高 + get_screen_info(); + super.onConfigurationChanged(newConfig); + Log.e("TAG", "onConfigurationChanged"); + // setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); //设置横屏 + } + +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/RecomActivity.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/RecomActivity.java new file mode 100644 index 0000000..946de0a --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/RecomActivity.java @@ -0,0 +1,120 @@ +package com.example.Activity; + +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.Handler; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.List; + +import com.example.R; +import com.example.RecyclerView.MyRecyclerViewAdapter; +import com.example.RecyclerView.MyViewHolder; +import com.example.Object.BookObj; +import com.example.Object.RecomListObj; +import com.example.Service.BookService; + +public class RecomActivity extends AppCompatActivity { + + private List bookObjs; + + private RecyclerView recyclerView; + + private ImageView back; + + private Handler mHandler = new Handler(); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_recom); + + // 获取同类书籍 + Bundle bundle = getIntent().getExtras(); + bookObjs = ((RecomListObj)bundle.getSerializable("list")).getBookObjs(); + + // 获取相关控件 + back = findViewById(R.id.recom_back); + recyclerView = findViewById(R.id.recom_recyclerview); + + // 内容填充 + MyRecyclerViewAdapter adapter = new MyRecyclerViewAdapter(RecomActivity.this, R.layout.item_book, bookObjs) { + @Override + public void convert(MyViewHolder holder, BookObj bookObj) { + final ImageView imageView = holder.getView(R.id.item_book_cover); + TextView bookName = holder.getView(R.id.item_book_name); + TextView bookAuthor = holder.getView(R.id.item_book_author); + TextView bookType = holder.getView(R.id.item_book_type); + TextView bookIntro = holder.getView(R.id.item_book_intro); + bookName.setText(bookObj.getTitle()); + bookType.setText(bookObj.getMajorCate()); + bookAuthor.setText(bookObj.getAuthor()); + String intro = bookObj.getLongIntro(); + if (intro.length() > 50) intro = intro.substring(0, 50); + intro += "..."; + bookIntro.setText(intro); + + //通过网络获取书籍图标 + final String iconURL = BookService.StaticsUrl + bookObj.getCover(); + new Thread(new Runnable() { + @Override + public void run() { + try { + URL url = new URL(iconURL); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + connection.setConnectTimeout(10000); + if (connection.getResponseCode() == 200) { + InputStream inputStream = connection.getInputStream(); + final Bitmap bitmap = BitmapFactory.decodeStream(inputStream); + mHandler.post(new Runnable() { + @Override + public void run() { + imageView.setImageBitmap(bitmap); + } + }); + } + } catch (Exception e) { + System.err.println(e.getMessage()); + } + } + }).start(); + } + }; + adapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() { + @Override + public void onClick(int position) { + //跳转到书籍详情界面 + Intent intent = new Intent(RecomActivity.this, BookDetailActivity.class); + Bundle bundle = new Bundle(); + bundle.putSerializable("bookobj", bookObjs.get(position)); + intent.putExtras(bundle); + startActivity(intent); + } + + @Override + public void onLongClick(int position) { + + } + }); + recyclerView.setAdapter(adapter); + recyclerView.setLayoutManager(new LinearLayoutManager(RecomActivity.this)); + + back.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/SearchActivity.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/SearchActivity.java new file mode 100644 index 0000000..f503caf --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/SearchActivity.java @@ -0,0 +1,507 @@ +package com.example.Activity; + + +import android.content.Context; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.os.Handler; +import android.os.Looper; +import android.support.constraint.ConstraintLayout; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.SearchView; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.Toast; + + +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import com.example.R; +import com.example.RecyclerView.MyRecyclerViewAdapter; +import com.example.RecyclerView.MyViewHolder; +import com.example.Object.BookObj; +import com.example.Object.SearchResultObj; +import com.example.Service.BookService; + +import static com.example.DataBase.DatabaseControl.getInstance; +import static com.example.Service.BookService.getBookService; + +public class SearchActivity extends AppCompatActivity { + + private SearchView searchView; + private TextView cancelView; + private TextView text1; + private TextView text2; + private TextView text3; + private TextView text4; + private TextView text5; + private TextView text6; + private ImageView deleteView; + private ImageView freshView; + private ListView historyList; + private ListView fuzzyList; + private ConstraintLayout initialLayout; + private LinearLayout searchLayout; + private RecyclerView resultList; + private List histories; + private List tempFuzzy; + private List results; + private MyRecyclerViewAdapter recyclerViewAdapter; + private boolean isSubmit; + private boolean flag; + public Handler handler = new Handler(); + private String[] hotBooks = {"一品娇宠","剑来","逆天邪神","神医嫡女","官梯", + "最强狂兵","无敌剑域","一世倾城","天骄战纪","元尊", + "天行","修罗武神","永夜君王","家有王妃初长成","神级奶爸", + "神医毒妃","战神狂飙","逆天邪神","神医嫡女","江山美色", + "圣墟","极品透视学生","正道潜龙","斗罗大陆","雪中悍刀行", + "枭臣","将夜","校花的贴身高手","大刁民","偷香高手",}; + + + // 辅助函数:判断网络是否连接 + public boolean isNetWorkConnected(Context context) { + if (context != null) { + ConnectivityManager mConnectivityManager = (ConnectivityManager) context + .getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo(); + if (mNetworkInfo != null) { + return mNetworkInfo.isConnected(); + } + } + return false; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_search); + isSubmit = false; + flag = true; //用于同步问题的布尔变量 + //初始化列表 + histories = getInstance(getBaseContext()).getAllHistory(); + tempFuzzy = new ArrayList<>(); + results = new ArrayList<>(); + //获取控件 + freshView = findViewById(R.id.search_fresh_image); + cancelView = findViewById(R.id.search_cancel_text); + searchView = findViewById(R.id.search_search_searchView); + deleteView = findViewById(R.id.search_delete_image); + historyList = findViewById(R.id.search_history_list); + fuzzyList = findViewById(R.id.search_fuzzy_list); + resultList = findViewById(R.id.search_result_list); + initialLayout = findViewById(R.id.search_initial_layout); + searchLayout = findViewById(R.id.search_afters_layout); + text1 = findViewById(R.id.search_pop_text1); + text2 = findViewById(R.id.search_pop_text2); + text3 = findViewById(R.id.search_pop_text3); + text4 = findViewById(R.id.search_pop_text4); + text5 = findViewById(R.id.search_pop_text5); + text6 = findViewById(R.id.search_pop_text6); + + //设置历史列表adapter + final ArrayAdapter historyAdapter = new ArrayAdapter<>(this,R.layout.item_listview,histories); + historyList.setAdapter(historyAdapter); + //设置结果列表adapter + recyclerViewAdapter = new MyRecyclerViewAdapter(SearchActivity.this,R.layout.item_book,results) { + @Override + public void convert(MyViewHolder holder, final SearchResultObj.book book) { + TextView name = holder.getView(R.id.item_book_name); + name.setText(book.getTitle()); + TextView author = holder.getView(R.id.item_book_author); + author.setText(book.getAuthor()); + TextView major = holder.getView(R.id.item_book_type); + major.setText(book.getCat()); + TextView intro = holder.getView(R.id.item_book_intro); + String introString = book.getShortIntro(); + if (introString.length() > 50){ + introString = introString.substring(0,49)+"……"; + } + intro.setText(introString); + final ImageView cover = holder.getView(R.id.item_book_cover); + new Thread(new Runnable() { + @Override + public void run() { + try { + if (isNetWorkConnected(MainActivity.getContext())) { + URL url = new URL(BookService.StaticsUrl + book.getCover()); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + connection.setConnectTimeout(10000); + if (connection.getResponseCode() == 200) { + InputStream inputStream = connection.getInputStream(); + final Bitmap bitmap = BitmapFactory.decodeStream(inputStream); + handler.post(new Runnable() { + @Override + public void run() { + cover.setImageBitmap(bitmap); + } + }); + } + } + else{ + Looper.prepare(); + Toast.makeText(SearchActivity.this,"网络似乎出现了点问题",Toast.LENGTH_SHORT).show(); + Looper.loop(); + } + } catch (Exception e) { + System.err.println(e.getMessage()); + } + } + }).start(); + } + }; + recyclerViewAdapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() { + @Override + public void onClick(final int position) { + final Intent intent = new Intent(SearchActivity.this, BookDetailActivity.class); + final Bundle bundle = new Bundle(); + new Thread(new Runnable() { + @Override + public void run() { + if (isNetWorkConnected(MainActivity.getContext())) { + final BookObj t = getBookService().getBookById(results.get(position).get_id()); + if (t != null) + handler.post(new Runnable() { + @Override + public void run() { + bundle.putSerializable("bookobj", t); + intent.putExtras(bundle); + startActivity(intent); + } + }); + } + else { + Looper.prepare(); + Toast.makeText(SearchActivity.this,"网络似乎出现了点问题",Toast.LENGTH_SHORT).show(); + Looper.loop(); + } + } + }).start(); + } + + @Override + public void onLongClick(int position) { + + } + }); + resultList.setAdapter(recyclerViewAdapter); + resultList.setLayoutManager(new LinearLayoutManager(this)); + //设置模糊关联列表adapter + final ArrayAdapter fuzzyAdapter = new ArrayAdapter<>(this,R.layout.item_listview2,tempFuzzy); + fuzzyList.setAdapter(fuzzyAdapter); + + + //设置热门搜索函数 + text1.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + String s = text1.getText().toString(); + recordClick(s); + } + }); + text2.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + String s = text2.getText().toString(); + recordClick(s); + } + }); + text3.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + String s = text3.getText().toString(); + recordClick(s); + } + }); + text4.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + String s = text4.getText().toString(); + recordClick(s); + } + }); + text5.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + String s = text5.getText().toString(); + recordClick(s); + } + }); + text6.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + String s = text6.getText().toString(); + recordClick(s); + } + }); + + + //设置搜索函数 + searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(final String s) { + isSubmit = true; + //添加历史 + if (!histories.contains(s)){ + histories.add(s); + getInstance(getBaseContext()).addSearchHistory(s); + } + //设置可见 + searchLayout.setVisibility(View.VISIBLE); + fuzzyList.setVisibility(View.GONE); + resultList.setVisibility(View.VISIBLE); + //填充数据 + new Thread(new Runnable() { + @Override + public void run() { + if (isNetWorkConnected(MainActivity.getContext())) { + SearchResultObj tt = getBookService().getSearchResultObj(s, 0, 8); + results.clear(); + if (tt != null) { + List t = tt.getBookList(); + results.addAll(t); + handler.post(new Runnable() { + @Override + public void run() { + recyclerViewAdapter.notifyDataSetChanged(); + } + }); + } + else { + Looper.prepare(); + Toast.makeText(SearchActivity.this,"搜索不到相关内容",Toast.LENGTH_SHORT).show(); + Looper.loop(); + } + } + else { + Looper.prepare(); + Toast.makeText(SearchActivity.this,"网络似乎出现了点问题",Toast.LENGTH_SHORT).show(); + Looper.loop(); + } + } + }).start(); + recyclerViewAdapter.notifyDataSetChanged(); + return false; + } + + @Override + public boolean onQueryTextChange(final String s) { + //设置可见 + if (!isSubmit) { + if (s.equals("")) { + initialLayout.setVisibility(View.VISIBLE); + searchLayout.setVisibility(View.GONE); + } + else { + initialLayout.setVisibility(View.GONE); + searchLayout.setVisibility(View.VISIBLE); + fuzzyList.setVisibility(View.VISIBLE); + resultList.setVisibility(View.GONE); + } + } + else { + if (s.equals("")) { + fuzzyList.setVisibility(View.GONE); + resultList.setVisibility(View.VISIBLE); + } + else { + fuzzyList.setVisibility(View.VISIBLE); + resultList.setVisibility(View.GONE); + } + } + //填充数据 + if (!s.equals("")&&flag) { + new Thread(new Runnable() { + @Override + public void run() { + flag = false; + if (isNetWorkConnected(MainActivity.getContext())) { + SearchResultObj tt = getBookService().getSearchResultObj(s, 0, 8); + List t = new ArrayList<>(); + if (tt != null) { + List tss = tt.getBookList(); + int size = tss.size(); + for (int i = 0; i < size; i++) + t.add(tss.get(i).getTitle()); + } + tempFuzzy.clear(); + if (t.size() > 0) + tempFuzzy.addAll(t); + handler.post(new Runnable() { + @Override + public void run() { + fuzzyAdapter.notifyDataSetChanged(); + } + }); + } + else { + Looper.prepare(); + Toast.makeText(SearchActivity.this,"网络似乎出现了点问题",Toast.LENGTH_SHORT).show(); + Looper.loop(); + } + flag = true; + } + }).start(); + fuzzyAdapter.notifyDataSetChanged(); + } + return false; + } + }); + + //设置历史删除函数 + deleteView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + getInstance(getBaseContext()).deleteHistory(); + histories.clear(); + historyAdapter.notifyDataSetChanged(); + } + }); + + //设置历史点击函数 + historyList.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + final String s = histories.get(position); + recordClick(s); + } + }); + + //模糊搜索点击函数 + fuzzyList.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + final String s = tempFuzzy.get(position); + isSubmit = true; + //添加历史 + if (!histories.contains(s)){ + histories.add(s); + getInstance(getBaseContext()).addSearchHistory(s); + } + //设置可见 + initialLayout.setVisibility(View.GONE); + searchLayout.setVisibility(View.VISIBLE); + fuzzyList.setVisibility(View.GONE); + resultList.setVisibility(View.VISIBLE); + //填充数据 + new Thread(new Runnable() { + @Override + public void run() { + if (isNetWorkConnected(MainActivity.getContext())) { + SearchResultObj tt = getBookService().getSearchResultObj(s, 0, 8); + List t = tt.getBookList(); + results.clear(); + if (t != null) + results.addAll(t); + handler.post(new Runnable() { + @Override + public void run() { + recyclerViewAdapter.notifyDataSetChanged(); + } + }); + } + else { + Looper.prepare(); + Toast.makeText(SearchActivity.this,"网络似乎出现了点问题",Toast.LENGTH_SHORT).show(); + Looper.loop(); + } + } + }).start(); + recyclerViewAdapter.notifyDataSetChanged(); + searchView.setQuery(s,true); + } + }); + //取消按钮点击事件 + cancelView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + + //更换热门图书函数 + freshView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + freshPopBook(); + } + }); + } + public void recordClick(final String s) { + isSubmit = true; + //设置可见 + initialLayout.setVisibility(View.GONE); + searchLayout.setVisibility(View.VISIBLE); + fuzzyList.setVisibility(View.GONE); + resultList.setVisibility(View.VISIBLE); + //添加历史 + if (!histories.contains(s)){ + histories.add(s); + getInstance(getBaseContext()).addSearchHistory(s); + } + //填充数据 + new Thread(new Runnable() { + @Override + public void run() { + if (isNetWorkConnected(MainActivity.getContext())) { + SearchResultObj tt = getBookService().getSearchResultObj(s, 0, 8); + results.clear(); + if (tt != null) { + List t = tt.getBookList(); + results.addAll(t); + handler.post(new Runnable() { + @Override + public void run() { + recyclerViewAdapter.notifyDataSetChanged(); + } + }); + } + else { + Looper.prepare(); + Toast.makeText(SearchActivity.this,"搜索不到相关内容",Toast.LENGTH_SHORT).show(); + Looper.loop(); + } + } + else { + Looper.prepare(); + Toast.makeText(SearchActivity.this,"网络似乎出现了点问题",Toast.LENGTH_SHORT).show(); + Looper.loop(); + } + } + }).start(); + recyclerViewAdapter.notifyDataSetChanged(); + searchView.setQuery(s,true); + } + + public void freshPopBook() { + Random ra =new Random(); + int t = ra.nextInt(29); + text1.setText(hotBooks[t]); + t = (t+1)%30; + text2.setText(hotBooks[t]); + t = (t+1)%30; + text3.setText(hotBooks[t]); + t = (t+1)%30; + text4.setText(hotBooks[t]); + t = (t+1)%30; + text5.setText(hotBooks[t]); + t = (t+1)%30; + text6.setText(hotBooks[t]); + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/text.puml b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/text.puml new file mode 100644 index 0000000..ac2c2d3 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Activity/text.puml @@ -0,0 +1,11 @@ +@startuml +'https://plantuml.com/sequence-diagram + +autonumber + +Alice -> Bob: Authentication Request +Bob --> Alice: Authentication Response + +Alice -> Bob: Another authentication Request +Alice <-- Bob: another authentication Response +@enduml \ No newline at end of file diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/DataBase/DatabaseControl.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/DataBase/DatabaseControl.java new file mode 100644 index 0000000..81173d6 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/DataBase/DatabaseControl.java @@ -0,0 +1,279 @@ +package com.example.DataBase; + +import android.content.ContentValues; +import android.content.Context; +import android.content.res.Resources; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.List; + +import com.example.Activity.MainActivity; +import com.example.R; +import com.example.Object.ShelfBookObj; +import com.example.Object.UserStatusObj; + +public class DatabaseControl extends SQLiteOpenHelper { + private static final String DB_NAME= "readerBase.db"; + private static final String TABLE_NAME1 = "shelfbook_table"; + private static final String TABLE_NAME2 = "categorybook_table"; + private static final String TABLE_NAME3 = "status_table"; + private static final int DB_VERSION = 1; + + + private static DatabaseControl instance = null; + public static DatabaseControl getInstance(Context context) { + if (instance == null) { + instance = new DatabaseControl(context); + } + return instance; + } + + //byte[] 转 Bitmap + public Bitmap bytesToBitmap(byte[] b) { + if (b.length != 0) { + return BitmapFactory.decodeByteArray(b, 0, b.length); + } else { + return null; + } + } + //Bitmap → byte[] + public byte[] bitmapToBytes(Bitmap bm) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + bm.compress(Bitmap.CompressFormat.PNG, 100, baos); + return baos.toByteArray(); + } + //这个list用于保存所有书架书籍信息 + private List allShelfBook = null; + public List getAllShelfBook() { + return getAllShelfBookFromDB(); + } + + //从数据库中查询所有书架书目 + private List getAllShelfBookFromDB() { + SQLiteDatabase db = getWritableDatabase(); + Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_NAME1, null); + List list = new ArrayList<>(); + while (cursor.moveToNext()) { + String id = cursor.getString(cursor.getColumnIndex("_id")); + String major = cursor.getString(cursor.getColumnIndex("major")); + String author = cursor.getString(cursor.getColumnIndex("author")); + int readChapter = cursor.getInt(cursor.getColumnIndex("progress")); + int type = cursor.getInt(cursor.getColumnIndex("type")); + String name = cursor.getString(cursor.getColumnIndex("name")); + String address = cursor.getString(cursor.getColumnIndex("address")); + String description = cursor.getString(cursor.getColumnIndex("description")); + byte[] imageByte = cursor.getBlob(cursor.getColumnIndex("image")); + list.add(new ShelfBookObj(id,name, bytesToBitmap(imageByte),"",readChapter,address,type,description,author,major)); + } + cursor.close(); + db.close(); + return list; + } + //根据book id删除数据 + public void deleteShelfBook(String id) { + SQLiteDatabase db = getWritableDatabase(); + db.delete(TABLE_NAME1, "_id = ?", new String[] { id }); + } + + public void addShelfBook(ShelfBookObj book) { + SQLiteDatabase db = getWritableDatabase(); + ContentValues values = new ContentValues(); + //开始添加第一条数据_id TEXT PRIMARY KEY, name TEXT, type INTEGER ,progress INTEGER, address TEXT,image BLOB, description TEXT + values.put("name",book.getName()); + values.put("description",book.getDescription()); + values.put("type",book.getType()); + values.put("_id",book.getBookId()); + values.put("author",book.getAuthor()); + values.put("major",book.getMajor()); + values.put("address",book.getAddress()); + values.put("progress",book.getReadChapter()); + values.put("image",bitmapToBytes(book.getIcon())); + db.insert(TABLE_NAME1,null,values); + db.close(); + } + + //获取多少条搜索历史 + public int getHistoryCount() { + SQLiteDatabase db = getWritableDatabase(); + Cursor cursor = db.query(TABLE_NAME2, null, null, null, null, null, null); + return cursor.getCount(); + } + + //更新阅读进度 + public void updateProgress(int progress, String id) { + SQLiteDatabase db = getWritableDatabase(); + ContentValues value = new ContentValues(); + value.put("progress", progress); + db.update(TABLE_NAME1, value, "_id=?", new String[] { id }); + db.close(); + } + + public List getAllHistory() { + SQLiteDatabase db = getWritableDatabase(); + Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_NAME2, null); + List list = new ArrayList<>(); + while (cursor.moveToNext()) { + String content = cursor.getString(cursor.getColumnIndex("content")); + list.add(content); + } + cursor.close(); + db.close(); + return list; + } + + //搜索历史添加(不超过10个) + public void addSearchHistory(String s) { + SQLiteDatabase db = getWritableDatabase(); + if (getHistoryCount() > 9){ + Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_NAME2, null); + cursor.moveToFirst(); + String name = cursor.getString(cursor.getColumnIndex("content")); + db.delete(TABLE_NAME2, "content=?", new String[] {name}); + } + ContentValues cv = new ContentValues(); + cv.put("content", s); + db.insert(TABLE_NAME2, null, cv); + db.close(); + } + + public boolean judgeBookExist(String id) { + SQLiteDatabase db = getWritableDatabase(); + Cursor cursor = db.query(TABLE_NAME1, null, "_id=?", new String[] { id }, null, null, null); + return cursor.moveToFirst(); + } + + //删除搜索历史 + public void deleteHistory() { + SQLiteDatabase db = getWritableDatabase(); + db.execSQL("DELETE FROM " + TABLE_NAME2); + } + + // 更新用户阅读器习惯的状态 + public void updateStatus(int user_id, int hor_or_ver_screen) { + SQLiteDatabase db = getWritableDatabase(); + ContentValues value = new ContentValues(); + value.put("hor_or_ver_screen", hor_or_ver_screen); + db.update(TABLE_NAME3, value, "user_id=?", new String[] { Integer.toString(user_id)}); + db.close(); + } + + // 获取用户阅读器习惯的横竖屏 + public int get_Hor_Or_Ver_Screen_Status(int user_id) { + SQLiteDatabase db = getWritableDatabase(); + String id = Integer.toString(user_id); + String sql = String.format("SELECT * FROM " + TABLE_NAME3 + " where user_id='%s'" , id); + Cursor cursor = db.rawQuery(sql, null); + int res = 1; + while (cursor.moveToNext()) { + res = cursor.getInt(cursor.getColumnIndex("hor_or_ver_screen")); + return res; + } + cursor.close(); + db.close(); + return res; + } + + // 更新用户阅读器习惯的状态 + public void updateStatus(int user_id, UserStatusObj u) { + SQLiteDatabase db = getWritableDatabase(); + ContentValues value = new ContentValues(); + value.put("hor_or_ver_screen", u.getHor_or_ver_screen()); // 1表示竖屏,0表示横屏 + value.put("day_or_night_status", u.getDay_or_night_status()); // 0表示日间,1表示夜间 + value.put("textSize", u.getTextSize()); // 字体大小 + db.update(TABLE_NAME3, value, "user_id=?", new String[] { Integer.toString(user_id)}); + db.close(); + } + + public UserStatusObj get_User_Status_Obj(int user_id) { + SQLiteDatabase db = getWritableDatabase(); + String id = Integer.toString(user_id); + String sql = String.format("SELECT * FROM " + TABLE_NAME3 + " where user_id='%s'" , id); + Cursor cursor = db.rawQuery(sql, null); + UserStatusObj res = null; + while (cursor.moveToNext()) { + int hor_or_ver_screen = cursor.getInt(cursor.getColumnIndex("hor_or_ver_screen")); + int day_or_night_status = cursor.getInt(cursor.getColumnIndex("day_or_night_status")); + int textSize = cursor.getInt(cursor.getColumnIndex("textSize")); + res = new UserStatusObj(user_id, hor_or_ver_screen, day_or_night_status, textSize); + return res; + } + cursor.close(); + db.close(); + return res; + } + + + + + public DatabaseControl(Context context) { + super(context, DB_NAME, null, DB_VERSION ); + } + + @Override//创建数据库 + public void onCreate(SQLiteDatabase sqLiteDatabase) { + //书架上的书,含书名、类型(本地还是网络)、阅读进度、资源地址、书的封面 + String CREATE_TABLE1 = "CREATE TABLE if not exists " + + TABLE_NAME1 + + " (_id TEXT PRIMARY KEY, name TEXT, type INTEGER ,progress INTEGER, address TEXT,image BLOB, description TEXT, author TEXT, major TEXT)"; + //搜索历史 + String CREATE_TABLE2 = "CREATE TABLE if not exists " + + TABLE_NAME2 + + " (_id INTEGER PRIMARY KEY, content TEXT)"; + // 阅读器状态保存 + String CREATE_TABLE3 = "CREATE TABLE if not exists " + + TABLE_NAME3 + + " (user_id INTEGER PRIMARY KEY, hor_or_ver_screen INTEGER, day_or_night_status INTEGER, textSize INTEGER)"; + sqLiteDatabase.execSQL(CREATE_TABLE1); + sqLiteDatabase.execSQL(CREATE_TABLE2); + sqLiteDatabase.execSQL(CREATE_TABLE3); + + Resources res = MainActivity.getContext().getResources(); + Bitmap bitmap = BitmapFactory.decodeResource(res, R.mipmap.bookcover); + ContentValues values = new ContentValues(); + ShelfBookObj book = new ShelfBookObj("5816b415b06d1d32157790b1","圣墟",bitmap,"",0,"default",0,"在破败中崛起,在寂灭中复苏。沧海成尘,雷电枯竭,那一缕幽雾又一次临近大地,世间的枷锁被打开了,一个全新的世界就此揭开神秘的一角……","辰东","玄幻"); + //开始添加第一条数据_id TEXT PRIMARY KEY, name TEXT, type INTEGER ,progress INTEGER, address TEXT,image BLOB, description TEXT + values.put("name",book.getName()); + values.put("description",book.getDescription()); + values.put("type",book.getType()); + values.put("_id",book.getBookId()); + values.put("author",book.getAuthor()); + values.put("major",book.getMajor()); + values.put("address",book.getAddress()); + values.put("progress",book.getReadChapter()); + values.put("image",bitmapToBytes(book.getIcon())); + sqLiteDatabase.insert(TABLE_NAME1,null,values); + values.clear(); + bitmap = BitmapFactory.decodeResource(res, R.mipmap.bookcover2); + book = new ShelfBookObj("59ba0dbb017336e411085a4e","元尊",bitmap,"",0,"default",0,"《斗破苍穹》《武动乾坤》之后全新力作,朝堂太子踏上了荆棘重生之路…","天蚕土豆","玄幻"); + values.put("name",book.getName()); + values.put("description",book.getDescription()); + values.put("type",book.getType()); + values.put("_id",book.getBookId()); + values.put("author",book.getAuthor()); + values.put("major",book.getMajor()); + values.put("address",book.getAddress()); + values.put("progress",book.getReadChapter()); + values.put("image",bitmapToBytes(book.getIcon())); + sqLiteDatabase.insert(TABLE_NAME1,null,values); + + // 往阅读器状态表格中保存一条初始阅读器状态 + UserStatusObj u = new UserStatusObj(0,1,0,18); + values.clear(); + values.put("user_id", 0); // 用户id为0,表示默认状态 + values.put("hor_or_ver_screen", u.getHor_or_ver_screen()); // 1表示竖屏,0表示横屏 + values.put("day_or_night_status", u.getDay_or_night_status()); // 0表示日间,1表示夜间 + values.put("textSize", u.getTextSize()); // 字体大小 + sqLiteDatabase.insert(TABLE_NAME3,null,values); + } + + @Override + public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int ii) { + + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/BookShelfFragment.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/BookShelfFragment.java new file mode 100644 index 0000000..5a04c20 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/BookShelfFragment.java @@ -0,0 +1,148 @@ +package com.example.Fragment; + +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.Fragment; +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 android.widget.ImageView; +import android.widget.TextView; + +import java.util.List; + +import com.example.R; +import com.example.Activity.ReadPageActivity; +import com.example.DataBase.DatabaseControl; +import com.example.RecyclerView.MyRecyclerViewAdapter; +import com.example.RecyclerView.MyViewHolder; +import com.example.Object.ShelfBookObj; + +// 书架界面 +public class BookShelfFragment extends Fragment { + // Fragment的视图 + View view; + + // Fragment内的RecyclerView + RecyclerView recyclerView; // recyclerview + List myBooks; // recyclerview中的书籍数据 + MyRecyclerViewAdapter adapter; // recyclerview 的 adapter + + // book-item 项的各个控件 + private ImageView book_cover_imageview_control; + private TextView book_name_textview_control; + private TextView book_author_textview_control; + private TextView book_type_textview_control; + private TextView book_intro_textview_control; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + // 获取 Fragment 的视图 + view = inflater.inflate(R.layout.fragment_book_shelf, null); + + // 获取书籍数据 + getMyBooks(); + + // 设置页面的 RecyclerView + setRecyclerView(); + + // 返回视图 + return view; + } + + @Override + public void onResume() { + getMyBooks(); + setRecyclerView(); + //Toast.makeText(getActivity(), "进入Fragment" + " | " + myBooks.size(), Toast.LENGTH_SHORT).show(); +// System.out.println("onResume: " + myBooks.get(0).getReadChapter()); + //System.out.println("横竖屏状态:MainActivity-BookShelfFragment: " + DatabaseControl.getInstance(getActivity()).get_Hor_Or_Ver_Screen_Status(0)); + super.onResume(); + } + + // 获取书籍数据 + private void getMyBooks() { + //Bitmap bitmap = ((BitmapDrawable)getResources().getDrawable(R.mipmap.bookcover)).getBitmap(); + /*ShelfBookObj test = new ShelfBookObj("5816b415b06d1d32157790b1", "圣墟", bitmap, 0, "testAddress", 0, "testDescription"); + DatabaseControl.getInstance(getActivity()).addShelfBook(test);*/ + myBooks = DatabaseControl.getInstance(getActivity()).getAllShelfBook(); + //System.out.println("getBookSize: " + myBooks.size()); + } + + // 设置页面的 RecyclerView + private void setRecyclerView() { + // 获取页面的 RecyclerView 控件 + recyclerView = view.findViewById(R.id.fragment_book_shelf_recyclerview); + + // 设置 RecyclerView 的布局方式 + recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + + // 设置 RecyclerAdapter + adapter = new MyRecyclerViewAdapter(getActivity(), R.layout.item_book, myBooks) { + @Override + public void convert(MyViewHolder holder, ShelfBookObj shelfBookObj) { + // 书名 + TextView bookName = holder.getView(R.id.item_book_name); + bookName.setText(shelfBookObj.getName()); + // 封面 + ImageView imageView = holder.getView(R.id.item_book_cover); + imageView.setImageBitmap(shelfBookObj.getIcon()); + // 作者 + TextView author = holder.getView(R.id.item_book_author); + author.setText(shelfBookObj.getAuthor()); + // 类型 + TextView major = holder.getView(R.id.item_book_type); + major.setText(shelfBookObj.getMajor()); + // 简介 + TextView intro = holder.getView(R.id.item_book_intro); + String str = shelfBookObj.getDescription(); + if (str.length() > 50) str = str.substring(0, 50); + str += "..."; + intro.setText(str); + } + }; + adapter.refresh(myBooks); + adapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() { + @Override + public void onClick(int position) { + Intent intent = new Intent(getActivity(), ReadPageActivity.class); + Bundle bundle = new Bundle(); + bundle.putString("bookid", myBooks.get(position).getBookId()); + bundle.putInt("currentChapter", myBooks.get(position).getReadChapter()); + bundle.putString("bookname", myBooks.get(position).getName()); + System.out.println("传进去当前阅读章节数为:" + myBooks.get(position).getReadChapter()); + intent.putExtras(bundle); + startActivity(intent); + } + + @Override + public void onLongClick(final int position) { + // 长按弹出对话框 + AlertDialog.Builder dialog = new AlertDialog.Builder(getActivity()); + dialog.setMessage("确定要从书架移除" + myBooks.get(position).getName() + "吗?"); + dialog.setNegativeButton("NO", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + } + }); + dialog.setPositiveButton("YES", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + DatabaseControl.getInstance(getActivity()).deleteShelfBook(myBooks.get(position).getBookId()); + getMyBooks(); + setRecyclerView(); + } + }); + dialog.show(); + } + }); + recyclerView.setAdapter(adapter); + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/CategoryFragment.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/CategoryFragment.java new file mode 100644 index 0000000..e312b4f --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/CategoryFragment.java @@ -0,0 +1,96 @@ +package com.example.Fragment; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.view.ViewPager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RadioButton; +import android.widget.RadioGroup; + +import java.util.ArrayList; +import java.util.List; + +import com.example.R; + +// 分类的界面 +public class CategoryFragment extends Fragment { + private RadioGroup RG; + private RadioButton maleRB; + private RadioButton femaleRB; + private ViewPager viewPager; + private List fragmentList = new ArrayList<>(); + private TabFragmentPagerAdapter fragmentPagerAdapter; + + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_category, null); + //初始化控件 + RG = view.findViewById(R.id.category_RG); + viewPager = view.findViewById(R.id.category_viewPager); + maleRB = view.findViewById(R.id.category_RB_male); + femaleRB = view.findViewById(R.id.category_RB_female); + + //初始化Fragment + fragmentList.clear(); + MaleInCategoryFragment maleFragment = new MaleInCategoryFragment(); + MaleInCategoryFragment femaleFragment = new MaleInCategoryFragment(); + Bundle bundle1 = new Bundle(); + bundle1.putBoolean("isMale", true); + maleFragment.setArguments(bundle1); + fragmentList.add(maleFragment); + Bundle bundle2 = new Bundle(); + bundle2.putBoolean("isMale", false); + femaleFragment.setArguments(bundle2); + fragmentList.add(femaleFragment); + + viewPager.setOnPageChangeListener(new MyPagerChangeListener()); + fragmentPagerAdapter = new TabFragmentPagerAdapter(getChildFragmentManager(), fragmentList); + viewPager.setAdapter(fragmentPagerAdapter); + viewPager.setCurrentItem(0); + viewPager.setOffscreenPageLimit(1); + + RG.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(RadioGroup group, int checkedId) { + switch (checkedId) { + case R.id.category_RB_male: + viewPager.setCurrentItem(0); + break; + case R.id.category_RB_female: + viewPager.setCurrentItem(1); + break; + } + } + }); + + return view; + } + + //设置一个ViewPager的监听事件,左右滑动ViewPager时进行处理 + public class MyPagerChangeListener implements ViewPager.OnPageChangeListener { + @Override + public void onPageScrollStateChanged(int arg0) { + } + + @Override + public void onPageScrolled(int arg0, float arg1, int arg2) { + } + + @Override + public void onPageSelected(int arg0) { + switch (arg0) { + case 0: + maleRB.setChecked(true); + break; + case 1: + femaleRB.setChecked(true); + break; + } + } + } + +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/DetailCategoryFragment.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/DetailCategoryFragment.java new file mode 100644 index 0000000..b15d5f3 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/DetailCategoryFragment.java @@ -0,0 +1,320 @@ +package com.example.Fragment; + +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ProgressBar; +import android.widget.Toast; + +import java.util.ArrayList; +import java.util.List; + +import com.example.Activity.BookDetailActivity; +import com.example.R; +import com.example.RecyclerView.CateRecyclerViewAdapter; +import com.example.Object.AllRankingObj; +import com.example.Object.BookObj; +import com.example.Object.CategoryObj; +import com.example.Object.SingleRankingObj; +import com.example.Service.BookService; + +// 具体分类和榜单的Fragment +public class DetailCategoryFragment extends Fragment { + private boolean isRanking; //排行榜/具体分类 + private boolean isMale; //男生/女生 + private String title; //榜单名/类型名 + private String type; //具体榜单/具体类型 + + private RecyclerView recyclerView; + private ProgressBar progressBar; + private SwipeRefreshLayout swipeRefreshLayout; + private List bookObjList = new ArrayList<>(); + private CateRecyclerViewAdapter recyclerViewAdapter; + + //具体榜单的id + private String rankingid = ""; + + private int total; //书籍总数 + private int lastVisibleItem = 0; + private final int PAGE_COUNT = 10; + + Handler handler = new Handler(); + BookService bookService = BookService.getBookService(); + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + this.isRanking = getArguments().getBoolean("isRanking"); + this.isMale = getArguments().getBoolean("isMale"); + if (isRanking == false) { + Log.d("type in args:", getArguments().getString("type")); + switch (getArguments().getString("type")) { + case "热门": + this.type = "hot"; + break; + case "新书": + this.type = "new"; + break; + case "好评": + this.type = "reputation"; + break; + case "完结": + this.type = "over"; + break; + } + } + else this.type = getArguments().getString("type"); + this.title = getArguments().getString("title"); + + initBookList(); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_detail_category, null); + + progressBar = view.findViewById(R.id.detail_category_progressBar); + swipeRefreshLayout = view.findViewById(R.id.detail_category_swipeRefresh); + + //设置RecyclerView + recyclerView = view.findViewById(R.id.detail_category_recyclerView); + recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + recyclerViewAdapter = new CateRecyclerViewAdapter(getBookList(0, PAGE_COUNT), getActivity(), getBookList(0, PAGE_COUNT).size() > 0 ? true : false, isRanking); + recyclerViewAdapter.setOnItemClickListener(new CateRecyclerViewAdapter.OnItemClickListener() { + @Override + public void onClick(int position) { + //跳转到书籍详情界面 + Intent intent = new Intent(getActivity(), BookDetailActivity.class); + Bundle bundle = new Bundle(); + bundle.putSerializable("bookobj", bookObjList.get(position)); + intent.putExtras(bundle); + startActivity(intent); + } + }); + recyclerView.setAdapter(recyclerViewAdapter); + + //设置下拉显示的动画颜色 + swipeRefreshLayout.setColorSchemeColors(Color.RED, Color.BLUE); + //下拉刷新的回调事件 + swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + //数据刷新 + initBookList(); + } + }); + + //设置滑动监听器 + recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + // 在newState为滑到底部时 + if (newState == RecyclerView.SCROLL_STATE_IDLE) { + // 如果没有隐藏footView,那么最后一个条目的位置就比我们的getItemCount少1 + if (recyclerViewAdapter.isFadeTips() == false && lastVisibleItem + 1 == recyclerViewAdapter.getItemCount()) { + handler.postDelayed(new Runnable() { + @Override + public void run() { + // 然后调用updateRecyclerview方法更新RecyclerView + updateRecyclerView(recyclerViewAdapter.getLastPosition(), recyclerViewAdapter.getLastPosition() + PAGE_COUNT); + } + }, 500); + } + + // 如果隐藏了提示条,我们又上拉加载时,那么最后一个条目就要比getItemCount要少2 + if (recyclerViewAdapter.isFadeTips() == true && lastVisibleItem + 2 == recyclerViewAdapter.getItemCount()) { + handler.postDelayed(new Runnable() { + @Override + public void run() { + // 然后调用updateRecyclerview方法更新RecyclerView + updateRecyclerView(recyclerViewAdapter.getLastPosition(), recyclerViewAdapter.getLastPosition() + PAGE_COUNT); + } + }, 500); + } + } + } + + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + // 在滑动完成后,拿到最后一个可见的item的位置 + LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); + lastVisibleItem = layoutManager.findLastVisibleItemPosition(); + } + }); + + return view; + } + + void initBookList() { + bookObjList.clear(); + //检查网络连接 + ConnectivityManager connect = (ConnectivityManager)getActivity().getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo info = connect.getActiveNetworkInfo(); + if (info == null || !info.isAvailable()) { + Toast.makeText(getActivity(), "网络连接状况:未连接", Toast.LENGTH_LONG).show(); + return; + } + if (isRanking) getRankingBookList(); + else getCateBookList(); + } + + //获取排行榜书单 + void getRankingBookList() { + new Thread(new Runnable() { + @Override + public void run() { + AllRankingObj allRankingObj = bookService.getAllRankingObj(); + if (allRankingObj == null || allRankingObj.isOk() == false) { + Looper.prepare(); + Toast.makeText(getContext(), "获取数据失败", Toast.LENGTH_LONG).show(); + Looper.loop(); + Log.d("error", "获取全部排行榜失败"); + return; + } + //获取具体榜单的id + if (isMale) { //男生 + for (AllRankingObj.subClass subClass : allRankingObj.getMaleList()) { + if (subClass.getShortTitle().equals(title)) { + if (title.equals("热搜榜")) rankingid = subClass.getId(); + else { + if (type.equals("周榜")) rankingid = subClass.getId(); + else if (type.equals("月榜")) rankingid = subClass.getMonthRank(); + else if (type.equals("总榜")) rankingid = subClass.getTotalRank(); + else { + System.exit(1); + Log.d("error", "榜单名错误!"); + } + } + break; + } + } + } + else { //女生 + for (AllRankingObj.subClass subClass : allRankingObj.getFemaleList()) { + if (subClass.getShortTitle().equals(title)) { + if (title.equals("热搜榜")) rankingid = subClass.getId(); + else { + if (type.equals("周榜")) rankingid = subClass.getId(); + else if (type.equals("月榜")) rankingid = subClass.getMonthRank(); + else if (type.equals("总榜")) rankingid = subClass.getTotalRank(); + else { + System.exit(1); + Log.d("error", "榜单名不符!"); + } + } + break; + } + } + } + //得到id后再获取具体榜单的书籍信息 + new Thread(new Runnable() { + @Override + public void run() { + SingleRankingObj singleRankingObj = bookService.getSingleRankingObj(rankingid); + if (singleRankingObj == null || singleRankingObj.isOk() == false) { + Looper.prepare(); + Toast.makeText(getContext(), "获取失败", Toast.LENGTH_LONG).show(); + Looper.loop(); + Log.d("error", "获取单一排行榜失败"); + return; + } + List objList = singleRankingObj.getRanking().getBookList(); + total = singleRankingObj.getRanking().getTotal(); + for (int i = 0; i < objList.size(); ++i) { + BookObj bookObj = objList.get(i); + String intro = bookObj.getShortIntro(); + if (intro.length() > 50) intro = intro.substring(0, 50); + intro += "..."; + bookObj.setShortIntro(intro); + bookObjList.add(bookObj); + } + handler.post(new Runnable() { + @Override + public void run() { + updateRecyclerView(0, PAGE_COUNT); + progressBar.setVisibility(View.GONE); + //数据加载完毕时取消动画 + swipeRefreshLayout.setRefreshing(false); + Toast.makeText(getActivity(), "数据刷新完成", Toast.LENGTH_SHORT).show(); + } + }); + } + }).start(); + } + }).start(); + } + + //获取具体分类书单 + void getCateBookList() { + new Thread(new Runnable() { + @Override + public void run() { + String gender = (isMale == true) ? "male" : "female"; + Log.d("type:", "" + type); + final CategoryObj categoryObj = bookService.getBooksByCategoty(type, title, 0, 30000, gender); + if (categoryObj == null || categoryObj.isOk() == false) { + Looper.prepare(); + Toast.makeText(getContext(), "获取数据失败", Toast.LENGTH_LONG).show(); + Looper.loop(); + Log.d("error", "获取主题书单列表失败"); + return; + } + total = categoryObj.getTotal(); + for (BookObj bookObj : categoryObj.getBooks()) { + if (bookObj.getShortIntro().length() > 50){ + String intro = bookObj.getShortIntro(); + intro = intro.substring(0, 50); + intro += "..."; + bookObj.setShortIntro(intro); + } + bookObjList.add(bookObj); + } + handler.post(new Runnable() { + @Override + public void run() { + //Toast.makeText(getActivity(), "" + bookObjList.size() + " | " + total + " | " + categoryObj.getBooks().size(), Toast.LENGTH_SHORT).show(); + updateRecyclerView(0, PAGE_COUNT); + progressBar.setVisibility(View.GONE); + //数据加载完毕时取消动画 + swipeRefreshLayout.setRefreshing(false); + Toast.makeText(getActivity(), "数据刷新完成", Toast.LENGTH_SHORT).show(); + } + }); + } + }).start(); + } + + private void updateRecyclerView(int fromIndex, int toIndex) { + List newDatas = getBookList(fromIndex, toIndex); + if (newDatas.size() > 0) { + recyclerViewAdapter.updateList(newDatas, true); + } else { + recyclerViewAdapter.updateList(null, false); + } + } + + List getBookList(int from, int to) { + List newList = new ArrayList<>(); + for (int i = from; i < to && i < bookObjList.size(); ++i) { + newList.add(bookObjList.get(i)); + } + return newList; + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/MaleInCategoryFragment.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/MaleInCategoryFragment.java new file mode 100644 index 0000000..4e7e087 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/MaleInCategoryFragment.java @@ -0,0 +1,272 @@ +package com.example.Fragment; + +import android.content.Context; +import android.content.Intent; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.os.Bundle; +import android.os.Looper; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import android.widget.Toast; + +import java.util.ArrayList; +import java.util.List; + +import com.example.Activity.CategoryActivity; +import com.example.R; +import com.example.RecyclerView.CategoryRecyObj; +import com.example.RecyclerView.MyRecyclerViewAdapter; +import com.example.RecyclerView.MyViewHolder; +import com.example.Object.ClassificationObj1; +import com.example.Object.ClassificationObj2; +import com.example.Service.BookService; + +import static android.app.ProgressDialog.show; + +// 分类(男生/女生)界面 +public class MaleInCategoryFragment extends Fragment { + // Fragment 的 视图 + View view; + + // Fragment内的RecyclerView + RecyclerView recyclerView; // recyclerview + List myCategories; // recyclerview中的书籍数据 + MyRecyclerViewAdapter adapter; // recyclerview 的 adapter + + // 判断是女性分类还是男性分类 + boolean isMale = true; + + // 分类数据OBJ + private ClassificationObj1 classificationObj1; + private ClassificationObj2 classificationObj2; + + // bookservice 类 (用单例模式获取) + private BookService bookService; + + // 一级分类(写死) + public static String[] maleCategoriesName = {"玄幻", "奇幻", "武侠", "仙侠", "都市", "职场", "历史", "军事", "游戏", "竞技", "科幻", "灵异", "同人", "轻小说"}; + public static String[] femaleCategoriesName = {"古代言情", "现代言情", "青春校园", "纯爱", "玄幻奇幻", "武侠仙侠", "科幻", "游戏竞技", "悬疑灵异", "同人", "女尊", "莉莉"}; + String[] maleCategoriesBookCount = {"(56万本)", "(6.3万本)", "(4.8万本)", "(15万本)", "(38万本)", "(1.8万本)", "(7.9万本)", "(1.6万本)", "(8.9万本)", "(6648本)", "(13万本)", "(5.3万本)", "(4.6万本)", "(9761本)"}; + String[] femaleCategoriesBookCount = {"(57万本)", "(71万本)", "(15万本)", "(13万本)", "(15万本)", "(7.8万本)", "(1.8万本)", "(6553本)", "(2.0万本)", "(12万本)", "(2.2万本)", "(2.6万本)"}; + + + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // 获取传给Fragment的参数 + Bundle bundle = getArguments(); + this.isMale = bundle.getBoolean("isMale"); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + // 获取 Fragment 视图 + view = inflater.inflate(R.layout.fragment_male_in_category, null); + + // 获取分类数据 + getMyCategories(); + + // 设置 RecyclerView + setRecyclerView(); + + // Inflate the layout for this fragment + return view; + } + + + + + // 设置 RecyclerView + private void setRecyclerView() { + // 获取页面的 RecyclerView 控件 + recyclerView = view.findViewById(R.id.fragment_male_in_category_recyclerview); + + // 设置 RecyclerView 的布局方式 + recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 2)); + + // 设置 Adapter 配置 + adapter = new MyRecyclerViewAdapter(getActivity(), R.layout.item_category, myCategories) { + @Override + public void convert(MyViewHolder holder, CategoryRecyObj categoryRecyObj) { + TextView categoryName = holder.getView(R.id.item_category_name); + categoryName.setText(categoryRecyObj.getCategoryName()); + TextView categoryBookCount = holder.getView(R.id.item_category_count); + categoryBookCount.setText(categoryRecyObj.getBookCount()); + } + }; + + // 每个主类按钮的点击响应处理 + adapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() { + @Override + public void onClick(int position) { + //跳转具体分类界面 + Intent intent = new Intent(getActivity(), CategoryActivity.class); + Bundle bundle = new Bundle(); + bundle.putBoolean("isRanking", false); + bundle.putBoolean("isMale", isMale); + if (isMale) bundle.putString("title", maleCategoriesName[position]); + else bundle.putString("title", femaleCategoriesName[position]); + intent.putExtras(bundle); + startActivity(intent); + + /*System.out.println("onClick"); + + // 分类信息尚未获取,调用BookService去获取 + if(classificationObj2 == null) { + boolean isNetWorkConnected = isNetWorkConnected(getActivity()); + // 有网络 + if(isNetWorkConnected) { + System.out.println("网络连接状况:已连接"); + // 调用子线程进行访问,获取一级、二级分类信息 + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + classificationObj2 = bookService.getClassification2(); + Looper.prepare(); + if(classificationObj2 == null) { + Toast.makeText(getActivity(), "还是获取失败啊啊啊啊", Toast.LENGTH_SHORT).show(); + } + Looper.loop(); + } + }); + thread.start(); + + } + // 无网络 + else { + System.out.println("网络连接状况:未连接"); + Toast.makeText(getActivity(), "网络连接状况:未连接", Toast.LENGTH_SHORT).show(); + } + } + // 已经获取过分类信息 + else { + // 获取点击到的一级分类以及对应的二级分类数据 + String major; + String[] mins; + if(isMale) { + major = maleCategoriesName[position]; + mins = classificationObj2.getMaleList().get(position).getMins(); + } + else { + major = femaleCategoriesName[position]; + mins = classificationObj2.getFemaleList().get(position).getMins(); + } + // 获取失败 + if(major == null || mins == null) { + Toast.makeText(getActivity(), "获取失败", Toast.LENGTH_SHORT).show(); + } + // 获取数据成功 + else { + //Toast.makeText(getActivity(), major + "二级分类框弹出", Toast.LENGTH_SHORT).show(); + // 弹出一个二级分类框 + Dialog dialog = new Dialog(getActivity()); + dialog.setContentView(R.layout.dialog_category); + // 二级分类RecyclerView + RecyclerView dialog_recyclerview = dialog.findViewById(R.id.dialog_category_recyclerview); + // 二级分类数据初始化 + List dialog_categories = new ArrayList<>(); + for(int i = 0; i < mins.length; i++) + dialog_categories.add(new CategoryRecyObj(mins[i], "")); + + // 设置 Adapter + MyRecyclerViewAdapter dialog_adapter = new MyRecyclerViewAdapter(getActivity(), R.layout.item_category, dialog_categories) { + @Override + public void convert(MyViewHolder holder, CategoryRecyObj categoryRecyObj) { + TextView categoryName = holder.getView(R.id.item_category_name); + categoryName.setText(categoryRecyObj.getCategoryName()); + TextView categoryBookCount = holder.getView(R.id.item_category_count); + categoryBookCount.setVisibility(View.GONE); + } + }; + // 适配 Adapter + dialog_recyclerview.setAdapter(dialog_adapter); + // 设置 RecyclerView 布局 + dialog_recyclerview.setLayoutManager(new LinearLayoutManager(getActivity())); + + // 设置 dialog 属性并显示 + dialog.setCancelable(true); + dialog.show(); + } + + + + }*/ + } + + @Override + public void onLongClick(int position) { + + } + }); + + // 给 RecyclerView 适配 Adapter + recyclerView.setAdapter(adapter); + + } + + // 获取分类数据 + private void getMyCategories() { + boolean isNetWorkConnected = isNetWorkConnected(getActivity()); + bookService = BookService.getBookService(); + if(isNetWorkConnected) { + System.out.println("网络连接状况:已连接"); + // 调用子线程进行访问,获取一级、二级分类信息 + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + classificationObj2 = bookService.getClassification2(); + Looper.prepare(); + if(classificationObj2 == null) { + Toast.makeText(getActivity(), "获取失败", Toast.LENGTH_SHORT).show(); + } + Looper.loop(); + } + }); + thread.start(); + } + else { + System.out.println("网络连接状况:未连接"); + Toast.makeText(getActivity(), "网络连接状况:未连接", Toast.LENGTH_SHORT).show(); + } + myCategories = new ArrayList<>(); + // 男生向小说分类 + if(isMale) { + for(int i = 0; i < maleCategoriesName.length; i++) { + CategoryRecyObj c = new CategoryRecyObj(maleCategoriesName[i], maleCategoriesBookCount[i]); + myCategories.add(c); + } + } + // 女生向小说分类 + else { + for(int i = 0; i < femaleCategoriesName.length; i++) { + CategoryRecyObj c = new CategoryRecyObj(femaleCategoriesName[i], femaleCategoriesBookCount[i]); + myCategories.add(c); + } + } + } + + // 辅助函数:判断网络是否连接 + public boolean isNetWorkConnected(Context context) { + if (context != null) { + ConnectivityManager mConnectivityManager = (ConnectivityManager) context + .getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo(); + if (mNetworkInfo != null) { + return mNetworkInfo.isConnected(); + } + } + return false; + } + +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/RankingFragment.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/RankingFragment.java new file mode 100644 index 0000000..276e50b --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/RankingFragment.java @@ -0,0 +1,131 @@ +package com.example.Fragment; + +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Color; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +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 android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.List; + +import com.example.Activity.CategoryActivity; +import com.example.R; +import com.example.RecyclerView.MyRecyclerViewAdapter; +import com.example.RecyclerView.MyViewHolder; + +// 排行榜界面 +public class RankingFragment extends Fragment { + private boolean isMale; //男生/女生 + private int color1 = Color.parseColor("#F5D6D6");//最热榜 + private int color2 = Color.parseColor("#D8F8C2");//热搜榜 + private int color3 = Color.parseColor("#F9EBB0");//潜力榜 + private int color4 = Color.parseColor("#DBB5F4");//留存榜 + private int color5 = Color.parseColor("#CEFDFD");//完结榜 + + private RecyclerView recyclerView; + private List list = new ArrayList<>(); + private MyRecyclerViewAdapter adapter; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Bundle bundle = getArguments(); + this.isMale = bundle.getBoolean("isMale"); + if (isMale) { + list.add("最热榜"); + list.add("热搜榜"); + list.add("潜力榜"); + list.add("留存榜"); + list.add("完结榜"); + } + else { + list.add("热搜榜"); + list.add("留存榜"); + list.add("最热榜"); + list.add("潜力榜"); + list.add("完结榜"); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_ranking, null); + recyclerView = view.findViewById(R.id.ranking_recycler); + //设置recyclerView的显示 + recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + adapter = new MyRecyclerViewAdapter(getActivity(), R.layout.item_ranking, list) { + @Override + public void convert(MyViewHolder holder, String type) { + Bitmap bitmap = null; + int color = color1; + switch (type) { + case "最热榜": + if (isMale) bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.male_icon1, null); + else bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.female_icon1, null); + color = color1; + break; + case "热搜榜": + if (isMale) bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.male_icon2, null); + else bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.female_icon2, null); + color = color2; + break; + case "潜力榜": + if (isMale) bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.male_icon3, null); + else bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.female_icon3, null); + color = color3; + break; + case "留存榜": + if (isMale) bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.male_icon4, null); + else bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.female_icon4, null); + color = color4; + break; + case "完结榜": + if (isMale) bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.male_icon5, null); + else bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.female_icon5, null); + color = color5; + break; + } + ImageView imageView = holder.getView(R.id.ranking_item_image); + imageView.setImageBitmap(bitmap); + TextView textView = holder.getView(R.id.ranking_item_text); + textView.setText(type); + RelativeLayout layout = holder.getView(R.id.ranking_item_right); + layout.setBackgroundColor(color); + } + }; + //设置RecyclerView的点击响应事件 + adapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() { + @Override + public void onClick(int position) { + //跳转到对应榜单界面 + Intent intent = new Intent(getActivity(), CategoryActivity.class); + Bundle bundle = new Bundle(); + bundle.putBoolean("isRanking", true); + bundle.putBoolean("isMale", isMale); + bundle.putString("title", list.get(position)); + intent.putExtras(bundle); + startActivity(intent); + } + + @Override + public void onLongClick(int position) { + + } + }); + recyclerView.setAdapter(adapter); + + return view; + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/ReadPageFragment.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/ReadPageFragment.java new file mode 100644 index 0000000..77652d7 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/ReadPageFragment.java @@ -0,0 +1,73 @@ +package com.example.Fragment; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.util.TypedValue; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.TextView; + +import com.example.R; + +// 阅读界面的Fragment +public class ReadPageFragment extends Fragment { + // 页面数据 + private String title; //章节名 + private String content; //本章内容 + int day_or_night_status; //日间或夜间模式 + int textSize; //字体大小 + + // 帧页面View + View view; + // 帧页面控件 + private TextView titile_control; // 标题 + private TextView content_control; // 阅读页内容 + private FrameLayout whole_layout_control; // 整个框页面 + + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + this.content = getArguments().getString("content"); + this.title = getArguments().getString("title"); + this.day_or_night_status = getArguments().getInt("day_or_night_status"); + this.textSize = getArguments().getInt("textSize"); + //System.out.println("日间夜间:" + day_or_night_status); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // 获取帧页面View + view = inflater.inflate(R.layout.fragment_read_page, null); + + // 获取页面控件 + init_page_control(); + + // 设置页面内容 + init_page_info(); + + //todo + return view; + } + + private void init_page_info() { + titile_control.setText(title); // 设置标题 + content_control.setText(content); // 设置阅读页内容 + content_control.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize); + if(day_or_night_status == 0) { + whole_layout_control.setBackgroundColor(getResources().getColor(R.color.PapayaWhip)); + } + else whole_layout_control.setBackgroundColor(getResources().getColor(R.color.nightBackGround)); + //progress_control.setText(Integer.toString(currentChapter+1) + "/" + Integer.toString(totalChapter+1)); + } + + private void init_page_control() { + titile_control = view.findViewById(R.id.fragment_read_page_title); + content_control = view.findViewById(R.id.fragment_read_page_content); + whole_layout_control = view.findViewById(R.id.fragment_read_page_whole_layout); + //progress_control = view.findViewById(R.id.fragment_read_page_process); + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/TabFragmentPagerAdapter.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/TabFragmentPagerAdapter.java new file mode 100644 index 0000000..644a71a --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/TabFragmentPagerAdapter.java @@ -0,0 +1,28 @@ +package com.example.Fragment; + +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; + +import java.util.List; +// 碎片适配器 +public class TabFragmentPagerAdapter extends FragmentPagerAdapter { + private FragmentManager fm; + private List list; + + public TabFragmentPagerAdapter(FragmentManager fm, List list) { + super(fm); + this.fm = fm; + this.list = list; + } + + @Override + public Fragment getItem(int i) { + return list.get(i); + } + + @Override + public int getCount() { + return list.size(); + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/TabFragmentStatePagerAdapter.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/TabFragmentStatePagerAdapter.java new file mode 100644 index 0000000..509abe0 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Fragment/TabFragmentStatePagerAdapter.java @@ -0,0 +1,33 @@ +package com.example.Fragment; + +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.view.PagerAdapter; + +import java.util.List; +// 碎片状态适配器 +public class TabFragmentStatePagerAdapter extends android.support.v4.app.FragmentStatePagerAdapter { + private FragmentManager fm; + private List list; + + public TabFragmentStatePagerAdapter(FragmentManager fm, List list) { + super(fm); + this.fm = fm; + this.list = list; + } + + @Override + public int getItemPosition(Object object) { + return PagerAdapter.POSITION_NONE; + } + + @Override + public Fragment getItem(int i) { + return list.get(i); + } + + @Override + public int getCount() { + return list.size(); + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/AllRankingObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/AllRankingObj.java new file mode 100644 index 0000000..9706e25 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/AllRankingObj.java @@ -0,0 +1,89 @@ +package com.example.Object; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +public class AllRankingObj { + + // 男生 + @SerializedName("male") + private List maleList; + + // 女生 + @SerializedName("female") + private List femaleList; + + @SerializedName("ok") + private boolean ok; + + public List getMaleList() { + return maleList; + } + + public List getFemaleList() { + return femaleList; + } + + public boolean isOk() { + return ok; + } + + public class subClass { + // 周榜id + @SerializedName("_id") + private String id; + + // 排行榜全名 + @SerializedName("title") + private String title; + + // 排行榜大图标 + @SerializedName("cover") + private String cover; + + @SerializedName("collapse") + private boolean collapse; + + // 月榜id + @SerializedName("monthRank") + private String monthRank; + + // 总榜id + @SerializedName("totalRank") + private String totalRank; + + // 排行榜简称 + @SerializedName("shortTitle") + private String shortTitle; + + public String getId() { + return id; + } + + public String getTitle() { + return title; + } + + public String getCover() { + return cover; + } + + public boolean isCollapse() { + return collapse; + } + + public String getMonthRank() { + return monthRank; + } + + public String getTotalRank() { + return totalRank; + } + + public String getShortTitle() { + return shortTitle; + } + } + +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/BookObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/BookObj.java new file mode 100644 index 0000000..dfc3907 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/BookObj.java @@ -0,0 +1,166 @@ +package com.example.Object; + +import com.google.gson.annotations.SerializedName; + +import java.io.Serializable; + +// 书籍的对象 +public class BookObj implements Serializable { + // 书籍id + @SerializedName("_id") + private String id; + + // 书籍标题 + @SerializedName("title") + private String title; + + // 书籍作者 + @SerializedName("author") + private String author; + + // 书籍介绍 + @SerializedName("longIntro") + private String longIntro; + + // 书籍简介 + @SerializedName("shortIntro") + private String shortIntro; + + // 书籍封面图 + @SerializedName("cover") + private String cover; + + @SerializedName("site") + private String site; + + // 书籍一级分类 + @SerializedName("majorCate") + private String majorCate; + + // 书籍二级分类 + @SerializedName("minorCate") + private String minorCate; + + @SerializedName("sizetype") + private int sizetype; + + @SerializedName("contentType") + private String contentType; + + @SerializedName("allowMonthly") + private boolean allowMonthly; + + @SerializedName("banned") + private int banned; + + // 最近关注人数 + @SerializedName("latelyFollower") + private int latelyFollower; + + // 字数 + @SerializedName("wordCount") + private int wordCount; + + // 留存率 + @SerializedName("retentionRatio") + private float retentionRatio; + + // 最新章节 + @SerializedName("lastChapter") + private String lastChapter; + + @SerializedName("updated") + private String updated; + + // 性别 + @SerializedName("gender") + private String[] gender; + + // 标签 + @SerializedName("tags") + private String[] tags; + + public String getId() { + return id; + } + + public String getTitle() { + return title; + } + + public String getAuthor() { + return author; + } + + public String getShortIntro() { + return shortIntro; + } + + public void setShortIntro(String shortIntro) { + this.shortIntro = shortIntro; + } + + public String getCover() { + return cover; + } + + public String getSite() { + return site; + } + + public String getMajorCate() { + return majorCate; + } + + public String getMinorCate() { + return minorCate; + } + + public int getSizetype() { + return sizetype; + } + + public String getContentType() { + return contentType; + } + + public boolean isAllowMonthly() { + return allowMonthly; + } + + public String getLongIntro() { + return longIntro; + } + + public String[] getGender() { + return gender; + } + + public int getBanned() { + return banned; + } + + public int getLatelyFollower() { + return latelyFollower; + } + + public float getRetentionRatio() { + return retentionRatio; + } + + public String getLastChapter() { + return lastChapter; + } + + public String[] getTags() { + return tags; + } + + public int getWordCount() { + return wordCount; + } + + public String getUpdated() { + return updated; + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/CategoryObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/CategoryObj.java new file mode 100644 index 0000000..21b5f6e --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/CategoryObj.java @@ -0,0 +1,31 @@ +package com.example.Object; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +public class CategoryObj { + // 书籍总数 + @SerializedName("total") + private int total; + + // 书籍列表 + @SerializedName("books") + private List books; + + // 获取结果 + @SerializedName("ok") + private boolean ok; + + public int getTotal() { + return total; + } + + public List getBooks() { + return books; + } + + public boolean isOk() { + return ok; + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ChapterLinkObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ChapterLinkObj.java new file mode 100644 index 0000000..771f848 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ChapterLinkObj.java @@ -0,0 +1,42 @@ +package com.example.Object; + +import com.google.gson.annotations.SerializedName; + +import java.io.Serializable; + +public class ChapterLinkObj implements Serializable { + // 章节链接 + @SerializedName("link") + private String link; + + // 章节标题 + @SerializedName("title") + private String title; + + // 是否不可读 + @SerializedName("unreadable") + private boolean unreadable; + + public ChapterLinkObj() { + super(); + } + + public ChapterLinkObj(String _link, String _title, boolean _unreadable) { + link = _link; + title = _title; + unreadable = _unreadable; + } + + + public String getLink() { + return link; + } + + public String getTitle() { + return title; + } + + public boolean isUnreadable() { + return unreadable; + } +} \ No newline at end of file diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ChapterLinks.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ChapterLinks.java new file mode 100644 index 0000000..a01515b --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ChapterLinks.java @@ -0,0 +1,12 @@ +package com.example.Object; + +import java.io.Serializable; +import java.util.List; + +public class ChapterLinks implements Serializable { + public List chapterLinkList; + + public List getChapterLinkList() { + return chapterLinkList; + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ChapterObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ChapterObj.java new file mode 100644 index 0000000..af626a8 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ChapterObj.java @@ -0,0 +1,43 @@ +package com.example.Object; + +import com.google.gson.annotations.SerializedName; + +// 获取章节内容返回结果 +public class ChapterObj { + // 请求结果 + @SerializedName("ok") + private boolean ok; + + @SerializedName("chapter") + private Chapter ichapter; + + public boolean isOk() { + return ok; + } + + public Chapter getIchapter() { + return ichapter; + } + + /* + * 章节详情 + */ + public class Chapter { + // 章节标题 + @SerializedName("title") + private String title; + + // 章节内容 + @SerializedName("body") + private String body; + + + public String getTitle() { + return title; + } + + public String getBody() { + return body; + } + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ClassificationObj1.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ClassificationObj1.java new file mode 100644 index 0000000..975cf85 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ClassificationObj1.java @@ -0,0 +1,90 @@ +package com.example.Object; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +// 获取一级分类返回结果 +public class ClassificationObj1 { + // male分类 + @SerializedName("male") + private List maleList; + + // female分类 + @SerializedName("female") + private List femaleList; + + // picture分类 + @SerializedName("picture") + private List picList; + + @SerializedName("press") + private List pressList; + + @SerializedName("ok") + private boolean ok; + + public List getMaleList() { + return maleList; + } + + public List getFemaleList() { + return femaleList; + } + + public List getPicList() { + return picList; + } + + public List getPressList() { + return pressList; + } + + public boolean isOk() { + return ok; + } + + // 一级分类 + public class SubClass1 { + // 名称 + @SerializedName("name") + private String name; + + // 书籍数量 + @SerializedName("bookCount") + private int bookCount; + + // monthlyCount? + @SerializedName("monthlyCount") + private int monthlyCount; + + // 分类图标 + @SerializedName("icon") + private String icon; + + // 封面图链接 + @SerializedName("bookCover") + private String[] bookCover; + + public String getName() { + return name; + } + + public int getBookCount() { + return bookCount; + } + + public int getMonthlyCount() { + return monthlyCount; + } + + public String getIcon() { + return icon; + } + + public String[] getBookCover() { + return bookCover; + } + } + +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ClassificationObj2.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ClassificationObj2.java new file mode 100644 index 0000000..ec449c0 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ClassificationObj2.java @@ -0,0 +1,58 @@ +package com.example.Object; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +public class ClassificationObj2 { + @SerializedName("male") + private List maleList; + + @SerializedName("female") + private List femaleList; + + @SerializedName("picture") + private List picList; + + @SerializedName("press") + private List pressList; + + @SerializedName("ok") + private boolean ok; + + public List getMaleList() { + return maleList; + } + + public List getFemaleList() { + return femaleList; + } + + public List getPicList() { + return picList; + } + + public List getPressList() { + return pressList; + } + + public boolean isOk() { + return ok; + } + + public class SubClass2 { + @SerializedName("major") + private String major; + + @SerializedName("mins") + private String[] mins; + + public String getMajor() { + return major; + } + + public String[] getMins() { + return mins; + } + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/CptListObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/CptListObj.java new file mode 100644 index 0000000..5399d21 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/CptListObj.java @@ -0,0 +1,64 @@ +package com.example.Object; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +// 获取章节列表返回结果 +public class CptListObj { + // 请求结果 + @SerializedName("ok") + private boolean ok; + + @SerializedName("mixToc") + private mixToc imixToc; + + public boolean isOk() { + return ok; + } + + public mixToc getImixToc() { + return imixToc; + } + + /* + * 章节列表 + */ + public class mixToc { + @SerializedName("_id") + private String _id; + // 书籍id + @SerializedName("book") + private String book; + // 章节数 + @SerializedName("chaptersCount1") + private int chaptersCount; + // 章节列表 + @SerializedName("chapters") + public List chapterLinks; + // 更新时间 + @SerializedName("updated") + private String updated; + + public String get_id() { + return _id; + } + + public String getBook() { + return book; + } + + public int getChaptersCount() { + return chaptersCount; + } + + public List getChapterLinks() { + return chapterLinks; + } + + public String getUpdated() { + return updated; + } + + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/FuzzySearchResultObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/FuzzySearchResultObj.java new file mode 100644 index 0000000..3e213c8 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/FuzzySearchResultObj.java @@ -0,0 +1,26 @@ +package com.example.Object; + +import com.google.gson.annotations.SerializedName; + +public class FuzzySearchResultObj { + @SerializedName("code") + private int code; + + @SerializedName("msg") + private String msg; + + @SerializedName("data") + private String[] data; + + public int getCode() { + return code; + } + + public String getMsg() { + return msg; + } + + public String[] getData() { + return data; + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/RecomListObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/RecomListObj.java new file mode 100644 index 0000000..602a8b8 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/RecomListObj.java @@ -0,0 +1,16 @@ +package com.example.Object; + +import java.io.Serializable; +import java.util.List; +// +public class RecomListObj implements Serializable { + private List bookObjs; + + public RecomListObj(List bookObjs) { + this.bookObjs = bookObjs; + } + + public List getBookObjs() { + return bookObjs; + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/SearchResultObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/SearchResultObj.java new file mode 100644 index 0000000..88f496d --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/SearchResultObj.java @@ -0,0 +1,185 @@ +package com.example.Object; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; +// 搜索结果对象 +public class SearchResultObj { + // 书籍列表 + @SerializedName("books") + private List bookList; + + // 总数 + @SerializedName("total") + private int total; + + @SerializedName("ok") + private boolean ok; + + public List getBookList() { + return bookList; + } + + public int getTotal() { + return total; + } + + public boolean isOk() { + return ok; + } + + public class book { + // 书籍id + @SerializedName("_id") + private String _id; + + @SerializedName("hasCp") + private boolean hasCp; + + // 书名 + @SerializedName("title") + private String title; + + @SerializedName("aliases") + private String aliases; + + // 一级分类 + @SerializedName("cat") + private String cat; + + // 作者 + @SerializedName("author") + private String author; + + @SerializedName("site") + private String site; + + // 封面 + @SerializedName("cover") + private String cover; + + // 简介 + @SerializedName("shortIntro") + private String shortIntro; + + // 最新章节 + @SerializedName("lastChapter") + private String lastChapter; + + // 留存率 + @SerializedName("retentionRatio") + private float retentionRatio; + + @SerializedName("banned") + private int banned; + + @SerializedName("allowMonthly") + private boolean allowMonthly; + + // 关注人数 + @SerializedName("latelyFollower") + private int latelyFollower; + + // 字数 + @SerializedName("wordCount") + private int wordCount; + + // 类型 + @SerializedName("contentType") + private String contentType; + + @SerializedName("superscript") + private String superscript; + + @SerializedName("sizetype") + private int sizetype; + + @SerializedName("highlight") + private highlight mhighlight; + + public String get_id() { + return _id; + } + + public boolean isHasCp() { + return hasCp; + } + + public String getTitle() { + return title; + } + + public String getAliases() { + return aliases; + } + + public String getCat() { + return cat; + } + + public String getAuthor() { + return author; + } + + public String getSite() { + return site; + } + + public String getCover() { + return cover; + } + + public String getShortIntro() { + return shortIntro; + } + + public String getLastChapter() { + return lastChapter; + } + + public float getRetentionRatio() { + return retentionRatio; + } + + public int getBanned() { + return banned; + } + + public boolean isAllowMonthly() { + return allowMonthly; + } + + public int getLatelyFollower() { + return latelyFollower; + } + + public int getWordCount() { + return wordCount; + } + + public String getContentType() { + return contentType; + } + + public String getSuperscript() { + return superscript; + } + + public int getSizetype() { + return sizetype; + } + + public highlight getMhighlight() { + return mhighlight; + } + + public class highlight { + @SerializedName("title") + private String[] title; + + public String[] getTitle() { + return title; + } + } + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ShelfBookObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ShelfBookObj.java new file mode 100644 index 0000000..7cea380 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/ShelfBookObj.java @@ -0,0 +1,109 @@ +package com.example.Object; + +import android.graphics.Bitmap; +// 书架书籍对象 +public class ShelfBookObj { + String bookId; //id + private Bitmap icon; //图标 + private String iconURL; //图标网络url + private String name; //书名 + private String description; //描述 + private String author; //作者 + private String major; //一级分类 + int type; //0代表网络图片,1代表本地图片 + private String address; //本地书籍url + private int readChapter; //阅读到的章节 + + public ShelfBookObj(String bookId, String name, Bitmap icon, String iconURL, int readChapter, String address,int type,String description,String author, String major) { + this.bookId = bookId; + this.name = name; + this.icon = icon; + this.iconURL = iconURL; + this.readChapter = readChapter; + this.address = address; + this.type = type; + this.description = description; + this.author = author; + this.major = major; + } + + public String getIconURL() { + return iconURL; + } + + public void setIconURL(String iconURL) { + this.iconURL = iconURL; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getName() { + return name; + } + + public Bitmap getIcon() { + return icon; + } + + public String getAddress() { + return address; + } + + public void setIcon(Bitmap icon) { + this.icon = icon; + } + + public int getReadChapter() { + return readChapter; + } + + public void setName(String name) { + this.name = name; + } + + public void setAddress(String address) { + this.address = address; + } + + public void setReadChapter(int readChapter) { + this.readChapter = readChapter; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public String getBookId() { + return bookId; + } + + public void setBookId(String bookId) { + this.bookId = bookId; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getMajor() { + return major; + } + + public void setMajor(String major) { + this.major = major; + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/SingleRankingObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/SingleRankingObj.java new file mode 100644 index 0000000..ba30d4d --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/SingleRankingObj.java @@ -0,0 +1,175 @@ +package com.example.Object; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; +// 单独排行对象 +public class SingleRankingObj { + @SerializedName("ranking") + private Ranking ranking; + + @SerializedName("ok") + private boolean ok; + + public Ranking getRanking() { + return ranking; + } + + public boolean isOk() { + return ok; + } + + public class Ranking { + // 周榜id + @SerializedName("_id") + private String _id; + + // 更新时间 + @SerializedName("updated") + private String updated; + + // 排行榜全名 + @SerializedName("title") + private String title; + + @SerializedName("tag") + private String tag; + + // 排行榜大图标 + @SerializedName("cover") + private String cover; + + // 排行榜小图标 + @SerializedName("icon") + private String icon; + + @SerializedName("__v") + private String __v; + + // 月榜id + @SerializedName("monthRank") + private String monthRank; + + // 总榜id + @SerializedName("totalRank") + private String totalRank; + + // 排行榜简称 + @SerializedName("shortTitle") + private String shortTitle; + + @SerializedName("created") + private String created; + + @SerializedName("biTag") + private String biTag; + + @SerializedName("isSub") + private boolean isSub; + + @SerializedName("collapse") + private boolean collapse; + + @SerializedName("new") + private boolean _new; + + // 性别 + @SerializedName("gender") + private String gender; + + @SerializedName("priority") + private int priority; + + // 书籍列表 + @SerializedName("books") + private List bookList; + + // 周榜id + @SerializedName("id") + private String id; + + // 总数 + @SerializedName("total") + private int total; + + public String get_id() { + return _id; + } + + public String getUpdated() { + return updated; + } + + public String getTitle() { + return title; + } + + public String getTag() { + return tag; + } + + public String getCover() { + return cover; + } + + public String getIcon() { + return icon; + } + + public String get__v() { + return __v; + } + + public String getMonthRank() { + return monthRank; + } + + public String getTotalRank() { + return totalRank; + } + + public String getShortTitle() { + return shortTitle; + } + + public String getCreated() { + return created; + } + + public String getBiTag() { + return biTag; + } + + public boolean isSub() { + return isSub; + } + + public boolean isCollapse() { + return collapse; + } + + public boolean is_new() { + return _new; + } + + public String getGender() { + return gender; + } + + public int getPriority() { + return priority; + } + + public List getBookList() { + return bookList; + } + + public String getId() { + return id; + } + + public int getTotal() { + return total; + } + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/UserStatusObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/UserStatusObj.java new file mode 100644 index 0000000..7f81871 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Object/UserStatusObj.java @@ -0,0 +1,48 @@ +package com.example.Object; +// 用户状态对象 +public class UserStatusObj { + int user_id; + int hor_or_ver_screen; + int day_or_night_status; + int textSize; + + public UserStatusObj(int user_id, int hor_or_ver_screen, int day_or_night_status, int textSize) { + this.user_id = user_id; + this.hor_or_ver_screen = hor_or_ver_screen; + this.day_or_night_status = day_or_night_status; + this.textSize = textSize; + } + + public int getDay_or_night_status() { + return day_or_night_status; + } + + public int getHor_or_ver_screen() { + return hor_or_ver_screen; + } + + public int getTextSize() { + return textSize; + } + + public int getUser_id() { + return user_id; + } + + public void setDay_or_night_status(int dat_or_night_status) { + this.day_or_night_status = dat_or_night_status; + } + + public void setHor_or_ver_screen(int hor_or_ver_screen) { + this.hor_or_ver_screen = hor_or_ver_screen; + } + + public void setTextSize(int textSize) { + this.textSize = textSize; + } + + public void setUser_id(int user_id) { + this.user_id = user_id; + } +} + diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/CateRecyclerViewAdapter.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/CateRecyclerViewAdapter.java new file mode 100644 index 0000000..413070a --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/CateRecyclerViewAdapter.java @@ -0,0 +1,222 @@ +package com.example.RecyclerView; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.Handler; +import android.os.Looper; +import android.support.annotation.NonNull; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.ProgressBar; +import android.widget.TextView; + +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import com.example.R; +import com.example.Object.BookObj; +import com.example.Service.BookService; + +// 用于排行榜、分类界面的RecyclerView的Adapter +public class CateRecyclerViewAdapter extends RecyclerView.Adapter { + private Context context; + private List data; + private boolean isRanking; + private OnItemClickListener onItemClickListener; + + private int normalType = 0; // 第一种ViewType,正常的item + private int footType = 1; // 第二种ViewType,底部的提示View + + private boolean hasMore = true; // 变量,是否有更多数据 + private boolean fadeTips = false; // 变量,是否隐藏了底部的提示 + + private Handler mHandler = new Handler(Looper.getMainLooper()); //获取主线程的Handler + + + public CateRecyclerViewAdapter(List data, Context context, boolean hasMore, boolean isRanking) { + this.data = data; + this.context = context; + this.hasMore = hasMore; + this.isRanking = isRanking; + } + + public boolean isFadeTips() { + return fadeTips; + } + + @NonNull + @Override + public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) { + //根据不同的ViewType绑定不同的布局文件 + if (viewType == normalType) { + MyViewHolder holder = MyViewHolder.get(context, viewGroup, R.layout.item_book); + holder.setNormalTypeType(true); + return holder; + } + else { + MyViewHolder holder = MyViewHolder.get(context, viewGroup, R.layout.recycler_footer_view); + holder.setNormalTypeType(false); + return holder; + } + } + + @Override + public void onBindViewHolder(@NonNull final MyViewHolder holder, int position) { + if (data.isEmpty()) return; + if (holder.isNormalType() == true) {//是正常的布局 + BookObj bookObj = data.get(position); + if (isRanking && !data.isEmpty()) { + ImageView rankingImg = holder.getView(R.id.item_book_rankingImg); + if (position == 0) {//排行榜第一名 + rankingImg.setImageBitmap(BitmapFactory.decodeResource(context.getResources(), R.mipmap.first, null)); + rankingImg.setVisibility(View.VISIBLE); + } else if (position == 1) {//排行榜第二名 + rankingImg.setImageBitmap(BitmapFactory.decodeResource(context.getResources(), R.mipmap.second, null)); + rankingImg.setVisibility(View.VISIBLE); + } else if (position == 2) {//排行榜第三名 + rankingImg.setImageBitmap(BitmapFactory.decodeResource(context.getResources(), R.mipmap.third, null)); + rankingImg.setVisibility(View.VISIBLE); + } + else rankingImg.setVisibility(View.GONE); + } + final ImageView imageView = holder.getView(R.id.item_book_cover); + TextView bookName = holder.getView(R.id.item_book_name); + TextView bookAuthor = holder.getView(R.id.item_book_author); + TextView bookType = holder.getView(R.id.item_book_type); + TextView bookIntro = holder.getView(R.id.item_book_intro); + TextView followers = holder.getView(R.id.item_book_followers); + TextView retention = holder.getView(R.id.item_book_retention); + int num = bookObj.getLatelyFollower(); + if (num < 10000) { + followers.setText(bookObj.getLatelyFollower() + "人追"); + } + else { + num /= 10000; + followers.setText(num + "万人追"); + } + followers.setVisibility(View.VISIBLE); + retention.setText(bookObj.getRetentionRatio() + "%留存率"); + retention.setVisibility(View.VISIBLE); + bookName.setText(bookObj.getTitle()); + bookType.setText(bookObj.getMajorCate()); + bookAuthor.setText(bookObj.getAuthor()); + bookIntro.setText(bookObj.getShortIntro()); + + //通过网络获取书籍图标 + final String iconURL = BookService.StaticsUrl + bookObj.getCover(); + new Thread(new Runnable() { + @Override + public void run() { + try { + URL url = new URL(iconURL); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + connection.setConnectTimeout(10000); + if (connection.getResponseCode() == 200) { + InputStream inputStream = connection.getInputStream(); + final Bitmap bitmap = BitmapFactory.decodeStream(inputStream); + mHandler.post(new Runnable() { + @Override + public void run() { + imageView.setImageBitmap(bitmap); + } + }); + } + } catch (Exception e) { + System.err.println(e.getMessage()); + } + }}).start(); + } + else {//是提示加载信息的布局 + final ProgressBar progressBar = holder.getView(R.id.footer_view_progessBar); + final TextView tips = holder.getView(R.id.footer_view_text); + tips.setVisibility(View.VISIBLE); + progressBar.setVisibility(View.VISIBLE); + // 只有获取数据为空时,hasMore为false,所以当我们拉到底部时基本都会首先显示“正在加载更多...” + if (hasMore == true) { + // 不隐藏footView提示 + fadeTips = false; + if (data.size() > 0) { + // 如果查询数据发现增加之后,就显示正在加载更多数据 + tips.setText("正在加载更多数据..."); + progressBar.setVisibility(View.VISIBLE); + } + } else { + if (data.size() > 0) { + // 如果查询数据发现并没有增加时,就显示没有更多数据了 + tips.setText("没有更多数据了"); + // 隐藏提示条 + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + // 隐藏提示条 + tips.setVisibility(View.GONE); + progressBar.setVisibility(View.GONE); + // 将fadeTips设置true + fadeTips = true; + // hasMore设为true是为了让再次拉到底时,会先显示正在加载更多 + hasMore = true; + } + }, 500); + } + } + } + //设置监听器 + if (onItemClickListener != null) { + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + onItemClickListener.onClick(holder.getAdapterPosition()); + } + }); + } + } + + @Override + public int getItemCount() { + return data.size() + 1; + } + + //获取列表中数据源的最后一个位置 + public int getLastPosition() { + return data.size(); + } + + // 根据条目位置返回ViewType,以供onCreateViewHolder方法内获取不同的Holder + @Override + public int getItemViewType(int position) { + if (position == getItemCount() - 1) { + return footType; + } else { + return normalType; + } + } + + //下拉刷新时,通过暴露方法将数据源置为空 + public void resetDatas() { + data = new ArrayList<>(); + } + + //更新数据源,并修改hasMore的值,如果有增加数据,hasMore为true,否则为false + public void updateList(List newDatas, boolean hasMore) { + // 在原有的数据之上增加新数据 + if (newDatas != null) { + data.addAll(newDatas); + } + this.hasMore = hasMore; + notifyDataSetChanged(); + } + + public interface OnItemClickListener{ + void onClick(int position); + } + public void setOnItemClickListener(OnItemClickListener _onItemClickListener) { + this.onItemClickListener = _onItemClickListener; + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/CategoryRecyObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/CategoryRecyObj.java new file mode 100644 index 0000000..550a2fa --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/CategoryRecyObj.java @@ -0,0 +1,27 @@ +package com.example.RecyclerView; +// 分类的实体 +public class CategoryRecyObj { + private String categoryName; + private String bookCount; + + public CategoryRecyObj(String categoryName, String bookCount) { + this.categoryName = categoryName; + this.bookCount = bookCount; + } + + public String getBookCount() { + return bookCount; + } + + public String getCategoryName() { + return categoryName; + } + + public void setBookCount(String bookCount) { + this.bookCount = bookCount; + } + + public void setCategoryName(String categoryName) { + this.categoryName = categoryName; + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/MyRecyclerViewAdapter.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/MyRecyclerViewAdapter.java new file mode 100644 index 0000000..557b210 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/MyRecyclerViewAdapter.java @@ -0,0 +1,72 @@ +package com.example.RecyclerView; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.view.ViewGroup; +import java.util.List; + +public abstract class MyRecyclerViewAdapter extends RecyclerView.Adapter { + private Context context; + private int layoutId; + private List data; + private OnItemClickListener onItemClickListener; + + //构造函数 + public MyRecyclerViewAdapter(Context _context, int _layoutId, List _data){ + context = _context; + layoutId = _layoutId; + data = _data; + } + + //创建自定的ViewHolder和绑定ViewHolder + @Override + public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + MyViewHolder holder = MyViewHolder.get(context, parent, layoutId); + return holder; + } + + @Override + public void onBindViewHolder(final MyViewHolder holder, int position) { + convert(holder, data.get(position)); // convert函数需要重写,下面会讲 + if (onItemClickListener != null) { + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + onItemClickListener.onClick(holder.getAdapterPosition()); + } + }); + holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View view) { + onItemClickListener.onLongClick(holder.getAdapterPosition()); + return false; + } + }); + } + } + + @Override + public int getItemCount() { + if (data == null) + return 0; + return data.size(); + } + + public abstract void convert(final MyViewHolder holder, final T t); + + + public interface OnItemClickListener{ + void onClick(int position); + void onLongClick(int position); + } + + public void setOnItemClickListener(OnItemClickListener _onItemClickListener) { + this.onItemClickListener = _onItemClickListener; + } + + public void refresh(List list) { + this.data = list; + notifyDataSetChanged(); + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/MyViewHolder.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/MyViewHolder.java new file mode 100644 index 0000000..2ffa576 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/MyViewHolder.java @@ -0,0 +1,47 @@ +package com.example.RecyclerView; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.util.SparseArray; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +// ViewHolder用来复用列表中的控件 +public class MyViewHolder extends RecyclerView.ViewHolder { + private SparseArray views; + private View view; + private boolean isNormalType; + + public void setNormalTypeType(boolean type) { + this.isNormalType = type; + } + + public boolean isNormalType() { + return isNormalType; + } + + public MyViewHolder(Context _context, View _view, ViewGroup _viewGroup){ + super(_view); + view = _view; + views = new SparseArray(); + } + + public static MyViewHolder get(Context _context, ViewGroup _viewGroup, int _layoutId) { + View _view = LayoutInflater.from(_context).inflate(_layoutId, _viewGroup, false); + MyViewHolder holder = new MyViewHolder(_context, _view, _viewGroup); + return holder; + } + + public T getView(int _viewId) { + View _view = views.get(_viewId); + if (_view == null) { + // 创建view + _view = view.findViewById(_viewId); + // 将view存入views + views.put(_viewId, _view); + } + return (T)_view; + } + +} + diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/RankRecyObj.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/RankRecyObj.java new file mode 100644 index 0000000..03a447f --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/RecyclerView/RankRecyObj.java @@ -0,0 +1,27 @@ +package com.example.RecyclerView; + +import android.graphics.Bitmap; +// 排行榜实体类 +public class RankRecyObj { + private Bitmap image; + private String name; + private int color; + + public RankRecyObj(Bitmap image, String name, int color) { + this.image = image; + this.name = name; + this.color = color; + } + + public String getName() { + return name; + } + + public Bitmap getImage() { + return image; + } + + public int getColor() { + return color; + } +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Service/BookService.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Service/BookService.java new file mode 100644 index 0000000..7b6eb55 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Service/BookService.java @@ -0,0 +1,311 @@ +package com.example.Service; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.util.concurrent.TimeUnit; + +import com.example.Object.AllRankingObj; +import com.example.Object.BookObj; +import com.example.Object.CategoryObj; +import com.example.Object.ChapterObj; +import com.example.Object.ClassificationObj1; +import com.example.Object.ClassificationObj2; +import com.example.Object.CptListObj; +import com.example.Object.FuzzySearchResultObj; +import com.example.Object.SearchResultObj; +import com.example.Object.SingleRankingObj; +import okhttp3.OkHttpClient; +import retrofit2.Response; +import retrofit2.Retrofit; +import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; +import retrofit2.converter.gson.GsonConverterFactory; + + +public class BookService { + public static String ApiUrl = "http://api.zhuishushenqi.com"; + public static String StaticsUrl = "http://statics.zhuishushenqi.com"; + public static String ChapterUrl = "http://chapter2.zhuishushenqi.com"; + public static String FuzzySearchUrl = "https://www.apiopen.top"; + + private static BookService bookService = new BookService(); + + public static synchronized BookService getBookService() { + return bookService; + } + + OkHttpClient build = new OkHttpClient.Builder() + .connectTimeout(2, TimeUnit.SECONDS) + .readTimeout(2, TimeUnit.SECONDS) + .writeTimeout(2, TimeUnit.SECONDS) + .build(); + + // 用于API访问 + Retrofit retrofitForApi = new Retrofit.Builder() + .baseUrl(ApiUrl) + // 设置json数据解析器 + .addConverterFactory(GsonConverterFactory.create()) + // RxJava封装OkHttp的Call函数,本质还是利用OkHttp请求数据 + .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) + .client(build) + .build(); + + // 用于图片访问 + Retrofit retrofitForStatics = new Retrofit.Builder() + .baseUrl(StaticsUrl) + // 设置json数据解析器 + .addConverterFactory(GsonConverterFactory.create()) + // RxJava封装OkHttp的Call函数,本质还是利用OkHttp请求数据 + .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) + .client(build) + .build(); + + // 用于章节访问 + Retrofit retrofitForChapter = new Retrofit.Builder() + .baseUrl(ChapterUrl) + // 设置json数据解析器 + .addConverterFactory(GsonConverterFactory.create()) + // RxJava封装OkHttp的Call函数,本质还是利用OkHttp请求数据 + .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) + .client(build) + .build(); + + Retrofit retrofitForFuzzySearch = new Retrofit.Builder() + .baseUrl(FuzzySearchUrl) + .addConverterFactory(GsonConverterFactory.create()) + .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) + .client(build) + .build(); + + // 用于访问api + private UrlService ApiService = retrofitForApi.create(UrlService.class); + + // 用于访问图片 + private UrlService StaticsService = retrofitForStatics.create(UrlService.class); + + // 用于访问章节 + private UrlService ChapterService = retrofitForChapter.create(UrlService.class); + + // 用于模糊搜索 + private UrlService FuzzySearchService = retrofitForFuzzySearch.create(UrlService.class); + + // 所有排行榜 + private AllRankingObj allRankingObj; + + // 单一排行榜 + private SingleRankingObj singleRankingObj; + + // 一级分类 + private ClassificationObj1 classificationObj1; + + // 二级分类 + private ClassificationObj2 classificationObj2; + + // 书籍列表 + private CategoryObj categoryObj; + + // 书籍详情 + private BookObj bookObj; + + // 章节列表 + private CptListObj cptListObj; + + // 章节内容 + private ChapterObj chapterObj; + + // 书籍搜索结果 + private SearchResultObj searchResultObj; + + // 模糊搜索结果 + private FuzzySearchResultObj fuzzySearchResultObj; + + /* + * 获取所有排行榜 + * @param 无 + * @return AllRankingObj + */ + + public AllRankingObj getAllRankingObj() { + Response response = null; + try { + response = ApiService.getAllRanking().execute(); + allRankingObj = response.body(); + } catch (IOException e) { + e.printStackTrace(); + } + return allRankingObj; + } + + /* + * 获取单一排行榜 + * @param rankingId String _id 周榜、monthRank 月榜、totalRank 总榜 可从AllRankingObj中获得 + * @return SingleRankingObj + */ + + public SingleRankingObj getSingleRankingObj(String rankingId) { + Response response = null; + try { + response = ApiService.getSingleRanking(rankingId).execute(); + singleRankingObj = response.body(); + } catch (IOException e) { + e.printStackTrace(); + } + return singleRankingObj; + } + + /* + * 获取一级分类 + * @param 无 + * @return ClassificationObj1 + */ + + public ClassificationObj1 getClassification1() { + Response response = null; + try { + response = ApiService.getClassificationObj1().execute(); + classificationObj1 = response.body(); + } catch (IOException e) { + e.printStackTrace(); + } + return classificationObj1; + } + + /* + * 获取二级分类 + * @param 无 + * @return ClassificationObj2 + */ + + public ClassificationObj2 getClassification2() { + Response response = null; + try { + response = ApiService.getClassificationObj2().execute(); + classificationObj2 = response.body(); + } catch (IOException e) { + e.printStackTrace(); + } + return classificationObj2; + } + + /* + * 获取主题书单列表 + * @param type String hot(热门)、new(新书)、reputation(好评)、over(完结) + * major String 玄幻 可以从一级分类获得 + * start String 起始位置,从0开始 + * limit String 获取数量限制 20 + * gender String 性别 male、female + * @return CategoryObj + * 示例 bookService.getBooksByCategoty("hot", "玄幻", "0", "20", "male"); + */ + + public CategoryObj getBooksByCategoty(String type, String major, int start, int limit, String gender) { + Response response = null; + try { + response = ApiService.getBooksByCategory(type, major, start, limit, gender).execute(); + categoryObj = response.body(); + } catch (IOException e) { + e.printStackTrace(); + } + return categoryObj; + } + + public BookObj getBookById(String bookid) { + Response response = null; + try { + response = ApiService.getBookById(bookid).execute(); + bookObj = response.body(); + } catch (IOException e) { + e.printStackTrace(); + } + return bookObj; + } + + /* + * 获取章节列表 + * @param String bookid 书籍id,可从CategoryObj中获得 + * @return CptListObj 章节列表对象 + */ + + public CptListObj getChaptersByBookId(String bookid) { + Response response = null; + try { + response = ApiService.getChapters(bookid).execute(); + cptListObj = response.body(); + } catch (IOException e) { + e.printStackTrace(); + } + return cptListObj; + } + + /* + * 获取章节内容 + * @param String link 章节链接,可从CptListObj中获得 + * @return ChapterObj 章节对象 + */ + + public ChapterObj getChapterByLink(String link) { + Response response = null; + try { + response = ChapterService.getChapter(link).execute(); + chapterObj = response.body(); + } catch (IOException e) { + e.printStackTrace(); + } + return chapterObj; + } + + /* + * 获取书籍搜索结果 + * @param query String 关键词 + * start 结果开始位置 + * limit 结果最大数量 + * @return SearchResultObj 搜索结果对象 + */ + public SearchResultObj getSearchResultObj(String query, int start, int limit) { + Response response = null; + try { + response = ApiService.getSearchResult(query, start, limit).execute(); + searchResultObj = response.body(); + } catch (IOException e) { + e.printStackTrace(); + } + return searchResultObj; + } + + /* + * 获取书籍模糊搜索结果 + * @param name String 关键词 + * @return FuzzyResultObjs 模糊搜索结果对象 + */ + public FuzzySearchResultObj getFuzzySearchResult(String name) { + Response response = null; + try { + response = FuzzySearchService.getFuzzySearchResult(name).execute(); + fuzzySearchResultObj = response.body(); + } catch (IOException e) { + e.printStackTrace(); + } + return fuzzySearchResultObj; + } + + /* + * 获取图片 + * @param path + * @return Bitmap 图片 + */ + public Bitmap getImg(String path) { + Response response = null; + Bitmap bitmap = null; + try { + response = StaticsService.getImg(path).execute(); + InputStream is = response.body(); + bitmap = BitmapFactory.decodeStream(is); + } catch (IOException e) { + e.printStackTrace(); + } + return bitmap; + } + +} \ No newline at end of file diff --git a/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Service/UrlService.java b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Service/UrlService.java new file mode 100644 index 0000000..853a46a --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/java/com/example/Service/UrlService.java @@ -0,0 +1,116 @@ +package com.example.Service; + +import java.io.InputStream; + +import com.example.Object.AllRankingObj; +import com.example.Object.BookObj; +import com.example.Object.CategoryObj; +import com.example.Object.ChapterObj; +import com.example.Object.ClassificationObj1; +import com.example.Object.ClassificationObj2; +import com.example.Object.CptListObj; +import com.example.Object.FuzzySearchResultObj; +import com.example.Object.SearchResultObj; +import com.example.Object.SingleRankingObj; +import retrofit2.Call; +import retrofit2.http.GET; +import retrofit2.http.Path; +import retrofit2.http.Query; + +public interface UrlService { + /* + * 获取所有排行榜 + * @param 无 + * @return Call + */ + @GET("/ranking/gender") + Call getAllRanking(); + + /* + * 获取单一排行榜 + * @param rankingId String _id 周榜、monthRank 月榜、totalRank 总榜 + * @return Call + */ + @GET("/ranking/{rankingId}") + Call getSingleRanking(@Path("rankingId") String rankingId); + + + /* + * 获取一级分类 + * @param 无 + * @return Call + */ + @GET("/cats/lv2/statistics") + Call getClassificationObj1(); + + /* + * 获取二级分类 + * @param 无 + * @return Call + */ + @GET("/cats/lv2") + Call getClassificationObj2(); + + /* + * 获取主题书单列表 + * @param type String hot(热门)、new(新书)、reputation(好评)、over(完结) + * major String 玄幻 + * start String 起始位置,从0开始 + * limit String 限制获取数量 20 + * gender String 性别 male、female + * @return Call + */ + @GET("/book/by-categories") + Call getBooksByCategory(@Query("type") String type, @Query("major") String major, @Query("start") int start, @Query("limit") int limit, @Query("gender") String gender); + + /* + * 获取书籍详情 + * @param bookid String 书籍id + * @return Call 书籍对象 + */ + @GET("/book/{bookid}") + Call getBookById(@Path("bookid") String bookid); + + /* + * 获取章节列表 + * @param bookid 书籍id + * @return Call + */ + @GET("/mix-atoc/{bookid}?view=chapters") + Call getChapters(@Path("bookid") String bookid); + + /* + * 获取章节内容 + * @param link 章节链接 + * @return Call 章节对象 + */ + @GET("/chapter/{link}") + Call getChapter(@Path("link") String link); + + /* + * 获取书籍搜索结果 + * @param name String 书名 + * start int 结果开始位置 + * limit int 结果数量限制 + * @return Call 搜索结果对象 + */ + @GET("/book/fuzzy-search") + Call getSearchResult(@Query("query") String query, @Query("start") int start, @Query("limit") int limit); + + /* + * 获取模糊搜索结果 + * @param name 关键字 + * @return Call 模糊搜索结果对象 + */ + @GET("/novelSearchApi") + Call getFuzzySearchResult(@Query("name") String name); + + /* + * 获取图片 + * @param path + * @return Call 图片 + */ + @GET("{path}") + Call getImg(@Path("path") String path); + +} diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/buttonstyle.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/buttonstyle.xml new file mode 100644 index 0000000..655f7df --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/buttonstyle.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/card_edge.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/card_edge.xml new file mode 100644 index 0000000..2ea983b --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/card_edge.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/ic_launcher_background.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/ic_launcher_background.xml new file mode 100644 index 0000000..d5fccc5 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..c7bd21d --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/selector_tab_text_color.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/selector_tab_text_color.xml new file mode 100644 index 0000000..855c238 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/selector_tab_text_color.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/textview_border_blue.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/textview_border_blue.xml new file mode 100644 index 0000000..a0277ab --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/textview_border_blue.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/textview_border_green.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/textview_border_green.xml new file mode 100644 index 0000000..46dbae0 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable-v24/textview_border_green.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable/buttonstyle.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/buttonstyle.xml new file mode 100644 index 0000000..655f7df --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/buttonstyle.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable/card_edge.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/card_edge.xml new file mode 100644 index 0000000..2ea983b --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/card_edge.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable/ic_launcher_background.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..d5fccc5 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable/ic_launcher_foreground.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..c7bd21d --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable/selector_tab_text_color.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/selector_tab_text_color.xml new file mode 100644 index 0000000..855c238 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/selector_tab_text_color.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable/textview_border_blue.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/textview_border_blue.xml new file mode 100644 index 0000000..a0277ab --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/textview_border_blue.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/drawable/textview_border_green.xml b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/textview_border_green.xml new file mode 100644 index 0000000..46dbae0 --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/res/drawable/textview_border_green.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/202014040130tangjiefeng_Reader/app/src/main/res/layout/activity_book_detail.xml b/202014040130tangjiefeng_Reader/app/src/main/res/layout/activity_book_detail.xml new file mode 100644 index 0000000..2b91e6a --- /dev/null +++ b/202014040130tangjiefeng_Reader/app/src/main/res/layout/activity_book_detail.xml @@ -0,0 +1,280 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +