温馨提示:这篇文章已超过440天没有更新,请注意相关的内容是否还可用!
在Android Studio环境下开发的“悦读”app项目圆满完成。本次小组作业历经数月,我们共同协作,完成了app的各项功能开发。该app旨在为用户提供便捷的阅读体验,包括书籍推荐、在线阅读、阅读设置等功能。我们克服了许多技术难题,最终实现了流畅的用户界面和高效的性能表现。此次合作不仅提升了我们的技术能力,也锻炼了团队协作的能力。“悦读”app得到了良好的用户反馈,我们将继续优化和完善产品。
本人是小白,初学安卓,所以只能制作一个简陋的“毛坯房”。一开始想设计书店,使用安卓自带的sqlite数据库保存书本信息,然后通过搜索匹配有的书籍显示在搜索页面,添加进入购物车,选择数量后完成支付,相应的数据库内图书的数量也会发生变化。
这是我的预想效果,但实际操作起来难度很大,并且我对安卓数据库了解不足,所以就抛弃了这方案,选择老师上课讲解的一些控件来写应用,思路也从“书店”转为了更为简单些的“阅读器”。(我最后完成的内容真的很简单很简单,但是也花了我很长时间,这个主要是因为一开始我还没学会爬就想跑,有点心切)
下面我来介绍一下我的设计思路
设计框图
手绘如下:
点击app首先进入的是注册页,输入账户名,密码,电话和邮箱后点击注册,即可注册成功。数据会保存在user表中。
点击返回登录,会进入登录页面,登录页只需要输入账户和密码,核对无误后可以登录成功;
我使用了安卓自带的导航栏模板,本身有三个页面,后面还增加了一个fragment;
点击登录后进入首页,有搜索框和搜索按钮,还有热门推荐书籍图片;点击搜索和热门推荐图片会进入书籍详情页。
点击分类页,本想设计一个类似“京东”等购物平台有的分类页,但是太难了,后面放弃,使用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是用于查看已建立的图书表信息的
布局效果
对应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
效果展示
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的给大家看一下。
右键保存该数据库到自己的文件夹,然后用connection连接
连接后如下所示:
点击表可以查看,信息如下:
Fragment导航栏自定义修改
在三个基础上在添加一个
如下,模仿下面三个activity再创建一个Che(意思是购物车,本来想建购物车页面的),后面这个用来表示“书架”了。
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
menu布局
修改导航栏的名称,添加多一个item
navigation文件
同上,复制粘贴原布局代码即可,稍微修改一点
完善四个Fragment页面
首页
分类
书架
我的
各页面响应代码
首页
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内容,解决方法如下:
但是试了没有用,后面发现是没有执行到Log.d就出错了,所以跟这个无关,但是要是出现了问题也可以查看一下这个解决方法。
2.一直创建表不成功,记得再三查看这部分代码,看参数名称,还有类型,后面要是有一点点不一样就会报错。折磨了我好久,后面发现就是这里和Books类那边有出入!
报错没保存,但是看我的搜索记录就可以看出来问题所在:
参考博文有:
http://t.csdnimg.cn/qR41o
http://t.csdnimg.cn/iD00o
太晚了,抓紧睡觉!演示效果看我的主页,还在审核,不想等了。
还没有评论,来说两句吧...