Android Studio小组作业·“悦读”app总结,Android Studio小组作业,悦读app开发总结

马肤

温馨提示:这篇文章已超过440天没有更新,请注意相关的内容是否还可用!

在Android Studio环境下开发的“悦读”app项目圆满完成。本次小组作业历经数月,我们共同协作,完成了app的各项功能开发。该app旨在为用户提供便捷的阅读体验,包括书籍推荐、在线阅读、阅读设置等功能。我们克服了许多技术难题,最终实现了流畅的用户界面和高效的性能表现。此次合作不仅提升了我们的技术能力,也锻炼了团队协作的能力。“悦读”app得到了良好的用户反馈,我们将继续优化和完善产品。

本人是小白,初学安卓,所以只能制作一个简陋的“毛坯房”。一开始想设计书店,使用安卓自带的sqlite数据库保存书本信息,然后通过搜索匹配有的书籍显示在搜索页面,添加进入购物车,选择数量后完成支付,相应的数据库内图书的数量也会发生变化。

这是我的预想效果,但实际操作起来难度很大,并且我对安卓数据库了解不足,所以就抛弃了这方案,选择老师上课讲解的一些控件来写应用,思路也从“书店”转为了更为简单些的“阅读器”。(我最后完成的内容真的很简单很简单,但是也花了我很长时间,这个主要是因为一开始我还没学会爬就想跑,有点心切)

下面我来介绍一下我的设计思路


设计框图

手绘如下:

Android Studio小组作业·“悦读”app总结,Android Studio小组作业,悦读app开发总结 第1张

点击app首先进入的是注册页,输入账户名,密码,电话和邮箱后点击注册,即可注册成功。数据会保存在user表中。

点击返回登录,会进入登录页面,登录页只需要输入账户和密码,核对无误后可以登录成功;

我使用了安卓自带的导航栏模板,本身有三个页面,后面还增加了一个fragment;

Android Studio小组作业·“悦读”app总结,Android Studio小组作业,悦读app开发总结 第2张

点击登录后进入首页,有搜索框和搜索按钮,还有热门推荐书籍图片;点击搜索和热门推荐图片会进入书籍详情页。

点击分类页,本想设计一个类似“京东”等购物平台有的分类页,但是太难了,后面放弃,使用listview控件展示书籍,并没有根据类型分类;点击每个listitem会跳转对应网页阅读

点击书架页面,有添加书籍和已有书籍展示,没有具体的完整操作,点击添加标志会跳转书籍详情页;

点击我的,展示个人信息,可以看出来这是购物app的“我的”,因为前期目标是“书店”app,后面目标变化也就懒得更改了,利用上课所学知识获取电话权限,点击联系客服可以转入拨打页面;

书籍详情页里面是一本我喜欢的书,点击加入书架不会有反应,我没写;点击阅读会跳转网页,点返回会回到首页。

后面是具体代码和效果展示


创建数据库

先创建两个类,一个是User,一个是Books

Books

package com.example.yueshudian;
//创建user类,并添加属性和构造方法、get、set方法
public class Books {
    public String bookname;
    public String picture;
    public String author;
    public String address;
    public String classify;
    public Books(){}
    public Books(String bookname, String picture, String author, String address,String classify) {
        this.bookname = bookname;
        this.picture = picture;
        this.author = author;
        this.address = address;
        this.classify=classify;
    }
    public String getBookname() {
        return bookname;
    }
    public void setBookname(String bookname) {
        this.bookname = bookname;
    }
    public String getPicture() {
        return picture;
    }
    public void setPicture(String picture) {
        this.picture = picture;
    }
    public String getAuthor() {
        return author;
    }
    public void setAuthor(String author) {
        this.author = author;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address= address;
    }
    public String getClassify() {
        return classify;
    }
    public void setClassify(String classify) {
        this.classify= classify;
    }
}

User

package com.example.yueshudian;
//创建user类,并添加属性和构造方法、get、set方法
public class User {
    public String username;
    public String password;
    public String phone;
    public String emil;
    public User(){}
    public User(String username, String password, String phone, String emil) {
        this.username = username;
        this.password = password;
        this.phone = phone;
        this.emil = emil;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public String getEmil() {
        return emil;
    }
    public void setEmil(String emil) {
        this.emil = emil;
    }
}

里面创建了user+book.db数据库,并创建了两个表,一个是user一个是readbooks,大家应该看得懂。

package com.example.yueshudian;
import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import androidx.annotation.Nullable;
public class MySQLiteOpenHelper extends SQLiteOpenHelper {
    //定义全局变量db
    SQLiteDatabase db = getWritableDatabase();
    //创建用户表
    private static final String CREATE_USER = "create table user(id integer primary key autoincrement," +
            "username varchar(30)," +
            "password varchar(30)," +
            "phone varchar(30)," +
            "emil varchar(30))";
    private static final String CREATE_BOOK = "create table readbooks(id integer primary key autoincrement," +
            "bookname varchar(30)," +
            "picture varchar(30)," +
            "author varchar(30)," +
            "address varchar(60),"+
            "classify varchar(30))";
    //运行程序时,Android Studio帮你创建数据库,只会执行一次
    public MySQLiteOpenHelper(@Nullable Context context) {
        super(context, "user+book.db", null, 3);
    }
    //添加注册的方法,即把我们输入的数据保存在数据库中(插入)
    public long register(User u){
        ContentValues cv = new ContentValues();
        cv.put("username ",u.getUsername());
        cv.put("password",u.getPassword());
        cv.put("phone",u.getPhone());
        cv.put("emil",u.getEmil());
        long users = db.insert("user",null,cv);
        return users;
    }
    //登录方法实现
    public boolean login(String username,String password){
        boolean result = false;
        Cursor users = db.query("user", null, "username like?", new String[]{username}, null, null, null);
        if(users!=null){
            while (users.moveToNext()){
                @SuppressLint("Range") String username1 = users.getString(users.getColumnIndex("username"));
                Log.d("users", "login: "+username1);
                String password1 = users.getString(2);
                Log.d("users", "login: "+password1);
                result = password1.equals(password);
                return result;
            }
        }
        return false;
    }
    public boolean searchbook(String bookname){
        boolean result = false;
        Cursor books = db.query("readbooks", null, "bookname like?", new String[]{bookname}, null, null, null);
        if(books!=null){
            while (books.moveToNext()){
                @SuppressLint("Range") String bookname1 = books.getString(books.getColumnIndex("bookname"));
                Log.d("books", "login: "+bookname1);
                result = bookname1.equals(bookname);
                return result;
            }
        }
        return false;
    }
    //根据用户名查找当前登录用户信息
    public User select(String username){
        User SelectUser = new User();
        Cursor user = db.query("user", new String[]{"username", "phone", "emil"}, "username=?", new String[]{username}, null, null, null);
        while(user.moveToNext()){
            @SuppressLint("Range") String uname =user.getString(user.getColumnIndex("username"));
            @SuppressLint("Range") String phone = user.getString(user.getColumnIndex("phone"));
            @SuppressLint("Range") String emil = user.getString(user.getColumnIndex("emil"));
            SelectUser.setUsername(uname);
            SelectUser.setPhone(phone);
            SelectUser.setEmil(emil);
        }
        user.close();
        return SelectUser;
    }

    //丰富书库内容
    public long bookDB(Books book) {
        ContentValues cv = new ContentValues();
        cv.put("bookname", book.bookname);
        cv.put("picture", book.picture);
        cv.put("author", book.author);
        // 注意:这里假设picture是图片在媒体存储中的URI
        cv.put("address", book.address);
        cv.put("classify", book.classify);
        Log.d("ljz in db:","db insert successful");
        // 插入数据到数据库
        long books=db.insert("readbooks", null, cv);
        return books;
    }
    //检索书籍
    public Books selectbook(String bookname){
        Books SelectBook = new Books();
        Cursor book = db.query("books", new String[]{"bookname", "price", "author","address","classify"}, "bookname=?", new String[]{bookname}, null, null, null);
        while(book.moveToNext()){
            @SuppressLint("Range") String bname =book.getString(book.getColumnIndex("bookname"));
            @SuppressLint("Range") String picture = book.getString(book.getColumnIndex("picture"));
            @SuppressLint("Range") String author = book.getString(book.getColumnIndex("author"));
            @SuppressLint("Range") String address = book.getString(book.getColumnIndex("address"));
            @SuppressLint("Range") String classify =book.getString(book.getColumnIndex("classify"));
            SelectBook.setBookname(bname);
            SelectBook.setPicture(picture);
            SelectBook.setAuthor(author);
            SelectBook.setAddress(address);
            SelectBook.setClassify(classify);
        }
        book.close();
        return SelectBook;
    }

    //创建数据表
    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        if (sqLiteDatabase != null) {
            sqLiteDatabase.execSQL(CREATE_USER);
            sqLiteDatabase.execSQL(CREATE_BOOK);
        }
    }
    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
        if(sqLiteDatabase!=null){
            sqLiteDatabase.execSQL("drop table if exists user");
            sqLiteDatabase.execSQL("drop table if exists readbooks");
            onCreate(sqLiteDatabase);
        }
    }
}

注册页面

注册页面布局:registerpage.xml

其中的DBsearchButton是用于查看已建立的图书表信息的










布局效果

Android Studio小组作业·“悦读”app总结,Android Studio小组作业,悦读app开发总结 第3张

对应Acticity:RegisterActivity

此处还不是fragment流动布局,很好写,不过我自己熟悉的是kt语言,我用ai自动转java,有时候会有一些漏洞,缝缝补补也好了。

package com.example.yueshudian;
import androidx.appcompat.app.AppCompatActivity;
import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.time.DayOfWeek;
public class RegisterActivity extends AppCompatActivity implements View.OnClickListener {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        mySQLiteOpenHelper = new MySQLiteOpenHelper(this);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.registerpage);
        //初始化获取的布局元素
        find();
        addBooksToDB();
    }
    //获取注册按钮,预先定义,下方输入框同理
    private Button register,gotologin,DBsearchButton;
    private EditText username,password,phone,emil;
    //使用MySQLiteOpenHelper类中的方法
    private MySQLiteOpenHelper mySQLiteOpenHelper;
    private  SQLiteDatabase db ;
    String bookname,picture,classify,author,address;

    //控制注册按钮点击完后不给点击了
    boolean flag = false;
    //跳转回登录页面
    public void goback(){
        Intent gl = new Intent(RegisterActivity.this,LoginActivity.class);
        startActivity(gl);
    }
    //初始化获取的布局元素
    public void find(){
        username = findViewById(R.id.username);
        password = findViewById(R.id.password);
        phone = findViewById(R.id.phone);
        emil = findViewById(R.id.email);
        register = findViewById(R.id.registerButton);
        register.setOnClickListener(this);
        gotologin = findViewById(R.id.gotologin);
        gotologin.setOnClickListener(this);
        DBsearchButton=findViewById(R.id.DBSearchButton);
        DBsearchButton.setOnClickListener(this);
    }
    //注册逻辑实现
    public void register(){
        String ru = username.getText().toString();
        String rps = password.getText().toString();
        String rph = phone.getText().toString();
        String rem = emil.getText().toString();
        User user = new User(ru,rps,rph,rem);
        if(ru.equals("")){
            Toast.makeText(this, "账号不能为空!", Toast.LENGTH_SHORT).show();
        } else if (rps.equals("")) {
            Toast.makeText(this, "密码不能为空!", Toast.LENGTH_SHORT).show();
        } else if (rph.equals("")) {
            Toast.makeText(this, "电话不能为空!", Toast.LENGTH_SHORT).show();
        }else if(rem.equals("")){
            Toast.makeText(this, "邮箱不能为空!", Toast.LENGTH_SHORT).show();
        }else{
            register.setEnabled(false);
            register.setTextColor(0xFFD0EFC6);
            if(mySQLiteOpenHelper.register(user)!=-1){
                Toast.makeText(this, "注册成功", Toast.LENGTH_SHORT).show();
            }else{
                Toast.makeText(this, "注册失败!", Toast.LENGTH_SHORT).show();
            }
        }
    }
    @SuppressLint("Range")
    public  void query(){
        Cursor cursor= db.query("readbooks",null,null,null,null,null,null);
        if(cursor.moveToFirst()){
            Log.d("ljz action:", "entry query " );
            do{
                bookname = cursor.getString(cursor.getColumnIndex("bookname"));
                picture = cursor.getString(cursor.getColumnIndex("picture"));
                author = cursor.getString(cursor.getColumnIndex("author"));
                address = cursor.getString(cursor.getColumnIndex("address"));
                classify = cursor.getString(cursor.getColumnIndex("classify"));
                Log.d("ljz action:", "bookname:" + bookname);
                Log.d("ljz action:", "picture:" + picture);
                Log.d("ljz action:", "author:" + author);
                Log.d("ljz action:", "address:" + address);
                Log.d("ljz action:", "classify:" + classify);
            }while(cursor.moveToNext());
        }
        cursor.close();
    }
    // 假设你有一个方法来添加几本书到数据库中
    public void addBooksToDB() {
        // 创建几本书的实例
        Books book1 = new Books("云中记","E:\android_studio\yueshudian\app\src\main\res\drawable\book1.png","阿来","https://www.qimao.com/shuku/214405/","课外读物");
        Books book2 = new Books("尘埃落定",  "E:\android_studio\yueshudian\app\src\main\res\drawable\book2.png","阿来","https://www.qimao.com/shuku/202200/","课外读物");
        Books book3 = new Books("红星照耀中国", "E:\android_studio\yueshudian\app\src\main\res\drawable\book3.png","埃德加·斯诺","https://book.qidian.com/info/1015409387/","课外读物");
        Books book4 = new Books("信号与系统",  "E:\android_studio\yueshudian\app\src\main\res\drawable\book4.png","张小虹","https://weread.qq.com/web/bookDetail/1c032310811e42197g013ccc","专业书籍");
//        Books book5 = new Books("通信原理", "E:\android_studio\yueshudian\app\src\main\res\drawable\book5.png"," "," ","专业书籍");
//        Books book6 = new Books("信息论预编码",  "E:\android_studio\yueshudian\app\src\main\res\drawable\book5.png"," "," ","专业书籍");
        if(mySQLiteOpenHelper.bookDB(book1)!=-1&&mySQLiteOpenHelper.bookDB(book2)!=-1&&mySQLiteOpenHelper.bookDB(book3)!=-1&&mySQLiteOpenHelper.bookDB(book4)!=-1){
            Log.d("ljz add books:", "bookadd  successful");
        }else{
            Toast.makeText(this, "添加失败!", Toast.LENGTH_SHORT).show();
        }
//        // 将这些书添加到数据库中
//        bookDB(book1);
//        bookDB(book2);
//        bookDB(book3);
//        bookDB(book4);
//        bookDB(book5);
//        bookDB(book6);
//        Log.d("ljz add books:", "bookadd  successful");
    }
    //监听按钮点击事件
    @SuppressLint("NonConstantResourceId")
    @Override
    public void onClick(View view) {
        int id = view.getId();
        if(id==R.id.registerButton){
                register();
        }
        else if(id==R.id.gotologin){
            goback();
        }
        else if(id==R.id.DBSearchButton){
            Log.d("ljz action:", "DBsearchbutton clicked" );
            db = mySQLiteOpenHelper.getWritableDatabase();
            query();
        }
    }
    @Override
    public void onPointerCaptureChanged(boolean hasCapture) {
        super.onPointerCaptureChanged(hasCapture);
    }
}

登录页面

注册页面布局:loginpage.xml


    
    
    
    

效果展示

Android Studio小组作业·“悦读”app总结,Android Studio小组作业,悦读app开发总结 第4张

LoginActivity

package com.example.yueshudian;
import androidx.appcompat.app.AppCompatActivity;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class LoginActivity extends AppCompatActivity implements View.OnClickListener {
    private Button registerButton,loginButton;
    private EditText username,password;
    private MySQLiteOpenHelper mySQLiteOpenHelper;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        mySQLiteOpenHelper = new MySQLiteOpenHelper(this);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.loginpage);
        find();
    }
    public void find(){
        loginButton = findViewById(R.id.loginButton);
        registerButton = findViewById(R.id.registerButton1);
        username = findViewById(R.id.username1);
        password = findViewById(R.id.password1);
        loginButton.setOnClickListener(this);
        registerButton.setOnClickListener(this);
    }
    @SuppressLint("NonConstantResourceId")
    @Override
    public void onClick(View view) {
        int id = view.getId();
        if (id == R.id.loginButton) {
            String n = username.getText().toString();
            String p = password.getText().toString();
            if (n.equals("")) {
                Toast.makeText(this, "请输入账号", Toast.LENGTH_SHORT).show();
            } else if (p.equals("")) {
                Toast.makeText(this, "请输入密码", Toast.LENGTH_SHORT).show();
            } else {
                boolean login = mySQLiteOpenHelper.login(n, p);
                if (login) {
                    Toast.makeText(this, "登录成功!", Toast.LENGTH_SHORT).show();
                    User select = mySQLiteOpenHelper.select(n);
                    //先去导航页
                    Intent Nav = new Intent(LoginActivity.this, NavigationActivity.class);
                    Bundle bundle = new Bundle();
                    bundle.putString("username", select.username);
                    bundle.putString("emil", select.emil);
                    bundle.putString("phone", select.phone);
                    Nav.putExtras(bundle);
                    username.setText("");
                    password.setText("");
                    startActivity(Nav);
                } else {
                    Toast.makeText(this, "账号或密码错误,请重新输入", Toast.LENGTH_SHORT).show();
                    password.setText("");
                }
            }
        } else if (id == R.id.registerButton1) {
            Intent re = new Intent(LoginActivity.this,RegisterActivity.class);
            startActivity(re);
        }
    }
    @Override
    public void onPointerCaptureChanged(boolean hasCapture) {
        super.onPointerCaptureChanged(hasCapture);
    }
}

保存数据库后可以通过该工具查看DB内的信息,在settings内下载并apply(后面的图片均为以前的图,与我创建表不同)有时候保存db会死机,因为没删掉,其实就是bug,有时候删了也会死机,一运行就产生db文件,所以我后面也无法查看我的db文件了,只能用以前保存的db的给大家看一下。

Android Studio小组作业·“悦读”app总结,Android Studio小组作业,悦读app开发总结 第5张

右键保存该数据库到自己的文件夹,然后用connection连接

Android Studio小组作业·“悦读”app总结,Android Studio小组作业,悦读app开发总结 第6张

连接后如下所示:

Android Studio小组作业·“悦读”app总结,Android Studio小组作业,悦读app开发总结 第7张

点击表可以查看,信息如下:

Android Studio小组作业·“悦读”app总结,Android Studio小组作业,悦读app开发总结 第8张

 


Fragment导航栏自定义修改

在三个基础上在添加一个

如下,模仿下面三个activity再创建一个Che(意思是购物车,本来想建购物车页面的),后面这个用来表示“书架”了。

Android Studio小组作业·“悦读”app总结,Android Studio小组作业,悦读app开发总结 第9张

NavigationActivity

修改一下,添加R.id.navigation_che进去

package com.example.yueshudian;
import android.os.Bundle;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import com.example.yueshudian.databinding.ActivityNavigationBinding;
public class NavigationActivity extends AppCompatActivity {
    private ActivityNavigationBinding binding;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityNavigationBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        BottomNavigationView navView = findViewById(R.id.nav_view);
        // Passing each menu ID as a set of Ids because each
        // menu should be considered as top level destinations.
        AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
                R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications,R.id.navigation_che)
                .build();
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_navigation);
        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
        NavigationUI.setupWithNavController(binding.navView, navController);
    }
}

activity_navigation.xml

不要忘了改导航栏的布局文件,这里面不需要改,展示一下

    
    

fragmen_che.xml

别忘了添加一个xml

Android Studio小组作业·“悦读”app总结,Android Studio小组作业,悦读app开发总结 第10张

menu布局

修改导航栏的名称,添加多一个item


    
    
    
    

navigation文件

同上,复制粘贴原布局代码即可,稍微修改一点

Android Studio小组作业·“悦读”app总结,Android Studio小组作业,悦读app开发总结 第11张


完善四个Fragment页面

首页

    
    
        
        
        
        
    
        
        
    
    

 

Android Studio小组作业·“悦读”app总结,Android Studio小组作业,悦读app开发总结 第12张

分类

    
        
        
    
    

Android Studio小组作业·“悦读”app总结,Android Studio小组作业,悦读app开发总结 第13张

书架


    
    
        
        
    
    
        
        
    
    
        
        
    
    

Android Studio小组作业·“悦读”app总结,Android Studio小组作业,悦读app开发总结 第14张

我的


    
    
    
    
    
    
    
        
        
            
            
        
    
        
        
        
            
            
            
            
                
                
            
            
                
                
            
            
                
                
            
            
                
                
            
        
    
        
        
            
            
        
        
        
            
            
        
        
        
            
            
        
        
        
            
            
        
        
    
    

Android Studio小组作业·“悦读”app总结,Android Studio小组作业,悦读app开发总结 第15张


各页面响应代码

首页

package com.example.yueshudian.ui.home;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import com.example.yueshudian.BookDetailActivity;
import com.example.yueshudian.Books;
import com.example.yueshudian.LoginActivity;
import com.example.yueshudian.MySQLiteOpenHelper;
import com.example.yueshudian.NavigationActivity;
import com.example.yueshudian.R;
import com.example.yueshudian.User;
import com.example.yueshudian.databinding.FragmentDashboardBinding;
import com.example.yueshudian.databinding.FragmentHomeBinding;
public class HomeFragment extends Fragment {
    private FragmentHomeBinding binding;
    private MySQLiteOpenHelper mySQLiteOpenHelper;
    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        HomeViewModel homeViewModel =
                new ViewModelProvider(this).get(HomeViewModel.class);
        binding = FragmentHomeBinding.inflate(inflater, container, false);
        View root = binding.getRoot();
        final TextView textView = binding.textHome;
        homeViewModel.getText().observe(getViewLifecycleOwner(), textView::setText);
        return root;
    }
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        //搜索响应
        ImageView search = (ImageView) getActivity().findViewById(R.id.searchButton);
        search.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent bookdetail = new Intent(getActivity(), BookDetailActivity.class);//与普通Activity中不同,用getActivity()
                startActivity(bookdetail);
                Toast.makeText(getActivity(), "search successful", Toast.LENGTH_LONG).show();
            }
        });
        //点击图片跳转响应
        ImageView chengai = (ImageView) getActivity().findViewById(R.id.chengai);
        chengai.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent bookdetail = new Intent(getActivity(), BookDetailActivity.class);//与普通Activity中不同,用getActivity()
                startActivity(bookdetail);
                Toast.makeText(getActivity(), "search successful", Toast.LENGTH_LONG).show();
            }
        });
        //输入内容响应
        TextView searchEditText = (TextView) getActivity().findViewById(R.id.searchEditText);
        searchEditText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String n = searchEditText.getText().toString();
                if (n.equals("")) {
                    Toast.makeText(getActivity(), "请输入书籍名称", Toast.LENGTH_SHORT).show();
                } else {
                    boolean searchbook = mySQLiteOpenHelper.searchbook(n);
                    if (searchbook) {
                        Toast.makeText(getActivity(), "搜索成功!", Toast.LENGTH_SHORT).show();
                        Books selectbook = mySQLiteOpenHelper.selectbook(n);
                        Intent Nav = new Intent(getActivity(), BookDetailActivity.class);
                        Bundle bundle = new Bundle();
                        bundle.putString("bookname", selectbook.bookname);
                        Nav.putExtras(bundle);
                        startActivity(Nav);
                    } else {
                        Toast.makeText(getActivity(), "搜索失败!", Toast.LENGTH_SHORT).show();
                    }
                }
            }
        });
    }
}

分类

package com.example.yueshudian.ui.dashboard;
import static com.example.yueshudian.R.id.listViewDirectory;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import com.example.yueshudian.R;
import com.example.yueshudian.databinding.FragmentDashboardBinding;
import android.content.Intent;
import android.net.Uri;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class DashboardFragment extends Fragment {
    private FragmentDashboardBinding binding;
    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_dashboard, container, false);
        // 初始化数据
        List directoryItems = new ArrayList();
        directoryItems.add("云中记");
        directoryItems.add("尘埃落定");
        directoryItems.add("红星照耀中国");
        directoryItems.add("通信原理");
        directoryItems.add("信号与系统");
        directoryItems.add("信息论与编码");
        directoryItems.add("微机原理");
        directoryItems.add("老子他说");
        directoryItems.add("电磁场与电磁波");
        directoryItems.add("命若琴弦");
        directoryItems.add("有人自林中坠落");
        directoryItems.add("C++程序设计");
        directoryItems.add("高频电子线路");
        directoryItems.add("数字图像处理");
        directoryItems.add("虚拟仪器");
        directoryItems.add("线性代数");
        // 获取 ListView
        ListView listViewDirectory = view.findViewById(R.id.listViewDirectory);
        // 设置 Adapter
        ArrayAdapter adapter = new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_1, directoryItems);
        listViewDirectory.setAdapter(adapter);
        // 设置点击事件监听器
        listViewDirectory.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView parent, View view, int position, long id) {
                String itemText = directoryItems.get(position);
                String url = null;
                switch (itemText) {
                    case "云中记":
                        url = "https://www.qimao.com/shuku/214405/";
                        break;
                    case "尘埃落定":
                        url = "https://www.qimao.com/shuku/202200/";
                        break;
                    case "红星照耀中国":
                        url = "https://book.qidian.com/info/1015409387";
                        break;
                    case "信号与系统":
                        url = "https://weread.qq.com/web/bookDetail/1c032310811e42197g013ccc";
                        break;
                    default:
                        Toast.makeText(getActivity(), "错误!无该书籍信息", Toast.LENGTH_SHORT).show();
                        break;
                }
                if (url != null) {
                    Intent intent = new Intent(Intent.ACTION_VIEW);
                    intent.setData(Uri.parse(url));
                    startActivity(intent);
                } else {
                    Toast.makeText(getActivity(), "网页加载失败!", Toast.LENGTH_SHORT).show();
                }
            }
        });
        return view;
    }
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }
}

书架

package com.example.yueshudian.ui.Che;//原来叫购物车,改成了书架
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import com.example.yueshudian.BookDetailActivity;
import com.example.yueshudian.Books;
import com.example.yueshudian.R;
import com.example.yueshudian.databinding.FragmentCheBinding;
import com.example.yueshudian.databinding.FragmentDashboardBinding;
public class CheFragment extends Fragment {
    private FragmentCheBinding binding;
    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        CheViewModel CheViewModel =
                new ViewModelProvider(this).get(CheViewModel.class);
        binding = FragmentCheBinding.inflate(inflater, container, false);
        View root = binding.getRoot();
        final TextView textView = binding.textChe;
        CheViewModel.getText().observe(getViewLifecycleOwner(), textView::setText);
        return root;
    }
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        //添加书本响应
        ImageView addbook = (ImageView) getActivity().findViewById(R.id.addbook);
        addbook.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent sliptocatagory = new Intent(getActivity(), BookDetailActivity.class);//与普通Activity中不同,用getActivity()
                startActivity(sliptocatagory);
            }
        });
        //阅读book1
        ImageView book1 = (ImageView) getActivity().findViewById(R.id.book1);
        book1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String url = "https://www.qimao.com/shuku/214405/";
                Intent intent = new Intent(Intent.ACTION_VIEW);
                intent.setData(Uri.parse(url));
                startActivity(intent);
            }
        });
        //其他书本同操作
    }
}

我的

package com.example.yueshudian.ui.notifications;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.fragment.FragmentNavigator;
import com.example.yueshudian.BookDetailActivity;
import com.example.yueshudian.R;
import com.example.yueshudian.databinding.FragmentDashboardBinding;
import com.example.yueshudian.databinding.FragmentNotificationsBinding;
public class NotificationsFragment extends Fragment {
    private FragmentNotificationsBinding binding;
    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        NotificationsViewModel notificationsViewModel =
                new ViewModelProvider(this).get(NotificationsViewModel.class);
        binding = FragmentNotificationsBinding.inflate(inflater, container, false);
        View root = binding.getRoot();
        final TextView textView = binding.textNotifications;
        notificationsViewModel.getText().observe(getViewLifecycleOwner(), textView::setText);
        return root;
    }
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        //联系客服
        TextView search = (TextView) getActivity().findViewById(R.id.callphone);
        search.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                callPhone();
            }
        });
        //输入内容响应
    }
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }
    public void callPhone() {
        try {
            Intent intent = new Intent(Intent.ACTION_DIAL);
            intent.setData(Uri.parse("tel:10086"));
            // 确保Fragment所在的Activity存在
            FragmentActivity activity = getActivity();
            if (activity != null) {
                activity.startActivity(intent);
            } else {
                // Fragment可能还没有被附加到Activity上,此时可以处理错误或等待合适的时机
                Toast.makeText(getActivity(), "callphone failed", Toast.LENGTH_LONG).show();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

AndroidManifest.xml

千万不要忘记在这边声明权限,还有一些activity


    
    
    
    
        
        
        
        
            
                
                
            
        
    

最后说一下我出现的一些问题

1.小米真机调试无法显示logcat内容,解决方法如下:

Android Studio小组作业·“悦读”app总结,Android Studio小组作业,悦读app开发总结 第16张

但是试了没有用,后面发现是没有执行到Log.d就出错了,所以跟这个无关,但是要是出现了问题也可以查看一下这个解决方法。

2.一直创建表不成功,记得再三查看这部分代码,看参数名称,还有类型,后面要是有一点点不一样就会报错。折磨了我好久,后面发现就是这里和Books类那边有出入!

Android Studio小组作业·“悦读”app总结,Android Studio小组作业,悦读app开发总结 第17张

报错没保存,但是看我的搜索记录就可以看出来问题所在:

Android Studio小组作业·“悦读”app总结,Android Studio小组作业,悦读app开发总结 第18张

Android Studio小组作业·“悦读”app总结,Android Studio小组作业,悦读app开发总结 第19张

参考博文有:

http://t.csdnimg.cn/qR41o

http://t.csdnimg.cn/iD00o


太晚了,抓紧睡觉!演示效果看我的主页,还在审核,不想等了。

 

 


0
收藏0
文章版权声明:除非注明,否则均为VPS857原创文章,转载或复制请以超链接形式并注明出处。

相关阅读

  • 【研发日记】Matlab/Simulink自动生成代码(二)——五种选择结构实现方法,Matlab/Simulink自动生成代码的五种选择结构实现方法(二),Matlab/Simulink自动生成代码的五种选择结构实现方法详解(二)
  • 超级好用的C++实用库之跨平台实用方法,跨平台实用方法的C++实用库超好用指南,C++跨平台实用库使用指南,超好用实用方法集合,C++跨平台实用库超好用指南,方法与技巧集合
  • 【动态规划】斐波那契数列模型(C++),斐波那契数列模型(C++实现与动态规划解析),斐波那契数列模型解析与C++实现(动态规划)
  • 【C++】,string类底层的模拟实现,C++中string类的模拟底层实现探究
  • uniapp 小程序实现微信授权登录(前端和后端),Uniapp小程序实现微信授权登录全流程(前端后端全攻略),Uniapp小程序微信授权登录全流程攻略,前端后端全指南
  • Vue脚手架的安装(保姆级教程),Vue脚手架保姆级安装教程,Vue脚手架保姆级安装指南,Vue脚手架保姆级安装指南,从零开始教你如何安装Vue脚手架
  • 如何在树莓派 Raspberry Pi中本地部署一个web站点并实现无公网IP远程访问,树莓派上本地部署Web站点及无公网IP远程访问指南,树莓派部署Web站点及无公网IP远程访问指南,本地部署与远程访问实践,树莓派部署Web站点及无公网IP远程访问实践指南,树莓派部署Web站点及无公网IP远程访问实践指南,本地部署与远程访问详解,树莓派部署Web站点及无公网IP远程访问实践详解,本地部署与远程访问指南,树莓派部署Web站点及无公网IP远程访问实践详解,本地部署与远程访问指南。
  • vue2技术栈实现AI问答机器人功能(流式与非流式两种接口方法),Vue2技术栈实现AI问答机器人功能,流式与非流式接口方法探究,Vue2技术栈实现AI问答机器人功能,流式与非流式接口方法详解
  • 发表评论

    快捷回复:表情:
    评论列表 (暂无评论,0人围观)

    还没有评论,来说两句吧...

    目录[+]

    取消
    微信二维码
    微信二维码
    支付宝二维码