Commit fa55e8c8 by 段启岩

博客详情完成

parent 04cbf6e7
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no">
<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="github-markdown.min.css">
<link href="default.min.css" rel="stylesheet"/>
<style>
.article__content {
padding: 0 10px;
* {
margin: 0;
padding: 0;
}
body{
padding: 0px;
}
.hljs {
// background: #fcfcfc;
}
</style>
</head>
......@@ -21,8 +29,11 @@
function loadArticleContent(content) {
document.getElementById("Article_Content").innerHTML = content;
hljs.initHighlightingOnLoad();
hljs.initLineNumbersOnLoad();
hljs.initHighlighting.called = false;
hljs.configure({
classPrefix:'',
});
hljs.initHighlighting();
}
</script>
</body>
......
package cn.yunliyunwai.beyondclouds.data.model;
import java.util.Date;
public class Article {
private String title;
private String articleAbstract;
private Integer commentNumber;
private Integer praiseNumber;
private Integer viewNumber;
private String category;
private boolean praised;
private Date createTime;
private boolean followedAuthor;
private UserInfo author;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getArticleAbstract() {
return articleAbstract;
}
public void setArticleAbstract(String articleAbstract) {
this.articleAbstract = articleAbstract;
}
public Integer getCommentNumber() {
return commentNumber;
}
public void setCommentNumber(Integer commentNumber) {
this.commentNumber = commentNumber;
}
public Integer getPraiseNumber() {
return praiseNumber;
}
public void setPraiseNumber(Integer praiseNumber) {
this.praiseNumber = praiseNumber;
}
public Integer getViewNumber() {
return viewNumber;
}
public void setViewNumber(Integer viewNumber) {
this.viewNumber = viewNumber;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public boolean isFollowedAuthor() {
return followedAuthor;
}
public void setFollowedAuthor(boolean followedAuthor) {
this.followedAuthor = followedAuthor;
}
public UserInfo getAuthor() {
return author;
}
public void setAuthor(UserInfo author) {
this.author = author;
}
}
......@@ -2,9 +2,6 @@ package cn.yunliyunwai.beyondclouds.data.model;
import java.util.Date;
import lombok.Data;
@Data
public class Blog {
private String blogId;
......@@ -20,6 +17,154 @@ public class Blog {
private String allowComment;
private String allowForward;
private String userNick;
private Integer commentNumber;
private Integer praiseNum;
private Integer viewNumber;
private boolean followedAuthor;
private Date createTime;
public String getBlogId() {
return blogId;
}
public void setBlogId(String blogId) {
this.blogId = blogId;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getCategoryId() {
return categoryId;
}
public void setCategoryId(String categoryId) {
this.categoryId = categoryId;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getBlogTitle() {
return blogTitle;
}
public void setBlogTitle(String blogTitle) {
this.blogTitle = blogTitle;
}
public String getBlogAbstract() {
return blogAbstract;
}
public void setBlogAbstract(String blogAbstract) {
this.blogAbstract = blogAbstract;
}
public String getCover() {
return cover;
}
public void setCover(String cover) {
this.cover = cover;
}
public String getOriginLink() {
return originLink;
}
public void setOriginLink(String originLink) {
this.originLink = originLink;
}
public String getContentHtml() {
return contentHtml;
}
public void setContentHtml(String contentHtml) {
this.contentHtml = contentHtml;
}
public String getViewPrivileges() {
return viewPrivileges;
}
public void setViewPrivileges(String viewPrivileges) {
this.viewPrivileges = viewPrivileges;
}
public String getAllowComment() {
return allowComment;
}
public void setAllowComment(String allowComment) {
this.allowComment = allowComment;
}
public String getAllowForward() {
return allowForward;
}
public void setAllowForward(String allowForward) {
this.allowForward = allowForward;
}
public String getUserNick() {
return userNick;
}
public void setUserNick(String userNick) {
this.userNick = userNick;
}
public Integer getCommentNumber() {
return commentNumber;
}
public void setCommentNumber(Integer commentNumber) {
this.commentNumber = commentNumber;
}
public Integer getPraiseNum() {
return praiseNum;
}
public void setPraiseNum(Integer praiseNum) {
this.praiseNum = praiseNum;
}
public Integer getViewNumber() {
return viewNumber;
}
public void setViewNumber(Integer viewNumber) {
this.viewNumber = viewNumber;
}
public boolean isFollowedAuthor() {
return followedAuthor;
}
public void setFollowedAuthor(boolean followedAuthor) {
this.followedAuthor = followedAuthor;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}
......@@ -31,4 +31,10 @@ public interface IUserRepository {
*/
LiveData<Result<UserInfo>> getUserInfo();
/**
* 获取我用户信息
* @return
*/
LiveData<Result<UserInfo>> getUserInfo(String userId);
}
......@@ -37,4 +37,9 @@ public class UserRepositoryImpl implements IUserRepository {
public LiveData<Result<UserInfo>> getUserInfo() {
return userApiStore.getUserInfo();
}
@Override
public LiveData<Result<UserInfo>> getUserInfo(String userId) {
return userApiStore.getUserInfo(userId);
}
}
......@@ -10,6 +10,7 @@ import cn.yunliyunwai.beyondclouds.data.model.form.SmsLoginForm;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Path;
import retrofit2.http.Query;
public interface UserApiStore {
......@@ -36,4 +37,12 @@ public interface UserApiStore {
*/
@GET("my/baseinfo")
LiveData<Result<UserInfo>> getUserInfo();
/**
* 获取用户信息
* @param userId
* @return
*/
@GET("user/{userId}/baseinfo")
LiveData<Result<UserInfo>> getUserInfo(@Path("userId") String userId);
}
package cn.yunliyunwai.beyondclouds.ui.blog;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
......@@ -41,7 +42,9 @@ public class BlogDetailActivity extends BaseActivity<BlogDetailViewModel, Activi
@Override
protected ActivityBlogDetailBinding initDataBinding(LayoutInflater inflater) {
return ActivityBlogDetailBinding.inflate(inflater);
ActivityBlogDetailBinding binding = ActivityBlogDetailBinding.inflate(inflater);
binding.setLifecycleOwner(this);
return binding;
}
@Override
......@@ -61,7 +64,7 @@ public class BlogDetailActivity extends BaseActivity<BlogDetailViewModel, Activi
}
});
WebView webView = binding.webViewBlogDetail;
WebView webView = binding.webViewArticle;
webView.loadUrl("file:///android_asset/pages/article.html");
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
......@@ -80,12 +83,31 @@ public class BlogDetailActivity extends BaseActivity<BlogDetailViewModel, Activi
@Override
public void onChanged(BlogDetailViewModel.LoadState loadState) {
if (loadState.isLoadComplete()) {
webView.loadUrl("javascript:loadArticleContent(`" + viewModel.getBlog().getContentHtml() + "`)");
String contentHtml = viewModel.getBlog().getValue().getContentHtml().replace("\n", "<br>");
contentHtml = contentHtml.replaceAll("'", "\\\\'");
webView.loadUrl("javascript:loadArticleContent('" + contentHtml + "')");
}
}
});
viewModel.fetchBlog(blogId);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
binding.scrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
@Override
public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
int articleInfoWrapperHeight = binding.articleInfoWrapper.getHeight();
if (scrollY >= articleInfoWrapperHeight) {
if (viewModel.getBlog().getValue() != null) {
binding.toolBar.setTitle(viewModel.getBlog().getValue().getBlogTitle());
}
} else {
binding.toolBar.setTitle("");
}
}
});
}
}
}
......@@ -85,4 +85,9 @@ public class BeyondToolBar extends FrameLayout {
public void setOnRightIconClickListener(OnClickListener onClickListener) {
binding.iconRight.setOnClickListener(onClickListener);
}
public void setTitle(String title) {
this.mTitle = title;
binding.txtTitle.setText(mTitle);
}
}
......@@ -9,7 +9,9 @@ import javax.inject.Inject;
import cn.yunliyunwai.beyondclouds.data.model.Blog;
import cn.yunliyunwai.beyondclouds.data.model.Result;
import cn.yunliyunwai.beyondclouds.data.model.UserInfo;
import cn.yunliyunwai.beyondclouds.data.source.IBlogRepository;
import cn.yunliyunwai.beyondclouds.data.source.IUserRepository;
import lombok.Data;
public class BlogDetailViewModel extends ViewModel {
......@@ -25,32 +27,40 @@ public class BlogDetailViewModel extends ViewModel {
}
private IBlogRepository blogRepository;
private IUserRepository userRepository;
private Blog mBlog;
private MutableLiveData<Blog> blog = new MutableLiveData<>();
private MutableLiveData<UserInfo> userInfo = new MutableLiveData<>();
private MutableLiveData<LoadState> loadState = new MutableLiveData<>();
@Inject
public BlogDetailViewModel(IBlogRepository blogRepository) {
public BlogDetailViewModel(IBlogRepository blogRepository, IUserRepository userRepository) {
this.blogRepository = blogRepository;
this.userRepository = userRepository;
loadState.setValue(new LoadState());
}
public Blog getBlog() {
return mBlog;
public LiveData<Blog> getBlog() {
return blog;
}
public LiveData<LoadState> getLoadState() {
return loadState;
}
public LiveData<UserInfo> getUserInfo() {
return userInfo;
}
public void fetchBlog(String blogId) {
blogRepository.getBlog(blogId).observeForever(new Observer<Result<Blog>>() {
@Override
public void onChanged(Result<Blog> blogResult) {
if (blogResult.getCode() == 0) {
mBlog = blogResult.getData();
fetchUserInfo(blogResult.getData().getUserId());
blog.setValue(blogResult.getData());
LoadState state = loadState.getValue();
state.setDataLoadComplete(true);
loadState.setValue(state);
......@@ -59,6 +69,17 @@ public class BlogDetailViewModel extends ViewModel {
});
}
private void fetchUserInfo(String userId) {
userRepository.getUserInfo(userId).removeObserver(new Observer<Result<UserInfo>>() {
@Override
public void onChanged(Result<UserInfo> userInfoResult) {
if (userInfoResult.getCode() == 0) {
userInfo.setValue(userInfoResult.getData());
}
}
});
}
public void webViewPageFinished() {
LoadState state = loadState.getValue();
state.setWebViewPageLoadComplete(true);
......
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#f5f8fa" />
<corners android:radius="2dp" />
</shape>
\ No newline at end of file
......@@ -3,12 +3,10 @@
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="cn.yunliyunwai.beyondclouds.viewmodel.AuthenticationViewModel.LoginWay" />
<import type="android.text.InputType" />
<import type="android.view.View" />
<variable
name="viewModel"
type="cn.yunliyunwai.beyondclouds.viewmodel.AuthenticationViewModel" />
type="cn.yunliyunwai.beyondclouds.viewmodel.BlogDetailViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
......@@ -16,23 +14,222 @@
android:background="@color/colorWhite"
tools:context=".ui.login.LoginActivity">
<cn.yunliyunwai.beyondclouds.view.BeyondToolBar
android:id="@+id/tool_bar"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:leftIcon="@string/icon_back"
app:title="博客详情"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
android:id="@+id/tool_bar"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:leftIcon="@string/icon_back"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<WebView
android:id="@+id/web_view_blog_detail"
android:overScrollMode="never"
<ScrollView
android:id="@+id/scroll_view"
app:layout_constraintTop_toBottomOf="@id/tool_bar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_width="match_parent"
android:layout_height="0dp" />
android:layout_height="0dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:paddingStart="12dp"
android:paddingLeft="12dp"
android:paddingEnd="12dp"
android:paddingRight="12dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/article_info_wrapper"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- 博客基本信息 -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/user_info_wrapper"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/image_user_avatar"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:src="@drawable/placeholder_circle"
android:layout_width="32dp"
android:layout_height="32dp" />
<TextView
android:id="@+id/txt_user_nick"
android:text='@{viewModel.blog == null ? "作者" : viewModel.blog.userNick}'
app:layout_constraintStart_toEndOf="@id/image_user_avatar"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginStart="6dp"
android:layout_marginLeft="6dp"
android:textColor="#333333"
android:textSize="14sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/txt_user_visit_num"
android:text='@{viewModel.userInfo == null ? "人气0·粉丝0" : "人气" + viewModel.userInfo.statistics.visitedNum + "粉丝" + viewModel.userInfo.statistics.fansNum}'
app:layout_constraintStart_toEndOf="@id/image_user_avatar"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginStart="6dp"
android:layout_marginLeft="6dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#999999"
android:textSize="10sp" />
<TextView
android:id="@+id/btn_follow_user"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:text="+关注"
android:textColor="#75d098"
android:textSize="13sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/txt_title"
android:text='@{viewModel.blog == null ? "标题" : viewModel.blog.blogTitle}'
android:textColor="#333333"
android:textSize="21sp"
app:layout_constraintTop_toBottomOf="@id/user_info_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/article_extra_info"
app:layout_constraintTop_toBottomOf="@id/txt_title"
android:layout_marginTop="6dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/txt_create_time"
android:text="2020-2-17 19:53:0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:textColor="#999999"
android:textSize="10sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/article_collect_info"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<cn.yunliyunwai.beyondclouds.view.BeyondTextIcon
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="10dp"
android:textColor="#cccccc"
android:text="@string/icon_message" />
<TextView
android:id="@+id/txt_comment_number"
android:text='@{viewModel.blog == null ? "0" : viewModel.blog.commentNumber.toString()}'
android:layout_marginStart="2dp"
android:layout_marginLeft="2dp"
android:textSize="10dp"
android:textColor="#cccccc"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<cn.yunliyunwai.beyondclouds.view.BeyondTextIcon
android:layout_marginStart="12dp"
android:layout_marginLeft="12dp"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="10dp"
android:textColor="#cccccc"
android:text="@string/icon_heart" />
<TextView
android:id="@+id/txt_praise_number"
android:text='@{viewModel.blog == null ? "0" : viewModel.blog.praiseNum.toString()}'
android:layout_marginStart="2dp"
android:layout_marginLeft="2dp"
android:textSize="10dp"
android:textColor="#cccccc"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<cn.yunliyunwai.beyondclouds.view.BeyondTextIcon
android:layout_marginStart="12dp"
android:layout_marginLeft="12dp"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="10dp"
android:textColor="#cccccc"
android:text="@string/icon_eye" />
<TextView
android:id="@+id/txt_view_number"
android:text='@{viewModel.blog == null ? "0" : viewModel.blog.viewNumber.toString()}'
android:layout_marginStart="2dp"
android:layout_marginLeft="2dp"
android:textSize="10dp"
android:textColor="#cccccc"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
<TextView
android:id="@+id/txt_article_category"
android:text='@{viewModel.blog == null ? "文章类别" : viewModel.blog.category}'
android:background="@drawable/background_article_abstract"
android:layout_marginTop="10dp"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:paddingStart="10dp"
android:paddingLeft="10dp"
android:paddingEnd="10dp"
android:paddingRight="10dp"
android:textColor="#666666"
android:textSize="12sp"
app:layout_constraintTop_toBottomOf="@id/article_info_wrapper"
app:layout_constraintStart_toStartOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/txt_article_abstract"
android:text='@{viewModel.blog == null ? "" : viewModel.blog.blogAbstract}'
android:visibility='@{(viewModel.blog != null) &amp;&amp; (viewModel.blog.blogAbstract != null) ? View.VISIBLE : View.GONE}'
android:textColor="#666666"
android:textSize="12sp"
android:background="@drawable/background_article_abstract"
android:layout_marginTop="16dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:paddingStart="10dp"
android:paddingLeft="10dp"
android:paddingEnd="10dp"
android:paddingRight="10dp"
app:layout_constraintTop_toBottomOf="@id/txt_article_category"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<WebView
android:id="@+id/web_view_article"
android:layout_marginTop="25dp"
android:overScrollMode="never"
app:layout_constraintTop_toBottomOf="@id/txt_article_abstract"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
\ No newline at end of file
......@@ -11,7 +11,6 @@
android:textColor="@color/colorTextLevel4"
android:layout_marginStart="12dp"
android:layout_marginLeft="12dp"
android:background="@drawable/background_white_touchable"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
......@@ -27,6 +26,9 @@
android:textSize="16sp"
android:textColor="@color/colorTextLevel1"
app:layout_constraintBottom_toBottomOf="parent"
android:maxEms="14"
android:maxLines="1"
android:ellipsize="end"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment