栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

基于Android的本地电子书阅读器的设计与实现Ebook(2)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

基于Android的本地电子书阅读器的设计与实现Ebook(2)

基于Android的本地电子书阅读器的设计与实现Ebook(2)

接着上回,我们继续分说下面步骤。
用户登录后,映入眼帘的就是我们实现阅读器的主要三个界面,分别是书架、感悟、分类。

首先这三个界面的切换是通过Fragment实现的底部导航:

activity_main_login.xml:




    
    

    

这里的menu是在res文件夹下创建的menu文件夹,具体存放图标和文字
menu_main.xml:



    
    
    

接下来是java文件MainLogin:

 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_login);

        viewPager=findViewById(R.id.viewPager);
        bottomNavigationView=findViewById(R.id.bottomNavigationView);

        //初始化fragments数组
        list=new ArrayList();
        list.add(new LoginFragment1());
        list.add(new LoginFragment2());
        list.add(new LoginFragment3());

        //设置底部导航点击和不点击时颜色
        Resources resource = getResources();
        @SuppressLint("ResourceType")
        ColorStateList csl = resource.getColorStateList(R.drawable.fgbtn);
        bottomNavigationView.setItemTextColor(csl);

        viewPager.setAdapter(new MyAdapter(getSupportFragmentManager(),list));

        //点击底部导航项,显示对应的页面
        bottomNavigationView.setOnNavigationItemSelectedListener(
                new BottomNavigationView.OnNavigationItemSelectedListener() {
                    @Override
                    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                        switch (item.getItemId()){
                            case R.id.item1:
                                viewPager.setCurrentItem(0);
                                break;
                            case R.id.item2:
                                viewPager.setCurrentItem(1);
                                break;
                            case R.id.item3:
                                viewPager.setCurrentItem(2);
                                break;
                        }
                        return true;

                    }
                });

        //页面左右滑动时,让底部的导航项和显示的页面保持一致
        viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                if(menuItem==null){
                    menuItem=bottomNavigationView.getMenu().getItem(0);
                }
                //将上次的选择设置为false,等待下次的选择
                menuItem.setChecked(false);
                menuItem=bottomNavigationView.getMenu().getItem(position);
                menuItem.setChecked(true);
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

    //作为fragment的适配器
    private class MyAdapter extends FragmentPagerAdapter
    {
        List list;
        public MyAdapter(@NonNull FragmentManager fm, List list) {
            super(fm);
            this.list=list;
        }

        @NonNull
        @Override
        public Fragment getItem(int position)

        {
            return (Fragment) list.get(position);
        }

        @Override
        public int getCount()
        {
            return list.size();
        }
    }
}

现在我们的底部导航已经建好了,接下来需要我们新建三个fragment页面,分别实现书架、感悟、分类三个部分。

首先是书架部分,先上图看看效果:

fragment_login1.xml:




    

        

        
    



在这里说明一下,页面的顶部本质是一个TextView控件,但文字是可以横向滚动的,所以得自己写一个基于TextView的子类。
java文件MarqueTextView:

public class MarqueTextView extends androidx.appcompat.widget.AppCompatTextView {

    public MarqueTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public MarqueTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MarqueTextView(Context context) {
        super(context);
    }

    @Override

    public boolean isFocused() {
        //就是把这里返回true即可
        return true;
    }
}

然后是实现书架这一部分的java文件LoginFragment1:

public class LoginFragment1 extends Fragment implements AdapterView.OnItemClickListener{
    //变量名注册
    ListView listView;
    SimpleAdapter simpleAdapter;

    public View onCreateView
            (@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_login1, container, false);
        //id注册
        listView = view.findViewById(R.id.lg3_listView);
        MarqueTextView as = view.findViewById(R.id.mtv);
        simpleAdapter = new SimpleAdapter(getActivity(),getData(),R.layout.item,
                new String[]{"title","image"},new int[]{R.id.item_tv,R.id.item_image});
        //设置适配器监听器
        listView.setAdapter(simpleAdapter);
        listView.setOnItemClickListener(this);
        //将文件由assets转移到手机空间
        copyFilesFromAssets(getActivity(),"ml","/data/data/com.example.ebook/files");
        as.setText(load());
        return view;
    }

    //设置listview图文
    private List> getData() {
        String [] titles={"射雕英雄传n简介:南宋末年,金兵入侵,朝廷奸臣当道。全真派丘处机因杀死汉奸王道乾,被官兵追杀,逃到江南一个小村牛家庄,与隐居在此处的爱国义士郭啸天和杨铁心一见如故,以“靖、康”为他俩即将出生的孩子命名,并留下一对短剑作为信物……",
                "神雕侠侣n简介:南宋末年,江南少年杨过被郭靖送去全真教学武。全真教教规森严,天性叛逆的杨过在教中吃尽苦头,忍无可忍,终于逃出全真教。被活死人墓中的小龙女收留为徒。师徒二人在墓中一起练武、一起长大,渐生情愫……",
                "倚天屠龙记n简介:少林寺觉远禅师看护《楞伽经》不力,导致经书被尹克西和潇湘子盗走。潇湘子和尹克西互相猜忌残杀,临终之前幡然醒悟,委托何足道向觉远转达经书的下落。何足道接受委托,并向少林寺发出挑战。适逢郭靖、黄蓉的女儿郭襄前往少林寺寻找杨过……",
                "绝对娇宠n简介:作者:陈三年n斯文霸道总裁装逼乘骄纵美人,爱让人勇敢,双向奔赴,梦会成真。",
                "斗罗大陆n简介:外门弟子唐三,因偷学内门绝学为唐门所不容,跳崖明志时却发专现没有死,反而以另属外一个身份来到了另一个世界,名叫斗罗大陆。这里没有魔法,没有斗气,没有武术,却有神奇的武魂……",
                "末日游戏场n简介:系统:“你们的任务是活下去,倾尽所有,不择手段地活下去,完成一场挑战,即可获得一张通行证。n星际333年,地球环境无法生存 开启全民末日游戏场,提过游戏得到通行证,获取生存资格。",
                "完美世界n简介:一粒尘可填海,一根草斩尽日月星辰,弹指间天翻地覆。n群雄并起,万族林立,诸圣争霸,乱天动地。问苍茫大地,谁主沉浮?!n一个少年从大荒中走出,一切从这里开始n"};
        int [] images={R.drawable.im1,R.drawable.im2,R.drawable.im3,
                R.drawable.im4,R.drawable.im5,
                R.drawable.im6,R.drawable.im7};
        List> list= new ArrayList<>();
        for(int i=0;i<7;i++){
            Map  map = new HashMap();
            map.put("title",titles[i]);
            map.put("image",images[i]);
            list.add(map);
        }
        return list;
    }

    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

    }
    //设置listview点击触发事件
    @Override
    public void onItemClick(AdapterView parent, View view, int position, long id) {
        switch (position){
            case 0:
                Intent intent0 = new Intent(getActivity(),ReadBook.class);
                intent0.putExtra("extra","0.txt");
                startActivity(intent0);
                break;
            case 1:
                Intent intent1 = new Intent(getActivity(),ReadBook.class);
                intent1.putExtra("extra","1.txt");
                startActivity(intent1);
                break;
            case 2:
                Intent intent2 = new Intent(getActivity(),ReadBook.class);
                intent2.putExtra("extra","2.txt");
                startActivity(intent2);
                break;
            case 3:
                Intent intent3 = new Intent(getActivity(),ReadBook.class);
                intent3.putExtra("extra","3.txt");
                startActivity(intent3);
                break;
            case 4:
                Intent intent4 = new Intent(getActivity(),ReadBook.class);
                intent4.putExtra("extra","4.txt");
                startActivity(intent4);
                break;
            case 5:
                Intent intent5 = new Intent(getActivity(),ReadBook.class);
                intent5.putExtra("extra","5.txt");
                startActivity(intent5);
                break;
            case 6:
                Intent intent6 = new Intent(getActivity(),ReadBook.class);
                intent6.putExtra("extra","6.txt");
                startActivity(intent6);
                break;

            default:
                throw new IllegalStateException("Unexpected value: " + position);


        }


    }



//       从assets目录中复制整个文件夹内容到新的路径下
//       @param  context  Context 使用CopyFiles类的Activity
//      @param  oldPath  String  原文件路径  如:Data(assets文件夹下文件夹名称)
//      @param  newPath  String  复制后路径  如:data/data/(手机内部存储路径名称)

    public void copyFilesFromAssets(Context context, String oldPath, String newPath) {
        try {
            String fileNames[] = context.getAssets().list(oldPath);//获取assets目录下的所有文件及目录名
            if (fileNames.length > 0) {//如果是目录
                File file = new File(newPath);
                file.mkdirs();//如果文件夹不存在,则递归
                for (String fileName : fileNames) {
                    copyFilesFromAssets(context,oldPath + "/" + fileName,newPath+"/"+fileName);
                }
            } else {//如果是文件
                InputStream is = context.getAssets().open(oldPath);
                FileOutputStream fos = new FileOutputStream(new File(newPath));
                byte[] buffer = new byte[1024];
                int byteCount=0;
                while((byteCount=is.read(buffer))!=-1) {//循环从输入流读取 buffer字节
                    fos.write(buffer, 0, byteCount);//将读取的输入流写入到输出流
                }
                fos.flush();//刷新缓冲区
                is.close();
                fos.close();
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            //如果捕捉到错误则通知UI线程
            //MainActivity.handler.sendEmptyMessage(COPY_FALSE);
        }


    }

    //设置顶部文字并循环播放
    String  load(){
        String tit="  欢迎来到Ebook阅读器,这是您打开知识宝库的钥匙!n" +
                "  欢迎来到Ebook阅读器,这是您打开知识宝库的钥匙!n" ;
        return tit;
    }
}

其实现在看来当时写的还是非常简单的,在书架展示这一块是靠代码后台输入文字介绍,以及用简单地Switch现实跳转,换成现在有更好的解决方式。不过这是后话,我想能力的提升也是循序渐进的。我还是来解释一些核心的代码。
书的内容是以txt格式存放在之前提到的asset文件夹里面,copyFilesFromAssets函数便是实现对asset文件内容的读取。这样就实现了文件可以随着代码一起保存并放到手机上,不用创建数据库(现在觉得创建了数据库实现的功能可能可以更加完善)是一种投机取巧的方式
这里的适配器simpleAdapter里的item:




    

    



当用户点进一本书后会看到类似界面:

activity_read_book.xml:



    


java文件ReadBook:

public class ReadBook extends AppCompatActivity {
    String txt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_read_book);

        Intent intent=getIntent();
        txt=intent.getStringExtra("extra");

        Log.d("ReadBook",txt);

        TextView sb =  findViewById(R.id.sd);
        sb.setMovementMethod(ScrollingMovementMethod.getInstance());
        sb.setSelected(true);
        sb.setText(load());
    }


    //获取手机空间中的txt文件
    public String load() {
        FileInputStream in = null;
        BufferedReader reader = null;
        StringBuilder content = new StringBuilder();
        try {
            in = openFileInput(txt);
            reader = new BufferedReader(new InputStreamReader(in));
            String line = "";
            while ((line = reader.readLine()) != null) {
                content.append("n");
                content.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return content.toString();
    }
}

这里的Log是用来实现两个活动直接的信息传递,load函数就是基本的读取txt文件操作了。

到此为止作为一个阅读器最重要的阅读功能就可以实现了,接下来的感悟和分类,均使用到了数据库,待下回分解。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1031987.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号