APP开发流程实例讲解-儒释道网络电台八天开发全程

功能和界面初步设定

APP开发流程实例讲解-儒释道网络电台八天开发全程

  1. 项目发起
  2. 功能和界面初步设定
  3. 在Android Studio中完成界面设计
  4. 实现功能代码:播放控制
  5. 优化排错:增强稳定性和添加异常处理
  6. 界面美化并进一步优化排错
  7. 百度云深度兼容测试并进一步优化排错
  8. 签名发布

昨天的做的设计图是比较简单的,主要麻烦是需要实现两侧的滑动抽屉菜单。

在Android Studio中有一个模板可以创建左侧抽屉,但儒释道网络电台APP需要两边两个抽屉。在网上找到一篇文章《AndroidDrawerLayout+fragment布局实现左右侧滑 》,是使用FragmentTransaction来实现左右侧栏的显现。还有一种办法是使用第三方组件SlidingMenu。难道就不能用Android Studio模板可以创建两侧抽屉滑动菜单吗?经过我一个多小时的探索和尝试,最终发现是可以的。创建的方法我已经写到另一篇文章《Android DrawerLayout+NavigationView布局实现左右两边侧滑菜单 》,这里不再多说。今天主要的完成的工作有。

双侧滑动抽屉菜单

实现方法上面已经说过,但又略有不同。根据昨天设计的界面,两侧菜单其实是三个ListView,但NavigationView主要是结合menu菜单来创建,有些不对路。经过尝试,最终删掉了NavigationView的menu属性,将列表加入到headerLayout中。实际代码如下:

nav_header_main.xml文件

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/drawer_layout"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"tools:openDrawer="start"><includelayout="@layout/app_bar_main"android:layout_width="match_parent"android:layout_height="match_parent" /><android.support.design.widget.NavigationViewandroid:id="@+id/nav_view"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_gravity="start"android:fitsSystemWindows="true"app:headerLayout="@layout/nav_header_main" /><android.support.design.widget.NavigationViewandroid:id="@+id/right_nav_view"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_gravity="end"android:fitsSystemWindows="true"app:headerLayout="@layout/nav_server_header_main" /></android.support.v4.widget.DrawerLayout>

然后就是在两个header的Layout文件如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:layout_height="wrap_content"android:showDividers="end"android:divider="@drawable/bottom_line"><ImageViewandroid:id="@+id/imageView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:paddingTop="@dimen/nav_header_vertical_spacing"android:src="@mipmap/ic_launcher"android:padding="8dp" /><LinearLayoutandroid:orientation="vertical"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="bottom"android:paddingBottom="8dp"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="@string/app_name" /><TextViewandroid:id="@+id/textView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="android.studio@android.com" /></LinearLayout></LinearLayout><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:layout_height="@dimen/banner48"android:showDividers="end"android:divider="@drawable/bottom_line"android:gravity="center_vertical"><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@android:drawable/ic_menu_today"android:layout_margin="8dp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:textAppearance="?android:attr/textAppearanceMedium"android:text="节目列表" /></LinearLayout><ListViewandroid:id="@+id/lv_programs"android:layout_width="match_parent"android:layout_height="wrap_content"></ListView><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:layout_height="@dimen/banner48"android:showDividers="end"android:divider="@drawable/bottom_line"android:gravity="center_vertical"><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@android:drawable/ic_menu_compass"android:layout_margin="8dp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:textAppearance="?android:attr/textAppearanceMedium"android:text="最新消息" /></LinearLayout><ListViewandroid:id="@+id/lv_news"android:layout_width="match_parent"android:layout_height="wrap_content"></ListView></LinearLayout>

nav_server_header_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:layout_height="@dimen/banner48"android:showDividers="end"android:divider="@drawable/bottom_line"android:gravity="center_vertical"><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@android:drawable/ic_menu_compass"android:layout_margin="8dp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:textAppearance="?android:attr/textAppearanceMedium"android:text="选择线路" /></LinearLayout><ListViewandroid:id="@+id/lv_servers"android:layout_width="match_parent"android:layout_height="wrap_content"></ListView></LinearLayout>

ListView列表项Layout就不贴了。

主界面的设计

如昨天设计图所示的Layout文件如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_behavior="@string/appbar_scrolling_view_behavior"tools:context="com.jianchi.fsp.buddhismnetworkradio.MainActivity"tools:showIn="@layout/app_bar_main"><!--640*360--><FrameLayoutandroid:id="@+id/player_frame"android:layout_alignParentStart="true"android:layout_alignParentTop="true"android:layout_alignParentLeft="true"android:layout_width="match_parent"android:layout_height="240dp"><VideoViewandroid:layout_width="match_parent"android:layout_height="240dp"android:id="@+id/videoView" /><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:layout_height="@dimen/banner48"android:layout_gravity="bottom"android:background="#b4b4b4b4"android:gravity="center_vertical"android:padding="8dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="净土大经科注 第318集"android:id="@+id/textView3"android:textColor="@android:color/white"android:layout_weight="1" /><CheckBoxandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="仅声音"android:id="@+id/checkBox" /></LinearLayout></FrameLayout><LinearLayoutandroid:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_below="@+id/player_frame"android:layout_alignParentLeft="true"android:layout_alignParentBottom="true"><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:background="@drawable/side_nav_bar"android:layout_height="@dimen/banner48"android:gravity="center_vertical"><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@mipmap/ic_jiangyi"android:paddingLeft="8dp"android:paddingRight="8dp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="经文讲义" /></LinearLayout><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_gravity="center_horizontal"><ScrollViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/scrollView"android:padding="8dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text New Text "android:id="@+id/textView2" /></ScrollView></LinearLayout></LinearLayout></RelativeLayout>

根据比例设置视频窗口高度

        FrameLayout player_frame = (FrameLayout) findViewById(R.id.player_frame);WindowManager wm = this.getWindowManager();int width = wm.getDefaultDisplay().getWidth();int height = width * 9 / 16;player_frame.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, height));

初步完成网络访问API类

网络访问使用了OKHTTP组件,并且是异步访问。OKHttp的使用这里就不多说了。功能实现方法是使用OKHttp下载网页,用正则表达式解析网页,抓取数据生成对象。调用完成事件将数据传回。然后再在UI线程中使用数据填充ListView等。

API类如下

package com.jianchi.fsp.buddhismnetworkradio;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;/*** Created by fsp on 16-7-5.*/
public class WebApi {/*节目时间表:视频音频播放器线路选择:http://www.amtb.tw/tvchannel/play-1-revised.asp最新讯息:http://www.amtb.tw/tvchannel/show_marquee.asp经文讲义:http://ft.hwadzan.com/mycalendar/mycalendar_embed_livetv.php?calendar_name=livetv* */private static final String programsListUrl  = "http://ft.hwadzan.com/mycalendar/mycalendar_embed.php?calendar_name=livetv&showview=day&valign=true&bgcolor=none&showtimecolumns=start&tvmenu=3";private static final String serversListUrl  = "http://www.amtb.tw/tvchannel/play-1-revised.asp";private static final String newsListUrl  = "http://www.amtb.tw/tvchannel/show_marquee.asp";private static final String noteUrl  = "http://ft.hwadzan.com/mycalendar/mycalendar_embed_livetv.php?calendar_name=livetv";Pattern programsListPattern = Pattern.compile("<td class='style1'>\\s*<strong>(.*?)</strong>\\s*(.*?)\\s*</td>");Pattern htmlTagPattern = Pattern.compile("<[^>]*>");Pattern serversListPattern = Pattern.compile("serverAddress = \"(.*?)\";\\s*serverName = \"(.*?)\";");Pattern newsListPattern = Pattern.compile("<div id='bul_\\d'>(.*?)</div>");Pattern noteItemPattern = Pattern.compile("<p class=\"MsoNormal\">\\s*(.*?)\\s*</p>");private OkHttpClient client = new OkHttpClient();IProgramsListEvent programsListEvent;IServersListEvent serversListEvent;IProgramsListEvent newsListEvent;IStringEvent noteEvent;public void GetNote(IStringEvent noteEvent) {this.noteEvent = noteEvent;Request request = new Request.Builder().url(noteUrl).build();client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {e.printStackTrace();WebApi.this.noteEvent.getMsg(null);}@Overridepublic void onResponse(Call call, Response response) throws IOException {String html = new String(response.body().bytes(), "big5");Matcher m = noteItemPattern.matcher(html);StringBuilder sb = new StringBuilder();while (m.find()){String nm = m.group(1);if(nm.startsWith("<")) {Matcher hm = htmlTagPattern.matcher(nm);nm = hm.replaceAll("");}sb.append(nm).append("\r\n");}WebApi.this.noteEvent.getMsg(sb.toString());}});}public void GetNewsList(IProgramsListEvent newsListEvent) {this.newsListEvent = newsListEvent;Request request = new Request.Builder().url(newsListUrl).build();client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {e.printStackTrace();WebApi.this.newsListEvent.getItems(null);}@Overridepublic void onResponse(Call call, Response response) throws IOException {String html = new String(response.body().bytes(), "big5");Matcher m = newsListPattern.matcher(html);List<String> newsList = new ArrayList<String>();while (m.find()){String nm = m.group(1);if(nm.startsWith("<")) {Matcher hm = htmlTagPattern.matcher(nm);nm = hm.replaceAll("");}newsList.add(nm);}WebApi.this.newsListEvent.getItems(newsList);}});}public void GetProgramsList(IProgramsListEvent programsListEvent) {this.programsListEvent = programsListEvent;Request request = new Request.Builder().url(programsListUrl).build();client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {e.printStackTrace();WebApi.this.programsListEvent.getItems(null);}@Overridepublic void onResponse(Call call, Response response) throws IOException {String html = new String(response.body().bytes(), "utf-8");Matcher m = programsListPattern.matcher(html);List<String> programsList = new ArrayList<String>();while (m.find()){String nm = m.group(2);if(nm.startsWith("<")) {Matcher hm = htmlTagPattern.matcher(nm);nm = hm.replaceAll("");}programsList.add(m.group(1) + " " + nm);}WebApi.this.programsListEvent.getItems(programsList);}});}public void GetServersList(IServersListEvent serversListEvent) {this.serversListEvent = serversListEvent;Request request = new Request.Builder().url(serversListUrl).build();client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {e.printStackTrace();}@Overridepublic void onResponse(Call call, Response response) throws IOException {String html = new String(response.body().bytes(), "utf-8");Matcher m = serversListPattern.matcher(html);ServersList serverList = new ServersList();while (m.find()){serverList.add(new ServerInfo(m.group(1), m.group(2)));}WebApi.this.serversListEvent.getServers(serverList);}});}
}

在UI线程中调用的代码如下

        api = new WebApi();api.GetNewsList(new IProgramsListEvent() {@Overridepublic void getItems(List<String> programs) {runOnUiThread(new Runnable() {@Overridepublic void run() {}});}});api.GetNote(new IStringEvent() {@Overridepublic void getMsg(String msg) {runOnUiThread(new Runnable() {@Overridepublic void run() {}});}});api.GetProgramsList(new IProgramsListEvent() {@Overridepublic void getItems(List<String> programs) {runOnUiThread(new Runnable() {@Overridepublic void run() {}});}});api.GetServersList(new IServersListEvent() {@Overridepublic void getServers(ServersList servers) {runOnUiThread(new Runnable() {@Overridepublic void run() {}});}});

总的来说写代码用的时间比较少,界面设计不熟悉用时较多。原计划每天花2个小时来做这个APP,但今天实际花有4个多小时。界面代码那里花时间过多了,写JAVA代码反而比较快。

明天按计划,写播放器控制的代码。

所有代码已经上传到GIT:https://code.csdn.net/do168/buddhismnetworkradio

APP开发流程实例讲解-儒释道网络电台八天开发全程-在Android Studio中完成界面设计相关推荐

  1. APP开发流程实例讲解-儒释道网络电台八天开发全程-百度云深度兼容测试并进一步优化排错

    APP开发流程实例讲解-儒释道网络电台八天开发全程之 百度云深度兼容测试并进一步优化排错 APP开发流程实例讲解-儒释道网络电台八天开发全程 项目发起 功能和界面初步设定 在Android Studi ...

  2. APP开发流程实例讲解-儒释道网络电台八天开发全程-项目发起

    APP开发流程实例讲解-儒释道网络电台八天开发全程 项目发起 APP开发流程实例讲解-儒释道网络电台八天开发全程 项目发起 功能和界面初步设定 在Android Studio中完成界面设计 实现功能代 ...

  3. APP开发流程实例讲解-儒释道网络电台八天开发全程-功能和界面初步设定

    APP开发流程实例讲解-儒释道网络电台八天开发全程 能和界面初步设定 APP开发流程实例讲解-儒释道网络电台八天开发全程 项目发起 功能和界面初步设定 在Android Studio中完成界面设计 实 ...

  4. APP开发流程实例讲解-儒释道网络电台八天开发全程-实现功能代码:播放控制

    APP开发流程实例讲解-儒释道网络电台八天开发全程 实现功能代码:播放控制 APP开发流程实例讲解-儒释道网络电台八天开发全程 项目发起 功能和界面初步设定 在Android Studio中完成界面设 ...

  5. APP开发流程实例讲解-儒释道网络电台八天开发全程-签名发布

    APP开发流程实例讲解-儒释道网络电台八天开发全程 签名发布 APP开发流程实例讲解-儒释道网络电台八天开发全程 项目发起 功能和界面初步设定 在Android Studio中完成界面设计 实现功能代 ...

  6. Android NDK开发之旅(2):一篇文章搞定Android Studio中使用CMake进行NDK/JNI开发

    Android NDK开发之旅(2):一篇文章搞定android Studio中使用CMake进行NDK/JNI开发 (码字不易,转载请声明出处:http://blog.csdn.NET/andrex ...

  7. Android开发——Android Studio中配置及使用OpenCV示例

    from: http://www.mobile-open.com/2015/86176.html 本文主要讲述了Android Studio中配置及使用OpenCV示例,现在整理出来分享给Androi ...

  8. Android Studio中的手机通讯录开发

    Android Studio中的手机通讯录,包含功能(按首字母排序,动态添加) 第一次写博客,也刚踏入工作,想着把自己在项目中遇到的问题,以及自己在工作中所做的项目记录下来,方便以后自己查找知识,一开 ...

  9. Android Studio中app出现红叉的解决方案

    Android Studio中app出现红叉的解决方案 如果你在网上搜索了一大圈之后发现还是没有解决你的问题,或许这篇文章能帮到你,同事的开发环境中遇到了,处理了一下午,期间包括删除工具,重装sdk等 ...

最新文章

  1. dom刷新局部元素_JavaScript中DOM和BOM基础
  2. 利用ESP32驱动控制步进电机驱动器:MS2806
  3. linux tail命令详解
  4. xml布局显示需要预判断,可是还没有show出来,怎么办?
  5. 一文讲清,MySQL中的二级索引
  6. RIP协议路由环路及解决方案
  7. NSArray 所有基础点示例
  8. 懂语言者得天下:NLP 凭什么被称为人工智能的掌上明珠?
  9. [原创]java WEB学习笔记103:Spring学习---Spring Bean配置:基于注解的方式(基于注解配置bean,基于注解来装配bean的属性)...
  10. 强悍的电子邮件地址(email address)正则表达式
  11. 下载firebug网站
  12. 电脑键盘equals在哪个位置_【电脑键盘在哪里调出来】电脑键盘在哪里找_电脑模拟键盘在哪里...
  13. 在线购物系统分析类图
  14. 线性回归方程b保留几位小数_线性回归的这些细节,你都搞明白了吗?
  15. 在ubantu下安装搜狗
  16. 大数据——Flink 知识点整理
  17. 详细解释基址寻址和变址寻址区别
  18. c语言堆、栈、数据段、代码段、bss段的疑惑
  19. 简单介绍一下什么是vue
  20. 解决Visual Studio2019登录微软账户登录不上的问题

热门文章

  1. 【100个 Unity实用技能】☀️ | Unity 复用动画控制器 Animator Override Controller 的简单使用
  2. python open函数参数_python中open函数的使用
  3. 【北京】安全研究员/工程师-20-35K,人体工程学座椅坐等你来~
  4. 数据挖掘学习小组简介!
  5. 苹果手机的处理器全都是64位的吗?
  6. virtualBox 踩坑记
  7. JQuery JSON
  8. 京东购物车html页面,仿京东购物车页面
  9. vdbench测试生成器
  10. IDEA如何设置为中文界面?