一、简单介绍

       该APP是一款简单易用、界面美观且功能强大的语音阅读器,实现本地导入阅读(支持大文件)、在线阅读、书签、跳转、日夜间模式、设置字体大小、设置书架/阅读界面背景等功能
        还支持语音阅读、吹气阅读、笑话大全等功能,
        适合开车、跑步、逛街、午夜等情况听书,
        免去眼睛的疲劳,专为Android用户考虑,是非常好、体贴的语音阅读器
        说明:开发源代码参考了互联网分享的一些代码

二、GuideActivity

        这是一个引导界面,和主流app一样,用户在第一次进入时能见到这个界面。主要用到的知识点是ViewPager,这个在网上已经用烂了,就不多说,直接上代码
       GuadeActivity.java
package com.xiaoli.ui;import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import java.util.ArrayList;
import com.hck.LoverReader.R;
import android.content.Intent;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.ImageView; public class GuideActivity extends Activity { private ViewPager viewPager;/**装分页显示的view的数�??*/private ArrayList<View> pageViews;     private ImageView imageView; /**将小圆点的图片用数组表示*/private ImageView[] imageViews; //包裹滑动图片的LinearLayout private ViewGroup viewPics; //包裹小圆点的LinearLayout private ViewGroup viewPoints;//第一次还有进入loadingprivate SharedPreferences sp;private SharedPreferences.Editor editor;boolean isFirstRun;@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);sp = this.getSharedPreferences("share", MODE_PRIVATE);//将要分页显示的View装入数组LayoutInflater inflater = getLayoutInflater(); pageViews = new ArrayList<View>(); pageViews.add(inflater.inflate(R.layout.viewpager_page1, null));pageViews.add(inflater.inflate(R.layout.viewpager_page2, null)); pageViews.add(inflater.inflate(R.layout.viewpager_page3, null));pageViews.add(inflater.inflate(R.layout.viewpager_page4, null));//创建imageviews数组,大小是要显示的图片的数 imageViews = new ImageView[pageViews.size()]; //从指定的XML文件加载视图 viewPics = (ViewGroup) inflater.inflate(R.layout.activity_guide, null); //实例化小圆点的linearLayout和viewpager viewPoints = (ViewGroup) viewPics.findViewById(R.id.viewGroup); viewPager = (ViewPager) viewPics.findViewById(R.id.guidePages); //添加小圆点的图片 for(int i=0;i<pageViews.size();i++){ imageView = new ImageView(GuideActivity.this); //设置小圆点imageview的参数imageView.setLayoutParams(new LayoutParams(20,20));//创建一个宽高均为20的布局imageView.setPadding(20, 0, 20, 0); //将小圆点layout添加到数组中 imageViews[i] = imageView; //默认选中的是第一张图片,此时第一个小圆点是选中状态,其他不是 if(i==0){ imageViews[i].setBackgroundResource(R.drawable.page_indicator_focused); }else{ imageViews[i].setBackgroundResource(R.drawable.page_indicator); } //将imageviews添加到小圆点视图 viewPoints.addView(imageViews[i]); } //显示滑动图片的视图setContentView(viewPics); //设置viewpager的设配器和监听事件 viewPager.setAdapter(new GuidePageAdapter()); viewPager.setOnPageChangeListener(new GuidePageChangeListener());         } private Button.OnClickListener  Button_OnClickListener = new Button.OnClickListener() { public void onClick(View v) { //设置已经引导 //setGuided(); //跳转Intent intent = new Intent();intent.setClass(GuideActivity.this, BookListActivity2.class);GuideActivity.this.startActivity(intent);GuideActivity.this.finish();}};  class GuidePageAdapter extends PagerAdapter{//销毁position位置的界面@Overridepublic void destroyItem(View v, int position, Object arg2) { // TODO Auto-generated method stub ((ViewPager)v).removeView(pageViews.get(position)); } @Overridepublic void finishUpdate(View arg0) { // TODO Auto-generated method stub } //获取当前窗体界面@Overridepublic int getCount() { // TODO Auto-generated method stub return pageViews.size(); } //初始化position位置的界面 @Overridepublic Object instantiateItem(View v, int position) { // TODO Auto-generated method stub ((ViewPager) v).addView(pageViews.get(position));   // 测试页卡1内的按钮事件   if (position == 3) {Button btn = (Button) v.findViewById(R.id.btn_close_guide);   btn.setOnClickListener(Button_OnClickListener);   }   return pageViews.get(position);   } // 判断是否由对象生成界面@Overridepublic boolean isViewFromObject(View v, Object arg1) { // TODO Auto-generated method stub return v == arg1; } @Overridepublic void startUpdate(View arg0) { // TODO Auto-generated method stub } @Overridepublic int getItemPosition(Object object) { // TODO Auto-generated method stub return super.getItemPosition(object); } @Overridepublic void restoreState(Parcelable arg0, ClassLoader arg1) { // TODO Auto-generated method stub } @Overridepublic Parcelable saveState() { // TODO Auto-generated method stub return null; } } class GuidePageChangeListener implements OnPageChangeListener{@Overridepublic void onPageScrollStateChanged(int arg0) { // TODO Auto-generated method stub } @Overridepublic void onPageScrolled(int arg0, float arg1, int arg2) { // TODO Auto-generated method stub } @Overridepublic void onPageSelected(int position) { // TODO Auto-generated method stub for(int i=0;i<imageViews.length;i++){ imageViews[position].setBackgroundResource(R.drawable.page_indicator_focused); //不是当前选中的page,其小圆点设置为未选中状态if(position !=i){ imageViews[i].setBackgroundResource(R.drawable.page_indicator); } } } }    

      最后这段代码指定了intent要跳转的activity,也就是我这个app的书架界面了
               

                //跳转Intent intent = new Intent();intent.setClass(GuideActivity.this, BookListActivity2.class);GuideActivity.this.startActivity(intent);GuideActivity.this.finish();

二、lodingActivity

     这个界面主要是在WelcomeActivity后,播放一下渐变动画(文字、图片随机出现),这个应该有点多余,因为可以从WelcomeActivity直接跳转到BookListActivity2界面,
但是自己写都写了,也不想删了
LodingActivity.javapackage com.xiaoli.ui;import java.util.Random;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import com.hck.LoverReader.R;public class LodingActivity extends Activity {private TextView textView;private FrameLayout layoutLoding2;private ImageView imageView;private Animation animation;//图片资源private int[] mArray = new int[]{R.drawable.f_0, R.drawable.f_1, R.drawable.f_2, R.drawable.loding2, R.drawable.f_3, R.drawable.f_4, R.drawable.f_5,R.drawable.f_6, R.drawable.f_7, R.drawable.f_8, R.drawable.f_9, R.drawable.f_10, R.drawable.f_11,};private Random random;//引导提示文字String[] tips;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);setContentView(R.layout.loding);//获取布局(设置动画)layoutLoding2 =(FrameLayout)findViewById(R.id.layoutLoding2);//随机数random=new Random();int mImgs=random.nextInt(mArray.length);imageView = (ImageView) findViewById(R.id.loding_im);imageView.setImageResource(mArray[mImgs]);//文字tips=getResources().getStringArray(R.array.loadingtips);int rTips=random.nextInt(tips.length);textView=(TextView)findViewById(R.id.lodingTips);textView.setText(tips[rTips]);animation = AnimationUtils.loadAnimation(this, R.anim.loding);layoutLoding2.setAnimation(animation);animation.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation arg0) {}@Overridepublic void onAnimationRepeat(Animation arg0) {}@Overridepublic void onAnimationEnd(Animation arg0) {//休眠500毫秒new Thread(){public void run() {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}.start();startActivity(new Intent(LodingActivity.this,BookListActivity2.class));finish();}});}                  

我们可以看到,里面定义了接个控件和一个Animation,主要就是随机产生图片和文字,播放一段动画,挺简单的。

三、WelComeActivity

   这个Activity的作用比较多,主要有
       1.加载一段动画
       2.动画加载完后,判断是不是用户第一次进入这个界面,如是则跳转到GuideActivity,否则跳转到LodingActivity.这个过程用到了sharedPreferences
   3.加载(初始化)书架界面的数据(书籍存在Raw文件下)。不是第一次才加载。
   
   Welcome.java源代码
   
package com.xiaoli.ui;import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.RelativeLayout;import com.hck.LoverReader.R;
import com.hck.book.uti.JMPManager;
import com.xiaoli.date.FinalDate;import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;import static com.hck.LoverReader.R.id.imageView;public class WelcomeActivity extends Activity {private RelativeLayout layoutWelcome;private SharedPreferences sp;private SharedPreferences.Editor editor;private Animation animation;//动画是否加载完private boolean isOK;//是否加载(登录)过数据private boolean isLogin;private Boolean isFirstRun;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);FinalDate.context=this;sp = getSharedPreferences("book", Context.MODE_PRIVATE);editor = sp.edit();isFirstRun = sp.getBoolean("isFirstRun", true);if (sp.getLong("time", 0) == 0) {editor = sp.edit();editor.putLong("time", System.currentTimeMillis());editor.commit();FinalDate.tme=System.currentTimeMillis();}else {FinalDate.tme=sp.getLong("time", 0);}if (sp.getBoolean("isFirst", true)) {FinalDate.isFirst=true;editor = sp.edit();editor.putBoolean("isFirst", false);editor.commit();}else {FinalDate.isFirst=false;}JMPManager manager = new JMPManager();manager.startService(this,1);requestWindowFeature(Window.FEATURE_NO_TITLE);getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);setContentView(R.layout.activity_welcome);layoutWelcome = (RelativeLayout) findViewById(R.id.RelativeLayout1);animation = AnimationUtils.loadAnimation(this, R.anim.dialog_enter);layoutWelcome.setAnimation(animation);if (!isLogin()) {new WelcomeActivity.AsyncSetApprove().execute();isLogin = false;} else {isLogin = true;}animation.setAnimationListener(new Animation.AnimationListener() {@Overridepublic void onAnimationStart(Animation arg0) {}@Overridepublic void onAnimationRepeat(Animation arg0) {}@Overridepublic void onAnimationEnd(Animation arg0) {isOK = true;//休眠1000毫秒new Thread(){public void run() {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}.start();//发送消息handler.sendEmptyMessage(2);}});}// 判断是否是第一次启动程序private boolean isFristRun() {if (!isFirstRun) {return false;} else {editor.putBoolean("isFirstRun", false);editor.commit();return true;}}//以前的loding代码private boolean isLogin() {sp = getSharedPreferences("mark", MODE_PRIVATE);isLogin = sp.getBoolean("isInit", false);if (isLogin) {return true;}return false;}Handler handler = new Handler() {@Overridepublic void handleMessage(android.os.Message msg) {if (isLogin && isOK ) {if (isFristRun()) {// 如果是第一次启动程序则进入引导界面Intent intent = new Intent(WelcomeActivity.this,GuideActivity.class);startActivity(intent);} else {// 如果不是第一次启动则进入主页Intent intent = new Intent(WelcomeActivity.this,LodingActivity.class);startActivity(intent);}WelcomeActivity.this.finish();}};};class AsyncSetApprove extends AsyncTask<String, Integer, String> {@Overrideprotected String doInBackground(String... params) {File path = getFilesDir();String[] strings = getResources().getStringArray(R.array.bookid);// 获取assets目录下的文件列表for (int i = 0; i < strings.length; i++) {try {FileOutputStream out = new FileOutputStream(path + "/"+ strings[i]);BufferedInputStream bufferedIn = new BufferedInputStream(getResources().openRawResource(R.raw.book1 + i));BufferedOutputStream bufferedOut = new BufferedOutputStream(out);byte[] data = new byte[2048];int length = 0;while ((length = bufferedIn.read(data)) != -1) {bufferedOut.write(data, 0, length);}// 将缓冲区中的数据全部写出bufferedOut.flush();// 关闭流bufferedIn.close();bufferedOut.close();sp.edit().putBoolean("isInit", true).commit();} catch (Exception e) {e.printStackTrace();}}ArrayList<HashMap<String, String>> insertList = new ArrayList<HashMap<String, String>>();File[] f1 = path.listFiles();int len = f1.length;for (int i = 0; i < len; i++) {if (f1[i].isFile()) {if (f1[i].toString().contains(".txt")) {HashMap<String, String> insertMap = new HashMap<String, String>();insertMap.put("parent", f1[i].getParent());insertMap.put("path", f1[i].toString());insertList.add(insertMap);}}}SQLiteDatabase db = MyApplication.bookDB.getWritableDatabase();db.delete(FinalDate.DATABASE_TABKE, "type='" + 2 + "'", null);for (int i = 0; i < insertList.size(); i++) {try {if (insertList.get(i) != null) {String s = insertList.get(i).get("parent");String s1 = insertList.get(i).get("path");String sql1 = "insert into " + FinalDate.DATABASE_TABKE+ " (parent,path" + ", type"+ ",now,ready) values('" + s + "','" + s1+ "',2,0,null" + ");";db.execSQL(sql1);}} catch (SQLException e) {Log.e("hck", "setApprove SQLException", e);} catch (Exception e) {Log.e("hck", "setApprove Exception", e);}}db.close();sp.edit().putBoolean("isInit", true).commit();return null;}@Overrideprotected void onPostExecute(String result) {isLogin = true;handler.sendEmptyMessage(1);super.onPostExecute(result);}}
}

 基本实现思路是:
          1.不是第一次Login就去加载Raw文件里面的书籍,如是则不用。相关代码
if (!isLogin()) {new WelcomeActivity.AsyncSetApprove().execute();isLogin = false;
} else {isLogin = true;
}

2.动画加载完后,发送消息给handler处理。相关代码

@Override
public void onAnimationEnd(Animation arg0) {isOK = true;//休眠1000毫秒new Thread(){public void run() {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}.start();//发送消息handler.sendEmptyMessage(2);
}

3.handler的handlerMessage中判断用户是不是第一次进入,并选择跳转界面

public void handleMessage(android.os.Message msg) {if (isLogin && isOK ) {if (isFristRun()) {// 如果是第一次启动程序则进入引导界面Intent intent = new Intent(WelcomeActivity.this,GuideActivity.class);startActivity(intent);} else {// 如果不是第一次启动则进入主页Intent intent = new Intent(WelcomeActivity.this,LodingActivity.class);startActivity(intent);}WelcomeActivity.this.finish();}}
// 判断是否是第一次启动程序private boolean isFristRun() {if (!isFirstRun) {return false;} else {editor.putBoolean("isFirstRun", false);editor.commit();return true;}}

四、效果图

    用AndroidStudio录制的短视频很模糊,然后直接用工具录制了GIF动图
    1.第一次启动(welcomeActivity没录制上)
    
    2.第二次启动
    
****************************************************************************************本文完,很少用csdn写文章,写得格式都全部乱了,唉!
以后有时间一定多写写
    

      


Android爱读app开发记录之一---Splash界面相关推荐

  1. Android兼容性系统app开发的一些探究

    Android兼容性系统app开发的一些探究 说明 起因 软件现状 需求 实现探究 第一点:软件兼容原则 第二点:软件实现方案 具体实现 说明 说明 本文是我根据自己开发期间项目需求探究的总结,里面有 ...

  2. 【Android开发】微信精选,文章资讯类App开发记录总结

    缘起 微信精选的App开发来源是在聚合数据上看到了有免费的微信精选的数据接口,无限调用.相对于其他的诸如违章查询,医药查询,NBA赛事等等,我感觉还是微信文章精选这个数据接口离我最近,所以想着拿着个数 ...

  3. Android入门 简单app开发:为女友实现记录月经周期的app

    前言 寒假答应给女友做一个记录月经周期的app,由于我太vegetable,写的比较辣鸡,大家凑活着看(手动笑哭) 思路: 首先要跟大家说的是, android开发 要明白开发思想:逻辑和视图是分开的 ...

  4. 基于Android的理财app开发,基于Android的个人理财系统的设计与实现.doc

    毕业论文(设计)题目: 基于Android的个人理财系统 ---设计与实现 学生姓名: 学 号: 专业班级: 计算机科学与技术092班 指导教师: 职称 副教授 指导教师: 职称 起止时间: 目 录 ...

  5. Android短视频app开发中如何实现上下滑动切换效果

    在大部分短视频app开发中,都会在app内增加上下滑动切换视频的功能,即下滑切换到下一条短视频,上滑切回到上一条.这种机制可以给用户带来良好的视觉体验,云豹作为优秀的app源码供应商,在该效果的实现上 ...

  6. android ril wifi,Android WIFI Ralink RT3070开发记录

    一.wifi基本架构 1.开源代码移植部分(external目录下) wireless_tools.wpa_supplicant.wpa_supplicant_6(后两项已经移植过) 生成库libwp ...

  7. Android——“i 分享”APP开发Day06

    继续上一篇的内容,写FindFragment.java文件,在上一篇的三个函数基础上基本就可以展示出热门内容了,接下来主要就是处理找人和找文按钮的事件 因为之后还需要实现找人的功能,所以要先给创建一个 ...

  8. [仿南航app开发日记2]主界面完成

    效果 先来看看主界面完成的效果: 这是主界面的样子,如果要参照原app是什么样子的可以参照我的上一篇博客: http://blog.csdn.net/supervictim/article/detai ...

  9. Android——“i分享”APP开发Day11

    通过前面一篇,"我的"页面的后台就搭建完整了,接下来就继续处理一下Android端下"我的"页面剩余还未完成的功能--修改密码.查看我的分享.查看我的日记.查看 ...

最新文章

  1. 老友记即将回归!用数据来重温经典剧情:老友记里到底说了多少次Oh my God?...
  2. 3.以太坊之秘钥文件
  3. 2、Flutter Widget(IOS Style) - CupertinoActionSheet;
  4. java-retry实现
  5. java 字节输入流_JavaIO流(一)-字节输入流与字符输入流
  6. git使用之搭建git仓库
  7. Flask 参数简介
  8. SAP FB60\FB70\MIRO 默认税码配置
  9. DynamipsGUI2.7使用介绍
  10. 【深度学习】图像超分实验:SRCNN/FSRCNN
  11. 网吧服务器安装操作系统,网吧无盘技术的安装与使用---服务器的操作系统为为wind...
  12. 魔方cfop公式软件_魔方与群论(一)(不要被标题吓到,高中生就可以看)
  13. LabVIEW调试技巧
  14. 《两日算法系列》之第四篇:隐马尔可夫模型HMM
  15. Win-TortoiseGit-使用之-合并代码
  16. 【T+】畅捷通T+选项设置界面没有“数据精度”调整项
  17. 超好用的Redis管理及监控工具
  18. 不能打开要写入的文件,软件安装不上解决方法
  19. VS报错:error LNK2026: 模块对于 SAFESEH 映像是不安全的
  20. 前端基础(不定期更新)

热门文章

  1. 通信原理包络是什么意思_适用于包络跟踪应用的高带宽AB类放大器设计
  2. 一个SpringBoot问题就干趴下了?我却凭着这份PDF文档吊打面试官(Spring Boot知识点+详解)
  3. 可再生能源与能源存储技术的结合和互补
  4. Adobe的PDF编辑软件Acrobat Pro DC 2023版本下载与安装教程
  5. 数字信号处理基础----xilinx除法器IP使用
  6. hdparm命令详解[转]
  7. adaptec raid linux,adaptecraid卡管理软件在windows和linux下的安装使用介绍(7页)-原创力文档...
  8. Office 2010 Excel 窗口独立显示
  9. 八十一、ElasticSearch详解(中)
  10. 查看 Linux 发行版名称和版本号的 8 种方法