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

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、历史阅读记录效果

相关推荐
千里马学框架3 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台3 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone3 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo3 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077003 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼3 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone3 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen3 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone3 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui