小说阅读软件书架界面和历史记录界面

1、引言

终于修改到书架界面和历史阅读记录界面了,修改完这两个界面就算完成一大半了,这两个界面其实都差不多,代码逻辑都一样,因此后面也会只展示书架界面的代码,历史阅读记录界面就展示效果图就行了。

2、实现代码

2.1、书架界面主布局

java 复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/rl_shelf"
    android:background="#ffffff">
    <RelativeLayout
        android:id="@+id/rl_book_top"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#00000000"
        android:layout_marginTop="10dp">
        <TextView
            android:id="@+id/tv_book"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginVertical="10dp"
            android:layout_marginLeft="10dp"
            android:text="书架"
            android:textColor="#303030"
            android:textSize="20sp"
            android:textStyle="bold" />
        <ImageView
            android:id="@+id/iv_search"
            android:layout_width="18dp"
            android:layout_height="18dp"
            android:layout_marginRight="35dp"
            android:layout_centerVertical="true"
            android:layout_alignParentRight="true"
            android:background="@drawable/search_shelf"/>
        <TextView
            android:id="@+id/tv_exit"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:layout_marginRight="35dp"
            android:text="退出管理"
            android:textColor="#303030"
            android:visibility="gone"
            android:layout_centerVertical="true"
            android:layout_alignParentRight="true"/>
    </RelativeLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/rl_book_top"
        android:orientation="vertical">
        <ImageView
            android:id="@+id/iv_shelf_line"
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="#c5c5c5"/>
        <GridView
            android:id="@+id/gv_shelf"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginTop="15dp"
            android:verticalSpacing="10dp"
            android:numColumns="3">
        </GridView>
    </LinearLayout>
    <RelativeLayout
        android:id="@+id/Rl_book_bottom"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#f5f5f5"
        android:visibility="gone"
        android:layout_alignParentBottom="true">
        <TextView
            android:id="@+id/tv_book_select"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="全选"
            android:textSize="20sp"
            android:layout_marginLeft="15dp"
            android:layout_marginVertical="15dp"
            android:layout_centerVertical="true"
            android:textColor="#606060"/>
        <TextView
            android:id="@+id/tv_book_delete"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:text="删除"
            android:textSize="20sp"
            android:layout_marginRight="15dp"
            android:layout_centerVertical="true"
            android:textColor="#ff0000"/>
    </RelativeLayout>
</RelativeLayout>

2.2、书架界面实际布局

java 复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff">
    <ImageView
        android:id="@+id/iv_grid"
        android:layout_width="90dp"
        android:layout_height="125dp"
        android:layout_centerHorizontal="true"
        android:background="@drawable/empty"/>
    <LinearLayout
        android:id="@+id/ll_content"
        android:layout_width="100dp"
        android:layout_below="@+id/iv_grid"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:gravity="center_horizontal">
        <TextView
            android:id="@+id/tv_grid"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="15sp"
            android:layout_marginTop="5dp"
            android:textColor="#303030"
            android:text="书名"/>
    </LinearLayout>
    <ImageView
        android:id="@+id/iv_select"
        android:layout_width="25dp"
        android:layout_height="25dp"
        android:layout_alignBottom="@+id/iv_grid"
        android:layout_alignRight="@+id/iv_grid"
        android:layout_marginRight="5dp"
        android:layout_marginBottom="5dp"
        android:visibility="gone"
        android:background="@drawable/checkbox_ic_default"/>
</RelativeLayout>

2.3、逻辑代码

在这里其实还要配合上次阅读界面那里添加书架和历史记录查看,但上次那里没修改,不过没太大变化,可以参考上次阅读界面那里。

java 复制代码
package xyz.dritrtj.read.fragment;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;

import xyz.dritrtj.read.R;
import xyz.dritrtj.read.base.BaseFragment;
import xyz.dritrtj.read.data.Title;
import xyz.dritrtj.read.ui.MainActivity;
import xyz.dritrtj.read.ui.ReadActivity;
import xyz.dritrtj.read.ui.SearchActivity;
import xyz.dritrtj.read.utils.DBHelper;
import xyz.dritrtj.read.utils.SetUiSize;

import java.util.ArrayList;
import java.util.List;
/**
 * 书架的展示页面
 */
public class BookShelfFragment extends BaseFragment implements View.OnClickListener {
    public static BookShelfFragment fragment;
    private RelativeLayout rl_shelf;
    private RelativeLayout rl_book_top;
    private TextView tv_book;
    private ImageView iv_search;
    private TextView tv_exit;
    private ImageView iv_shelf_line;
    private GridView gv_shelf;
    private RelativeLayout Rl_book_bottom;
    private TextView tv_book_select;
    private TextView tv_book_delete;
    @Override
    protected View initView() {
        View view=View.inflate(context, R.layout.book_shelf_fragment,null);
        rl_shelf = view.findViewById(R.id.rl_shelf);
        rl_book_top = view.findViewById(R.id.rl_book_top);
        tv_book = view.findViewById(R.id.tv_book);
        iv_search = view.findViewById(R.id.iv_search);
        iv_search.setOnClickListener(this);
        tv_exit = view.findViewById(R.id.tv_exit);
        tv_exit.setOnClickListener(this);
        iv_shelf_line = view.findViewById(R.id.iv_shelf_line);
        gv_shelf = view.findViewById(R.id.gv_shelf);
        Rl_book_bottom = view.findViewById(R.id.Rl_book_bottom);
        tv_book_select = view.findViewById(R.id.tv_book_select);
        tv_book_select.setOnClickListener(this);
        tv_book_delete = view.findViewById(R.id.tv_book_delete);
        tv_book_delete.setOnClickListener(this);
        fragment=this;
        return view;
    }
    /**
     * 重新设置尺寸
     */
    private void setView(){
        SetUiSize.setMarginTopRelative(rl_book_top,10);
        SetUiSize.setTextViewSize(tv_book,20);
        SetUiSize.setMarginLeftRelative(tv_book,10);
        SetUiSize.setMarginVerticalRelative(tv_book,10);
        SetUiSize.setWidthRelative(iv_search,18);
        SetUiSize.setHeightRelative(iv_search,18);
        SetUiSize.setMarginRightRelative(iv_search,35);
        SetUiSize.setTextViewSize(tv_exit,20);
        SetUiSize.setMarginRightRelative(tv_exit,35);
        SetUiSize.setHeightLinear(iv_shelf_line,1);
        SetUiSize.setMarginTopLinear(gv_shelf,15);
        SetUiSize.setTextViewSize(tv_book_select,20);
        SetUiSize.setMarginLeftRelative(tv_book_select,15);
        SetUiSize.setMarginVerticalRelative(tv_book_select,15);
        SetUiSize.setTextViewSize(tv_book_delete,20);
        SetUiSize.setMarginRightRelative(tv_book_delete,15);
        rl_shelf.setVisibility(View.VISIBLE);
    }
    @Override
    protected void initData() {
        super.initData();
        setView();
        query();
    }
    @SuppressLint("NonConstantResourceId")
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.iv_search://搜索
                startActivity(new Intent(getActivity(), SearchActivity.class));
                break;
            case R.id.tv_exit://退出管理
                handler.sendEmptyMessage(1);//刷新书架,取消选择
                break;
            case R.id.tv_book_select://全选和取消全选
                isCheck();
                break;
            case R.id.tv_book_delete://从书架中删除小说
                delete();
                break;
        }
    }
    /**
     * 判断是否选中
     */
    private void isCheck() {
        boolean flag;
        if (count()){
            flag=true;
            tv_book_select.setText("取消全选");
        }else {
            flag=false;
            tv_book_select.setText("全选");
        }
        for (int i = 0; i < list.size(); i++) {
            list.get(i).select=flag;
        }
        adapter.notifyDataSetChanged();
    }
    private List<Title> list=new ArrayList<>();
    private ShelfAdapter adapter=new ShelfAdapter();
    public class ShelfAdapter extends BaseAdapter{
        @Override
        public int getCount() {
            return list.size();
        }
        @Override
        public Object getItem(int position) {
            return list.get(position);
        }
        @Override
        public long getItemId(int position) {
            return position;
        }
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            Holder holder=null;
            if (convertView==null){
                convertView=View.inflate(getActivity(),R.layout.grid_item_shelf,null);
                holder=new Holder();
                holder.iv_grid = convertView.findViewById(R.id.iv_grid);
                SetUiSize.setWidthRelative(holder.iv_grid,90);
                SetUiSize.setHeightRelative(holder.iv_grid,125);
                holder.ll_content = convertView.findViewById(R.id.ll_content);
                SetUiSize.setWidthRelative(holder.ll_content,100);
                holder.tv_grid = convertView.findViewById(R.id.tv_grid);
                SetUiSize.setTextViewSize(holder.tv_grid,15);
                SetUiSize.setMarginTopLinear(holder.tv_grid,5);
                holder.iv_select = convertView.findViewById(R.id.iv_select);
                SetUiSize.setWidthRelative(holder.iv_select,25);
                SetUiSize.setHeightRelative(holder.iv_select,25);
                SetUiSize.setMarginRightRelative(holder.iv_select,5);
                SetUiSize.setMarginBottomRelative(holder.iv_select,5);
                convertView.setTag(holder);
            }else {
                holder= (Holder) convertView.getTag();
            }
            Title title = list.get(position);
            getBitmapFromSd(position);
            holder.iv_grid.setImageBitmap(title.bitmap);
            holder.tv_grid.setText(title.name);
            if (MainActivity.activity.exit){
                if (title.select){
                    holder.iv_select.setBackgroundResource(R.drawable.checkbox_ic_selected);
                }else {
                    holder.iv_select.setBackgroundResource(R.drawable.checkbox_ic_default);
                }
                holder.iv_select.setVisibility(View.VISIBLE);
            }else {
                holder.iv_select.setVisibility(View.GONE);
            }
            return convertView;
        }
        private class Holder{
            public ImageView iv_grid;
            public TextView tv_grid;
            public ImageView iv_select;
            public LinearLayout ll_content;
        }
    }
    /**
     * 查询书架数据
     */
    @SuppressLint("Range")
    private void query(){
        list.clear();
        DBHelper dbHelper=new DBHelper(getActivity(),1);
        SQLiteDatabase database = dbHelper.getReadableDatabase();
        String sql="CREATE TABLE IF NOT EXISTS shelf(\n" +
                "\tbook VARCHAR(20) NOT NULL,\n" +
                "\tauthor VARCHAR(30) NOT NULL,\n" +
                "\tintroduce VARCHAR(200),\n" +
                "\tpage VARCHAR(100),\n" +
                "\torigin VARCHAR(100) NOT NULL,\n" +
                "\tprogress INTEGER NOT NULL\n" +
                ");";
        database.execSQL(sql);
        Cursor cursor = database.query("shelf", null, null,
                null, null, null, null);
        Title title;
        while (cursor.moveToNext()){
            title = new Title();
            title.iv_back=R.drawable.empty;
            title.name=cursor.getString(cursor.getColumnIndex("book"));//书名
            title.author=cursor.getString(cursor.getColumnIndex("author"));//作者
            title.path=cursor.getString(cursor.getColumnIndex("origin"));
            title.index=cursor.getInt(cursor.getColumnIndex("progress"));
            title.imageName=cursor.getString(cursor.getColumnIndex("page"));
            list.add(title);
        }
        cursor.close();
        database.close();
        gv_shelf.setAdapter(adapter);
        gv_shelf.setOnItemClickListener((parent, view, position, id) -> {
            if (MainActivity.activity.exit){
                list.get(position).select=!list.get(position).select;
                count();
                adapter.notifyDataSetChanged();
            }else {
                Intent intent=new Intent(getActivity(), ReadActivity.class);
                intent.putExtra("url",list.get(position).path);//章节页面
                intent.putExtra("name",list.get(position).name);//书名
                intent.putExtra("author",list.get(position).author);//作者
                intent.putExtra("code","1");//表示是书架来源
                intent.putExtra("page",list.get(position).index+"");//表示是阅读进度
                startActivity(intent);
            }
        });
        gv_shelf.setOnItemLongClickListener((parent, view, position, id) -> {
            if (!MainActivity.activity.exit){//表示没有选中状态
                MainActivity.activity.exit=true;//设置为选中状态
                list.get(position).select=true;
                iv_search.setVisibility(View.GONE);//隐藏搜索
                tv_exit.setVisibility(View.VISIBLE);//显示退出管理
                MainActivity.activity.rg_main.setVisibility(View.GONE);//隐藏底部导航按钮
                Rl_book_bottom.setVisibility(View.VISIBLE);//显示底部按钮
                count();
                adapter.notifyDataSetChanged();//刷新视图
                return true;
            }
            return false;
        });
    }
    @SuppressLint("HandlerLeak")
    public Handler handler=new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case 0://刷新书架
                {
                    query();
                }
                    break;
                case 1://刷新书架,取消选择
                {
                    refresh();
                }
                    break;
                case 2://删除书架
                {
                    refresh();
                    query();
                }
                    break;
            }
        }
    };
    //刷新书架,取消选择
    private void refresh() {
        if (list.size()>0){
            int i = 0;
            for (; i < list.size(); i++) {
                list.get(i).select=false;
            }
        }
        MainActivity.activity.exit=false;
        tv_exit.setVisibility(View.GONE);//隐藏退出管理
        iv_search.setVisibility(View.VISIBLE);//显示搜索
        Rl_book_bottom.setVisibility(View.GONE);//隐藏底部按钮
        MainActivity.activity.rg_main.setVisibility(View.VISIBLE);//显示底部导航按钮
        adapter.notifyDataSetChanged();//刷新视图
    }
    private void getBitmapFromSd(int position) {
        // /storage/sdcard/Android/data/packageName/files/
        String filesPath = getActivity().getExternalFilesDir(null).getAbsolutePath();
        String filePath = filesPath+"/"+list.get(position).imageName;
        list.get(position).bitmap=BitmapFactory.decodeFile(filePath);
    }
    /**
     * 统计判断是否修改选择按钮展示文字
     */
    private boolean count(){
        int i = 0;
        int flag=0;
        for (; i < list.size(); i++) {
            if (list.get(i).select){
                flag++;
            }
        }
        if (flag<list.size()){
            tv_book_select.setText("全选");
            return true;
        }else if (flag==list.size()){
            tv_book_select.setText("取消全选");
        }
        return false;
    }
    /**
     * 移除小说,并重新加载暑假数据
     */
    private void delete(){
        DBHelper dbHelper=new DBHelper(getActivity(),1);
        SQLiteDatabase database = dbHelper.getReadableDatabase();
        String sql="CREATE TABLE IF NOT EXISTS shelf(\n" +
                "\tbook VARCHAR(20) NOT NULL,\n" +
                "\tauthor VARCHAR(30) NOT NULL,\n" +
                "\tintroduce VARCHAR(200),\n" +
                "\tpage VARCHAR(100),\n" +
                "\torigin VARCHAR(100) NOT NULL,\n" +
                "\tprogress INTEGER NOT NULL\n" +
                ");";
        database.execSQL(sql);
        int i = 0;
        for (; i < list.size(); i++) {
            if (list.get(i).select){
                database.delete("shelf","book = ? AND author = ?",
                        new String[]{list.get(i).name,list.get(i).author});
            }
        }
        database.close();
        //本地保存的图片不删除,用于后面优化复用图片
        handler.sendEmptyMessage(2);
    }
}

3、效果演示

3.1、书架效果

下图是正常情况下书架效果。

下图是长按后将小说从书架移除的效果。

3.2、历史阅读记录效果

相关推荐
闲暇部落19 分钟前
‌Kotlin中的?.和!!主要区别
android·开发语言·kotlin
诸神黄昏EX2 小时前
Android 分区相关介绍
android
大白要努力!3 小时前
android 使用SQLiteOpenHelper 如何优化数据库的性能
android·数据库·oracle
Estar.Lee3 小时前
时间操作[取当前北京时间]免费API接口教程
android·网络·后端·网络协议·tcp/ip
Winston Wood4 小时前
Perfetto学习大全
android·性能优化·perfetto
Dnelic-7 小时前
【单元测试】【Android】JUnit 4 和 JUnit 5 的差异记录
android·junit·单元测试·android studio·自学笔记
Eastsea.Chen9 小时前
MTK Android12 user版本MtkLogger
android·framework
长亭外的少年16 小时前
Kotlin 编译失败问题及解决方案:从守护进程到 Gradle 配置
android·开发语言·kotlin
建群新人小猿19 小时前
会员等级经验问题
android·开发语言·前端·javascript·php
1024小神20 小时前
tauri2.0版本开发苹果ios和安卓android应用,环境搭建和最后编译为apk
android·ios·tauri