Android项目实战系列—基于博学谷(七)课程模块(中)

image

由于这个模块内容较多,分为上、中、下 三篇博客分别来讲述,请耐心阅读。


课程模块分为四个部分

  • [ ] 课程列表
  • [x] 课程详情
  • [ ] 视频播放
  • [ ] 播放记录

课程模块(中)主要讲述课程详情部分

一、课程详情界面

1、创建课程详情界面

com.boxuegu.activity包中创建一个Java类命名为VideoListActivity。在res/layout文件夹下创建一个布局文件,命名为activity_video_list

2、导入界面图片 default_video_list_icon.pngvodeo_list_intro_icon.png

3、界面代码——activity_video_list.xml

1<?xml version="1.0" encoding="utf-8"?> 2<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:background="@android:color/white" 6 android:orientation="vertical"> 7 <TextView 8 android:layout_width="fill_parent" 9 android:layout_height="200dp" 10 android:background="@drawable/default_video_list_icon"/> 11 <LinearLayout 12 android:layout_width="fill_parent" 13 android:layout_height="50dp" 14 android:gravity="center" 15 android:orientation="horizontal"> 16 <RelativeLayout 17 android:layout_width="0dp" 18 android:layout_height="fill_parent" 19 android:layout_weight="1" 20 android:background="@drawable/video_list_intro_icon"> 21 <TextView 22 android:layout_width="fill_parent" 23 android:layout_height="46dp" 24 android:id="@+id/tv_intro" 25 android:layout_centerVertical="true" 26 android:background="#30B4FF" 27 android:gravity="center" 28 android:text="简 介" 29 android:textColor="#FFFFFF" 30 android:textSize="20sp"/> 31 </RelativeLayout> 32 <View 33 android:layout_width="1dp" 34 android:layout_height="48dp" 35 android:background="#C3C3C3"/> 36 <RelativeLayout 37 android:layout_width="0dp" 38 android:layout_height="fill_parent" 39 android:layout_weight="1" 40 android:background="@drawable/video_list_intro_icon"> 41 <TextView 42 android:layout_width="fill_parent" 43 android:layout_height="46dp" 44 android:id="@+id/tv_video" 45 android:layout_centerVertical="true" 46 android:background="#FFFFFF" 47 android:gravity="center" 48 android:text="视 频" 49 android:textColor="#000000" 50 android:textSize="20sp"/> 51 </RelativeLayout> 52 </LinearLayout> 53 <RelativeLayout 54 android:layout_width="fill_parent" 55 android:layout_height="fill_parent"> 56 <ListView 57 android:layout_width="fill_parent" 58 android:layout_height="fill_parent" 59 android:id="@+id/lv_video_list" 60 android:layout_marginLeft="15dp" 61 android:layout_marginRight="15dp" 62 android:divider="#E4E4E4" 63 android:dividerHeight="1dp" 64 android:scrollbars="none" 65 android:visibility="gone"/> 66 <ScrollView 67 android:layout_width="fill_parent" 68 android:layout_height="fill_parent" 69 android:id="@+id/sv_chapter_intro"> 70 <LinearLayout 71 android:layout_width="fill_parent" 72 android:layout_height="fill_parent" 73 android:orientation="horizontal"> 74 <TextView 75 android:layout_width="fill_parent" 76 android:layout_height="fill_parent" 77 android:id="@+id/tv_chapter_intro" 78 android:lineSpacingMultiplier="1.5" 79 android:padding="10dp" 80 android:text="wordpress简介" 81 android:textColor="@android:color/black" 82 android:textSize="14sp"/> 83 </LinearLayout> 84 </ScrollView> 85 </RelativeLayout> 86 87</LinearLayout>

二、课程详情界面Item

1、创建课程详情界面item

res/layout文件夹下创建一个布局文件,命名为video_list_item。导入所需图片 course_bar_icon.png

2、界面代码——video_list_item.xml

1<?xml version="1.0" encoding="utf-8"?> 2<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:orientation="horizontal" 4 android:layout_width="match_parent" 5 android:layout_height="wrap_content" 6 android:background="@android:color/white" 7 android:gravity="center_vertical" 8 android:paddingBottom="15dp" 9 android:paddingTop="15dp"> 10 <ImageView 11 android:id="@+id/iv_left_icon" 12 android:layout_width="25dp" 13 android:layout_height="25dp" 14 android:src="@drawable/course_bar_icon" /> 15 <TextView 16 android:id="@+id/tv_video_title" 17 android:layout_width="wrap_content" 18 android:layout_height="fill_parent" 19 android:layout_marginLeft="10dp" 20 android:gravity="center_vertical" 21 android:textColor="#333333" 22 android:textSize="14sp"/> 23</LinearLayout>

三、创建VideoBean

com.boxuegu.bean包中创建一个VideoBean类,用来创建视频的所有属性。
1package com.boxuegu.bean; 2 3public class VideoBean { 4 public int chapterId; //章节ID 5 public int videoId; //视频ID 6 public String title; //章节标题 7 public String secondTitle; //视频标题 8 public String videoPath; //视频播放地址 9}

四、课程界面Adapter

com.boxuegu.adapter包中创建一个VideoListAdapter类。代码如下:
1package com.boxuegu.adapter; 2 3import android.content.Context; 4import android.graphics.Color; 5import android.view.LayoutInflater; 6import android.view.View; 7import android.view.ViewGroup; 8import android.widget.BaseAdapter; 9import android.widget.ImageView; 10import android.widget.TextView; 11import java.util.List; 12import com.boxuegu.R; 13import com.boxuegu.bean.VideoBean; 14 15//列表 16public class VideoListAdapter extends BaseAdapter{ 17 18 private Context mContext; 19 private List<VideoBean> vbl; //视频列表数据 20 private int selectedPosition = -1; //点击时选中的位置 21 private OnSelectListener onSelectListener; 22 public VideoListAdapter(Context context,OnSelectListener onSelectListener){ 23 this.mContext = context; 24 this.onSelectListener = onSelectListener; 25 } 26 27 public void setSelectedPosition(int position){ 28 selectedPosition = position; 29 } 30 31 //设置数据更新界面 32 public void setData(List<VideoBean> vbl){ 33 this.vbl = vbl; 34 notifyDataSetChanged(); 35 } 36 37 //获取Item的总数 38 @Override 39 public int getCount() { 40 return vbl == null ? 0 : vbl.size(); 41 } 42 43 //根据position得到item对应的对象 44 @Override 45 public VideoBean getItem(int position) { 46 return vbl == null ? null : vbl.get(position); 47 } 48 49 //根据position得到item对应的ID 50 @Override 51 public long getItemId(int position) { 52 return position; 53 } 54 55 //得到对应position的item视图 56 @Override 57 public View getView(final int position, View view, ViewGroup viewGroup) { 58 final ViewHolder vh; 59 if (view == null){ 60 vh = new ViewHolder(); 61 view = LayoutInflater.from(mContext).inflate( 62 R.layout.video_list_item,null 63 ); 64 vh.tv_title = (TextView) view.findViewById(R.id.tv_video_title); 65 vh.iv_icon = (ImageView) view.findViewById(R.id.iv_left_icon); 66 view.setTag(vh); 67 }else { 68 vh = (ViewHolder) view.getTag(); 69 } 70 final VideoBean bean = getItem(position); 71 vh.iv_icon.setImageResource(R.drawable.course_bar_icon); 72 vh.tv_title.setTextColor(Color.parseColor("#333333")); 73 if (bean!=null){ 74 vh.tv_title.setText(bean.secondTitle); 75 //设置选中效果 76 if (selectedPosition == position){ 77 vh.iv_icon.setImageResource(R.drawable.course_intro_icon); 78 vh.tv_title.setTextColor(Color.parseColor("#009958")); 79 80 }else { 81 vh.iv_icon.setImageResource(R.drawable.course_bar_icon); 82 vh.tv_title.setTextColor(Color.parseColor("#333333")); 83 } 84 } 85 view.setOnClickListener(new View.OnClickListener() { 86 @Override 87 public void onClick(View view) { 88 if (bean == null) 89 return; 90 //播放视频 91 onSelectListener.onSelect(position,vh.iv_icon); 92 } 93 }); 94 return view; 95 } 96 97 class ViewHolder{ 98 public TextView tv_title; 99 public ImageView iv_icon; 100 } 101 102 //创建接口,传递position和ImageView 103 public interface OnSelectListener{ 104 void onSelect(int position,ImageView iv); 105 } 106}

五、视频列表数据的存放

1、Eclipse新建json文件,并改变文件的编码。

assets文件夹中右键,选择new,点击file

image

文件名输入data.json

image

由于默认的编码会导致软件运行以后中文出现乱码。在data.json文件里面,使用Alt+Enter快捷键弹出修改编码的对话框,编码方式选择UTF-8即可。

image

2、data.json代码如下:

1[ 2 { 3 "chapterId": 1, 4 "videoId": "1", 5 "title": "第1章 博客(网站)简介", 6 "secondTitle": "什么是博客", 7 "videoPath": "video11.mp4" 8 }, 9 { 10 "chapterId": 1, 11 "videoId": "2", 12 "title": "第1章 博客(网站)简介", 13 "secondTitle": "网站与博客的关系", 14 "videoPath": "beyond.mp4" 15 }, 16 { 17 "chapterId": 2, 18 "videoId": "1", 19 "title": "第2章 Linux系统简介", 20 "secondTitle": "认识Linux", 21 "videoPath": "" 22 }, 23 { 24 "chapterId": 2, 25 "videoId": "2", 26 "title": "第2章 Linux系统简介", 27 "secondTitle": "CentOS 7简单操作", 28 "videoPath": "" 29 }, 30 { 31 "chapterId": 3, 32 "videoId": "1", 33 "title": "第3章 WordPress简介", 34 "secondTitle": "动态博客系统", 35 "videoPath": "" 36 }, 37 { 38 "chapterId": 3, 39 "videoId": "2", 40 "title": "第3章 WordPress简介", 41 "secondTitle": "WordPress系统", 42 "videoPath": "" 43 }, 44 { 45 "chapterId": 4, 46 "videoId": "1", 47 "title": "第4章 安装MySQL数据库", 48 "secondTitle": "MySQL数据库简介", 49 "videoPath": "" 50 }, 51 { 52 "chapterId": 4, 53 "videoId": "2", 54 "title": "第4章 安装MySQL数据库", 55 "secondTitle": "安装MySQL数据库", 56 "videoPath": "" 57 }, 58 { 59 "chapterId": 5, 60 "videoId": "1", 61 "title": "第5章 数据存储服务器", 62 "secondTitle": "常见的服务器", 63 "videoPath": "" 64 }, 65 { 66 "chapterId": 5, 67 "videoId": "2", 68 "title": "第5章 数据存储服务器", 69 "secondTitle": "Nginx的安装", 70 "videoPath": "" 71 }, 72 { 73 "chapterId": 6, 74 "videoId": "1", 75 "title": "第6章 安装PHP环境", 76 "secondTitle": "PHP语法简介", 77 "videoPath": "" 78 }, 79 { 80 "chapterId": 6, 81 "videoId": "2", 82 "title": "第6章 安装PHP环境", 83 "secondTitle": "安装PHP", 84 "videoPath": "" 85 }, 86 { 87 "chapterId": 7, 88 "videoId": "1", 89 "title": "第7章 云服务器的购买", 90 "secondTitle": "购买云服务器", 91 "videoPath": "" 92 }, 93 { 94 "chapterId": 7, 95 "videoId": "2", 96 "title": "第7章 云服务器的购买", 97 "secondTitle": "云服务器的简单配置", 98 "videoPath": "" 99 }, 100 { 101 "chapterId": 8, 102 "videoId": "1", 103 "title": "第8章 域名购买及备案", 104 "secondTitle": "购买域名", 105 "videoPath": "" 106 }, 107 { 108 "chapterId": 8, 109 "videoId": "2", 110 "title": "第8章 域名购买及备案", 111 "secondTitle": "域名备案", 112 "videoPath": "" 113 }, 114 { 115 "chapterId": 9, 116 "videoId": "1", 117 "title": "第9章 安装WordPress", 118 "secondTitle": "安装前准备", 119 "videoPath": "" 120 }, 121 { 122 "chapterId": 9, 123 "videoId": "2", 124 "title": "第9章 安装WordPress", 125 "secondTitle": "安装WordPress", 126 "videoPath": "" 127 }, 128 { 129 "chapterId": 10, 130 "videoId": "1", 131 "title": "第10章 WordPress简单设置", 132 "secondTitle": "更换博客主题", 133 "videoPath": "" 134 }, 135 { 136 "chapterId": 10, 137 "videoId": "2", 138 "title": "第10章 WordPress简单设置", 139 "secondTitle": "博客基本布局设置", 140 "videoPath": "" 141 } 142]

六、课程详情界面逻辑代码

1、界面代码——VideoListActivity.java

1package com.boxuegu.activity; 2 3import android.content.Context; 4import android.content.Intent; 5import android.content.SharedPreferences; 6import android.content.pm.ActivityInfo; 7import android.graphics.Color; 8import android.support.annotation.NonNull; 9import android.support.v7.app.AppCompatActivity; 10import android.os.Bundle; 11import android.text.TextUtils; 12import android.view.View; 13import android.widget.ImageView; 14import android.widget.ListView; 15import android.widget.ScrollView; 16import android.widget.TextView; 17import android.widget.Toast; 18import org.json.JSONArray; 19import org.json.JSONObject; 20import java.io.BufferedReader; 21import java.io.IOException; 22import java.io.InputStream; 23import java.io.InputStreamReader; 24import java.util.ArrayList; 25import java.util.List; 26import com.boxuegu.R; 27import com.boxuegu.adapter.VideoListAdapter; 28import com.boxuegu.bean.VideoBean; 29import com.boxuegu.utils.AnalysisUtils; 30import com.boxuegu.utils.DBUtils; 31 32public class VideoListActivity extends AppCompatActivity implements View.OnClickListener { 33 34 private String intro; 35 private int chapterId; 36 private DBUtils db; 37 private ArrayList<VideoBean> videoList; 38 private TextView tv_intro; 39 private TextView tv_video; 40 private ListView lv_video_list; 41 private TextView tv_chapter_intro; 42 private ScrollView sv_chapter_intro; 43 private VideoListAdapter adapter; 44 45 @Override 46 protected void onCreate(Bundle savedInstanceState) { 47 super.onCreate(savedInstanceState); 48 setContentView(R.layout.activity_video_list); 49 //设置界面为视频 50 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 51 //从课程界面传过来的章节ID 52 chapterId = getIntent().getIntExtra("id", 0); 53 //从课程界面传过来的章节简介 54 intro = getIntent().getStringExtra("intro"); 55 db = DBUtils.getInstance(VideoListActivity.this); 56 initData(); 57 initView(); 58 59 } 60 61 //初始化界面UI控件 62 private void initView() { 63 tv_intro = (TextView) findViewById(R.id.tv_intro); 64 tv_video = (TextView) findViewById(R.id.tv_video); 65 lv_video_list = (ListView) findViewById(R.id.lv_video_list); 66 tv_chapter_intro = (TextView) findViewById(R.id.tv_chapter_intro); 67 sv_chapter_intro = (ScrollView)findViewById(R.id.sv_chapter_intro); 68 adapter = new VideoListAdapter(this, new VideoListAdapter.OnSelectListener() { 69 @Override 70 public void onSelect(int position, ImageView iv) { 71 adapter.setSelectedPosition(position); //设置适配器的选中项 72 VideoBean bean = videoList.get(position); 73 String videoPath = bean.videoPath; 74 //notifyDataSetChanged刷新UI 75 adapter.notifyDataSetChanged(); 76 if (TextUtils.isEmpty(videoPath)){ 77 Toast.makeText(VideoListActivity.this,"本地没有此视频,暂时无法播放",Toast.LENGTH_SHORT).show(); 78 return; 79 }else { 80 //判断用户是否登录,若登录则把视频添加到记录中 81 if (readLoginStatus()){ 82 String userName = AnalysisUtils.readLoginUserName(VideoListActivity.this); 83 db.saveVideoPlayList(videoList.get(position),userName); 84 85 } 86 //跳转到视频播放界面 87 88 } 89 } 90 }); 91 lv_video_list.setAdapter(adapter); 92 tv_intro.setOnClickListener(this); 93 tv_video.setOnClickListener(this); 94 adapter.setData(videoList); 95 tv_chapter_intro.setText(intro); 96 tv_intro.setBackgroundColor(Color.parseColor("#30B4FF")); 97 tv_video.setBackgroundColor(Color.parseColor("#FFFFFF")); 98 tv_intro.setTextColor(Color.parseColor("#FFFFFF")); 99 tv_video.setTextColor(Color.parseColor("#000000")); 100 101 102 } 103 /** 104 * 设置视频列表本地数据 105 */ 106 private void initData() { 107 //多个视频,用jsonArray 108 JSONArray jsonArray; 109 InputStream is = null; 110 try { 111 is = getResources().getAssets().open("data.json"); 112 jsonArray = new JSONArray(read(is)); 113 videoList = new ArrayList<VideoBean>(); 114 for (int i = 0;i < jsonArray.length();i++){ 115 VideoBean bean = new VideoBean(); 116 JSONObject jsonObj = jsonArray.getJSONObject(i); 117 if(jsonObj.getInt("chapterId") == chapterId){ 118 bean.chapterId = jsonObj.getInt("chapterId"); 119 bean.videoId = Integer.parseInt(jsonObj.getString("videoId")); 120 bean.title = jsonObj.getString("title"); 121 bean.secondTitle = jsonObj.getString("secondTitle"); 122 bean.videoPath = jsonObj.getString("videoPath"); 123 videoList.add(bean); 124 } 125 bean = null; 126 } 127 128 } catch (Exception e) { 129 e.printStackTrace(); 130 } 131 132 } 133/* 134 *读取数据流,参数in就是数据流,把输入流转换成字符串 135 */ 136 137 private String read(InputStream in) { 138 BufferedReader reader = null; 139 StringBuilder sb = null; 140 String line = null; 141 try { 142 sb = new StringBuilder(); //实例化一个StringBulider对象 143 //InoutStreamReader把in字节流转换成字符流 144 reader = new BufferedReader(new InputStreamReader(in)); 145 while ((line = reader.readLine()) != null) { 146 sb.append(line); 147 sb.append("\n"); 148 } 149 } catch (IOException e) { 150 e.printStackTrace(); 151 return ""; 152 } finally { 153 if (in != null) { 154 try { 155 in.close(); 156 } catch (IOException e) { 157 e.printStackTrace(); 158 } 159 } 160 if (reader != null) { 161 try { 162 reader.close(); 163 } catch (IOException e) { 164 e.printStackTrace(); 165 } 166 } 167 } 168 return sb.toString(); 169 } 170 171 /** 172 * 从SharedPreferences读取登录状态 173 */ 174 175 private boolean readLoginStatus() { 176 SharedPreferences sp = getSharedPreferences("loginInfo", Context.MODE_PRIVATE); 177 boolean isLogin = sp.getBoolean("isLogin",false); 178 return isLogin; 179 } 180 181 @Override 182 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 183 super.onActivityResult(requestCode, resultCode, data); 184 if (data!=null){ 185 // 186 int position = data.getIntExtra("position",0); 187 adapter.setSelectedPosition(position); 188 // 189 lv_video_list.setVisibility(View.VISIBLE); 190 sv_chapter_intro.setVisibility(View.GONE); 191 tv_intro.setBackgroundColor(Color.parseColor("#FFFFFF")); 192 tv_video.setBackgroundColor(Color.parseColor("#30B4FF")); 193 tv_intro.setTextColor(Color.parseColor("#000000")); 194 tv_video.setTextColor(Color.parseColor("#FFFFFF")); 195 196 } 197 } 198 199 @Override 200 public void onClick(View view) { 201 switch (view.getId()){ 202 case R.id.tv_intro: //简介 203 lv_video_list.setVisibility(View.GONE); 204 sv_chapter_intro.setVisibility(View.VISIBLE); 205 tv_intro.setBackgroundColor(Color.parseColor("#30B4FF")); 206 tv_video.setBackgroundColor(Color.parseColor("#FFFFFF")); 207 tv_intro.setTextColor(Color.parseColor("#FFFFFF")); 208 tv_video.setTextColor(Color.parseColor("#000000")); 209 break; 210 case R.id.tv_video: //视频 211 lv_video_list.setVisibility(View.VISIBLE); 212 sv_chapter_intro.setVisibility(View.GONE); 213 tv_intro.setBackgroundColor(Color.parseColor("#FFFFFF")); 214 tv_intro.setTextColor(Color.parseColor("#000000")); 215 tv_video.setBackgroundColor(Color.parseColor("#30B4FF")); 216 tv_video.setTextColor(Color.parseColor("#FFFFFF")); 217 break; 218 default: 219 break; 220 } 221 } 222} 223

2、修改代码

(1)、找到SQLiteHelper.java文件,在 public static final String U_USERINFO = "userinfo"; 下方添加如下代码:
public static final String U_VIDEO_PLAY_LIST = "videoplaylist";  //视频播放列表
(2)、找到SQLiteHelper.java文件,在onCreate()方法里面添加如下代码:
1//创建视频播放记录 2 db.execSQL("CREATE TABLE IF NOT EXISTS " + U_VIDEO_PLAY_LIST + "( " + 3 "_id INTEGER PRIMARY KEY AUTOINCREMENT, " 4 + "userName VARCHAR,"//用户名 5 + "chapterId INT," //章节id 6 + "videoId INT,"//小节id 7 + "videoPath VARCHAR," 8 + "title VARCHAR," //章节名字 9 + "secondTitle VARCHAR" // 视频名字 10 + ")");
(3)、找到SQLiteHelper.java文件,在onUpgrade()方法里面的onCreate(db);语句前添加如下代码:
db.execSQL("DROP TABLE IF NOT EXISTS " + U_VIDEO_PLAY_LIST);
(4)、找到DBUtils.java文件,添加如下代码:
1 //保存视频播放记录 2 public void saveVideoPlayList(VideoBean bean, String userName) { 3 //判断如果里面已经有此记录则需要先删除再重新存放 4 if (hasVideoPlay(bean.chapterId, bean.videoId, userName)) { 5 boolean isDelete = delVideoPlay(bean.chapterId, bean.videoId, userName); 6 if (!isDelete) { 7 //没有删除成功 8 return; 9 } 10 } 11 ContentValues cv = new ContentValues(); 12 cv.put("userName", userName); 13 cv.put("chapterId", bean.chapterId); 14 cv.put("videoId", bean.videoId); 15 cv.put("videoPath", bean.videoPath); 16 cv.put("title", bean.title); 17 cv.put("secondTitle", bean.secondTitle); 18 db.insert(SQLiteHelper.U_VIDEO_PLAY_LIST, null, cv); 19 20 } 21 22 /** 23 * 删除已经存在的是视屏记录 24 * @param chapterId 25 * @param videoId 26 * @param userName 27 * @return 28 */ 29 30 public boolean delVideoPlay(int chapterId, int videoId, String userName) { 31 boolean delSuccess = false; 32 int row = db.delete(SQLiteHelper.U_VIDEO_PLAY_LIST, " chapterId=? AND videoId=? AND userName=?", 33 new String[]{chapterId + "", videoId + "", userName}); 34 if (row > 0) { 35 delSuccess = true; 36 } 37 38 return delSuccess; 39 } 40 /** 41 * 判断视频记录是否存在 42 * @param chapterId 43 * @param videoId 44 * @param userName 45 * @return 46 */ 47 public boolean hasVideoPlay(int chapterId, int videoId, String userName) { 48 boolean hasVideo = false; 49 String sql = "SELECT * FROM " + SQLiteHelper.U_VIDEO_PLAY_LIST + " WHERE chapterId=? AND videoId=? AND userName =?"; 50 Cursor cursor = db.rawQuery(sql, new String[]{ chapterId + "", videoId + "", userName}); 51 if (cursor.moveToFirst()) { 52 hasVideo = true; 53 } 54 cursor.close(); 55 return hasVideo; 56 }
(5)、找到CourseAdapter.java文件,在两处注释//跳转到课程详情界面分别添加以下代码:
1 Intent intent = new Intent(mContext, VideoListActivity.class); 2intent.putExtra("id",bean.id); 3intent.putExtra("intro",bean.intro); 4mContext.startActivity(intent);

七、运行效果

image

Android项目实战系列—基于博学谷 开源地址

image                image

点赞
收藏

评论区

加载中...

相关推荐

Android项目实战系列—基于博学谷(七)课程模块(下)

!image(https://www.cztcms.cn/wpcontent/uploads/2020/03/%E5%8D%9A%E5%AD%A6%E8%B0%B7.png)由于这个模块内容较多,分为上、中、下三篇博客分别来讲述,请耐心阅读。课程模块分为四个部分\\课程列表\\课

Android项目实战系列—基于博学谷(一)项目综述

!image(https://www.cztcms.cn/wpcontent/uploads/2020/03/%E5%8D%9A%E5%AD%A6%E8%B0%B7.png)一、项目分析1、项目名称WordPress建站APP2、项目概述WordPress建站是一个学习博客建站技术的APP

Android项目实战系列—基于博学谷(四)我的模块(上)

!image(https://www.cztcms.cn/wpcontent/uploads/2020/03/%E5%8D%9A%E5%AD%A6%E8%B0%B7.png)由于这个模块内容较多,篇幅较长,请耐心阅读。“我”的模块分为四个部分\x\我的界面\x\设置界面\

Android项目实战系列—基于博学谷(四)我的模块(下)

!image(https://www.cztcms.cn/wpcontent/uploads/2020/03/%E5%8D%9A%E5%AD%A6%E8%B0%B7.png)由于这个模块内容较多,篇幅较长,请耐心阅读。“我”的模块分为四个部分\\我的界面\\设置界面\x

Android项目实战系列—基于博学谷(三)注册与登录模块

!image(https://www.cztcms.cn/wpcontent/uploads/2020/03/%E5%8D%9A%E5%AD%A6%E8%B0%B7.png)由于这个模块内容较多,篇幅较长,请耐心阅读。注册与登录模块分为三个部分\x\欢迎界面\x\注册界面\

Android项目实战系列—基于博学谷(六)习题模块

!image(https://www.cztcms.cn/wpcontent/uploads/2020/03/%E5%8D%9A%E5%AD%A6%E8%B0%B7.png)由于这个模块内容较多,篇幅较长,请耐心阅读。习题模块分为两个部分\x\习题列表界面\x\习题详情界面