1.效果预览
1.1.效果预览,从问答列表开始
前面实现了从列表到内容。
这里主要讲解从内容到详情。
点击每一个回答内容,进入回答详情页面。
1.2.触发的点击事件
在WendaContentViewBinder中,设置item点击事件:
WendaDetailActivity.lauch(bean);
2.问答详情的活动页面
2.1.源代码
public class WendaDetailActivity extends BaseActivity { private static final String TAG = "WendaDetailActivity"; public static void launch(WendaContentBean.AnsListBean bean) { InitApp.AppContext.startActivity(new Intent(InitApp.AppContext, WendaDetailActivity.class) .putExtra(TAG, bean) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_wenda_content_view); getSupportFragmentManager().beginTransaction() .replace(R.id.container, WendaDetailFragment.newInstance(getIntent().getParcelableExtra(TAG))) .commit(); } }
2.2.需要的布局
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:andro>
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/viewBackground"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:layout="@layout/fragment_news_tab"
>
</FrameLayout>
2.3.清单中活动配置
<activity android:name=".module.wenda.detail.WendaDetailActivity" android:configChanges="orientation|screenSize|uiMode" android:label="@string/title_wenda_detail" android:theme="@style/AppTheme.NoActionBar.Slidable"/>
3.问答详情页面片段
3.1.需要实现的底层接口
public interface IWendaDetail { interface View extends IBaseListView<Presenter> { /** * 加载网页 */ void onSetWebView(String baseUrl, boolean flag); /** * 请求数据 */ void onLoadData(); } interface Presenter extends IBasePresenter { /** * 请求数据 */ void doLoadData(String url); /** * 加载评论 */ void doLoadComment(String... ansId); /** * 加载更多评论 */ void doLoadMoreComment(); /** * 设置适配器 */ void doSetAdapter(List<NewsCommentBean.DataBean.CommentBean> list); /** * 加载完毕 */ void doShowNoMore(); } }
3.2.片段源代码
public class WendaDetailFragment extends BaseFragment<IWendaDetail.Presenter> implements IWendaDetail.View{ private static final String TAG = "WendaDetailFragment"; private WendaContentBean.AnsListBean bean = null; private String url; private String title; private String shareTitle; private WebView webView; private NestedScrollView scrollView; private ContentLoadingProgressBar progressBar; private TextView tv_title; private CircleImageView iv_user_avatar; private TextView tv_user_name; private RecyclerView recyclerView; private LinearLayout header_layout; private SwipeRefreshLayout swipeRefreshLayout; private MultiTypeAdapter adapter; private boolean canLoadMore; private Items oldItems = new Items(); public static WendaDetailFragment newInstance(Parcelable bean) { Bundle args = new Bundle(); args.putParcelable(TAG, bean); WendaDetailFragment fragment = new WendaDetailFragment(); fragment.setArguments(args); return fragment; } @Override protected void initData() { bean = getArguments().getParcelable(TAG); if (null == this.bean) { onShowNetError(); return; } url = bean.getShare_data().getShare_url(); onLoadData(); ImageLoader.loadCenterCrop(getActivity(), bean.getUser().getAvatar_url(), iv_user_avatar, R.color.viewBackground); tv_title.setText(bean.getTitle()); tv_user_name.setText(bean.getUser().getUname()); shareTitle = bean.getShare_data().getTitle(); header_layout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { WendaContentActivity.launch(bean.getQid()); } }); } @Override public void onLoadData() { presenter.doLoadData(url); } @Override public void setPresenter(IWendaDetail.Presenter presenter) { if (null == presenter) { this.presenter = new WendaDetailPresenter(this); } } @Override public void onSetAdapter(List<?> list) { Items newItems = new Items(list); newItems.add(new LoadingBean()); DiffCallback.notifyDataSetChanged(oldItems, newItems, DiffCallback.NEWS_COMMENT, adapter); oldItems.clear(); oldItems.addAll(newItems); canLoadMore = true; recyclerView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)); } @Override protected int attachLayoutId() { return R.layout.fragment_wenda_detail; } @Override protected void initView(View view) { Toolbar toolbar = view.findViewById(R.id.toolbar); initToolBar(toolbar, true, getString(R.string.title_wenda_detail)); toolbar.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { scrollView.smoothScrollTo(0, 0); } }); webView = view.findViewById(R.id.webview); initWebClient(); header_layout = view.findViewById(R.id.header_layout); header_layout.setBackgroundColor(SettingUtil.getInstance().getColor()); tv_title = view.findViewById(R.id.tv_title); iv_user_avatar = view.findViewById(R.id.iv_user_avatar); tv_user_name = view.findViewById(R.id.tv_user_name); scrollView = view.findViewById(R.id.scrollView); scrollView.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() { @Override public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { onHideLoading(); } }); scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() { @Override public void onScrollChanged() { View view = scrollView.getChildAt(scrollView.getChildCount() - 1); int diff = (view.getBottom() - (scrollView.getHeight() + scrollView.getScrollY())); if (diff == 0) { canLoadMore = false; presenter.doLoadMoreComment(); } } }); swipeRefreshLayout = view.findViewById(R.id.refresh_layout); swipeRefreshLayout.setColorSchemeColors(SettingUtil.getInstance().getColor()); swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { swipeRefreshLayout.post(new Runnable() { @Override public void run() { swipeRefreshLayout.setRefreshing(true); } }); presenter.doLoadData(url); } }); progressBar = view.findViewById(R.id.pb_progress); int color = SettingUtil.getInstance().getColor(); progressBar.getIndeterminateDrawable().setColorFilter(color, PorterDuff.Mode.MULTIPLY); progressBar.show(); recyclerView = view.findViewById(R.id.recycler_view); recyclerView.setHasFixedSize(true); // 禁止嵌套滚动 recyclerView.setNestedScrollingEnabled(false); adapter = new MultiTypeAdapter(oldItems); Register.registerNewsCommentItem(adapter); recyclerView.setAdapter(adapter); setHasOptionsMenu(true); } @Override public void onSetWebView(String url, boolean flag) { // 是否解析网页成功 if (flag) { webView.loadDataWithBaseURL(null, url, "text/html", "utf-8", null); presenter.doLoadComment(bean.getAnsid()); } else { webView.loadUrl(url); } } @SuppressLint("SetJavaScriptEnabled") private void initWebClient() { WebSettings settings = webView.getSettings(); settings.setJavaScriptEnabled(true); // 缩放,设置为不能缩放可以防止页面上出现放大和缩小的图标 settings.setBuiltInZoomControls(false); // 缓存 settings.setCacheMode(WebSettings.LOAD_DEFAULT); // 开启DOM storage API功能 settings.setDomStorageEnabled(true); // 开启application Cache功能 settings.setAppCacheEnabled(true); // 判断是否为无图模式 settings.setBlockNetworkImage(SettingUtil.getInstance().getIsNoPhotoMode()); // 不调用第三方浏览器即可进行页面反应 webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (!TextUtils.isEmpty(url)) { view.loadUrl(url); } return true; } @Override public void onPageFinished(WebView view, String url) { onHideLoading(); super.onPageFinished(view, url); } }); webView.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View view, int i, KeyEvent keyEvent) { if ((keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) { webView.goBack(); return true; } return false; } }); webView.setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { super.onProgressChanged(view, newProgress); if (newProgress >= 90) { onHideLoading(); } else { onShowLoading(); } } }); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.menu_wenda_detail, menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.action_wenda_share) { IntentAction.send(getActivity(), shareTitle + "\n" + url); } return super.onOptionsItemSelected(item); } @Override public void onShowNoMore() { getActivity().runOnUiThread(new Runnable() { @Override public void run() { if (oldItems.size() > 0) { Items newItems = new Items(oldItems); newItems.remove(newItems.size() - 1); newItems.add(new LoadingEndBean()); adapter.setItems(newItems); adapter.notifyDataSetChanged(); } else if (oldItems.size() == 0) { oldItems.add(new LoadingEndBean()); adapter.setItems(oldItems); adapter.notifyDataSetChanged(); } canLoadMore = false; } }); } @Override public void onShowLoading() { progressBar.show(); } @Override public void onHideLoading() { progressBar.hide(); swipeRefreshLayout.post(new Runnable() { @Override public void run() { swipeRefreshLayout.setRefreshing(false); } }); } @Override public void onShowNetError() { Snackbar.make(scrollView, R.string.network_error, Snackbar.LENGTH_SHORT).show(); getActivity().runOnUiThread(new Runnable() { @Override public void run() { adapter.setItems(new Items()); adapter.notifyDataSetChanged(); canLoadMore = false; } }); } }
3.3.新建实例。
传进去一个bean类。
传出去一个片段。
3.4.初始化视图。
获取toolbar,并进行相关设置。
获取webview,设置一些交互属性。
获取头部布局,设置颜色。
获取scrollView,设置滑动监听,以及设置观察树。
获取刷新圈,设置刷新事件。
获取进度条,设置颜色。
获取recyclerView,设置适配器。
设置菜单。
3.5.重写设置WebView。
判断是否解析网页成功。
3.6.初始化webClient,设置webView的配置。
3.7.设置菜单。
3.8.重写没有更多了,重写显示加载,重写隐藏加载,重写网络错误。
3.9.重写设置适配器和设置处理器。
3.10.重写布局。
需要的布局==>fragment_wenda_detail.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/news_content_main" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <include layout="@layout/toolbar"/> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:fadeScrollbars="true" android:scrollbarFadeDuration="1" android:scrollbars="vertical" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/refresh_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v4.widget.NestedScrollView android:id="@+id/scrollView" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:id="@+id/header_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/selectableItemBackground" android:foreground="?attr/selectableItemBackground" android:orientation="vertical"> <TextView android:id="@+id/tv_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:ellipsize="end" android:maxLines="2" android:padding="16dp" android:textAppearance="@style/TextAppearance.AppCompat.Title" android:textColor="@color/White" tools:text="都说床头不能朝西,有什么说法吗?"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/viewBackground" android:gravity="center_vertical" android:padding="8dp"> <com.jasonjan.headnews.widget.CircleImageView android:id="@+id/iv_user_avatar" android:layout_width="36dp" android:layout_height="36dp" android:scaleType="centerCrop" android:src="@color/Black" /> <TextView android:id="@+id/tv_user_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="8dp" android:layout_marginStart="8dp" android:ellipsize="end" android:maxLines="1" tools:text="用户名"/> </LinearLayout> <View android:id="@+id/divider" android:layout_width="match_parent" android:layout_height="1px" android:background="@color/line_divider"/> <WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="wrap_content"/> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" android:fadeScrollbars="true" android:scrollbarFadeDuration="1" android:scrollbars="vertical" app:layoutManager="LinearLayoutManager"/> </LinearLayout> </android.support.v4.widget.NestedScrollView> </android.support.v4.widget.SwipeRefreshLayout> <android.support.v4.widget.ContentLoadingProgressBar android:id="@+id/pb_progress" style="?android:attr/progressBarStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true"/> </RelativeLayout> </android.support.design.widget.CoordinatorLayout>
预览图片: