1 功能需求及技术可行性分析

预期实现一个应用——小跟班,它可以通过蓝牙与小车相连并对小车进行控制。本应用的主要功能有:

1 搜索蓝牙设备,取消搜索蓝牙设备

2 连接蓝牙设备,断开连接

3 对连接的蓝牙设备发送指令

(1)方向键控制

(2)两种模式控制

虽然看上去只有几个主要的功能点,但如果想要全部实现这些功能却需要用到各种技术,例如:UI、蓝牙等。

分析完了需求之后,接下来就要进行技术可行性分析了。首先如何可以控制手机的蓝牙功能,我们可以查看Android API开发指南(http://www.embeddedlinux.org.cn/androidapi/),里面提供了一些方法:

有了这些了解,就可以开始着手编写我的程序了。

2 创建你的工程

编写程序第一步当然就是创建一个新的工程。

项目名:ToFollow  包名:com.zl_sf.tofollow(包名可自定义)。填写完毕之后,一直点击Next直到Finish。首先分析一下:我们需要一个欢迎界面,一些引导界面,主界面和蓝牙适配器。

建好工程后,开始新建Activity,我们需要以下一些文件:

3 Welcome界面设计

我们需要设计一个开机动画。首先,选择一张满意的图片,放在Photoshop中稍作修改,加上自己的应用名和一些装饰。可以做一个渐变的动画,从无到有持续3s。效果图:

图片是自己PS的所以就不多说了,那么看看WelcomeActivity的代码吧:

package com.zl_sf.tofollow.start;import com.zl_sf.tofollow.R;import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.widget.LinearLayout;public class WelcomeActivity extends Activity {private LinearLayout welcome_layout;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_welcome);welcome_layout = (LinearLayout) findViewById(R.id.layout_welcome);AlphaAnimation alphaAnimation=new AlphaAnimation(0.0f, 1.0f);alphaAnimation.setDuration(3000);welcome_layout.startAnimation(alphaAnimation);alphaAnimation.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {// TODO Auto-generated method stub}@Overridepublic void onAnimationRepeat(Animation animation) {// TODO Auto-generated method stub}@Overridepublic void onAnimationEnd(Animation animation) {// TODO Auto-generated method stubIntent intent=new Intent(WelcomeActivity.this,GuideActivity.class);startActivity(intent);finish();}});}}

可以看到这个activity里面没有写全局显示的代码,因为我是在manifest中添加的相关权限:

<activityandroid:name=".start.WelcomeActivity"android:label="@string/app_name"android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter>
</activity>

另外,布局文件,activity_welcome.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:id="@+id/layout_welcome"android:background="@drawable/welcome"tools:context="com.zl_sf.tofollow.start.WelcomeActivity" ></LinearLayout>

这里只是添加了一个背景图片。可见,欢迎界面还是很容易实现的。

4 Guide界面设计

很多很好看的应用都有引导界面,用来介绍自己的软件或者是帮助第一次使用的人来使用这款软件,效果图如下:

感谢 花瓣网 提供的精美手绘图片~

是不是看起来很炫酷,哈哈,来看看实现过程吧:

在activity_guide布局文件中我们需要一个ViewPage控件,以及滑动的时候的四个小点。

首先来看看activity文件,GuideActivity:

package com.zl_sf.tofollow.start;import java.util.ArrayList;
import java.util.List;
import com.zl_sf.tofollow.R;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;public class GuideActivity extends Activity {private ViewPager vpGuide;private ImageView ivDots[];private int[] dots_id;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_guide);initGuideViews();initDots();vpGuide.setOnPageChangeListener(new OnPageChangeListener() {@Overridepublic void onPageSelected(int position) {for (int i = 0; i < ivDots.length; i++) {if (position == i) {ivDots[i].setImageResource(R.drawable.bg_point_selected);} else {ivDots[i].setImageResource(R.drawable.bg_point_normal);}}}@Overridepublic void onPageScrolled(int position, float arg1, int arg2) {}@Overridepublic void onPageScrollStateChanged(int postion) {}});}private void initDots() {dots_id = new int[] { R.id.ivDots1, R.id.ivDots2, R.id.ivDots3,R.id.ivDots4 };ivDots = new ImageView[dots_id.length];for (int i = 0; i < ivDots.length; i++) {ivDots[i] = (ImageView) findViewById(dots_id[i]);}}private void initGuideViews() {vpGuide = (ViewPager) findViewById(R.id.vpGuide);List<View> views = new ArrayList<View>();LayoutInflater layoutInflater = getLayoutInflater();View view1 = layoutInflater.inflate(R.layout.guide1, null);views.add(view1);View view2 = layoutInflater.inflate(R.layout.guide2, null);views.add(view2);View view3 = layoutInflater.inflate(R.layout.guide3, null);views.add(view3);View view4 = layoutInflater.inflate(R.layout.guide4, null);views.add(view4);GuideAdapter guideAdapter = new GuideAdapter(views);vpGuide.setAdapter(guideAdapter);}public void jumpMain(View view) {Intent intent = new Intent(this, com.zl_sf.tofollow.MainActivity.class);startActivity(intent);finish();}}

为了实现滑动效果,需要一个Adapter来帮助完成。GuideAdapter:

package com.zl_sf.tofollow.start;import java.util.List;import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;public class GuideAdapter extends PagerAdapter {private List<View> views;public GuideAdapter(List<View> views) {super();this.views = views;}@Overridepublic int getCount() {return views.size();}@Overridepublic boolean isViewFromObject(View view, Object object) {return view==object;}@Overridepublic Object instantiateItem(ViewGroup container, int position) {container.addView(views.get(position));return views.get(position);}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {container.removeView(views.get(position));}}

另外就是布局文件,activity_guide.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".GuideActivity" ><android.support.v4.view.ViewPagerandroid:id="@+id/vpGuide"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true" ></android.support.v4.view.ViewPager><LinearLayoutandroid:id="@+id/layoutDots"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"android:gravity="center_horizontal"android:layout_marginBottom="30dp"android:orientation="horizontal" ><ImageViewandroid:id="@+id/ivDots1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/bg_point_selected" /><ImageViewandroid:id="@+id/ivDots2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="10dp"android:background="@drawable/bg_point_normal" /><ImageViewandroid:id="@+id/ivDots3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="10dp"android:background="@drawable/bg_point_normal" /><ImageViewandroid:id="@+id/ivDots4"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="10dp"android:background="@drawable/bg_point_normal" /></LinearLayout></RelativeLayout>

页面下的点随着页面滑动切换效果,通过bg_point_selected.xml和bg_point_normal.xml实现,代码如下:

bg_point_selected.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="oval" ><sizeandroid:height="8dp"android:width="8dp" /><solid android:color="@color/silver" />
</shape>

bg_point_normal.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="oval" ><sizeandroid:height="8dp"android:width="8dp" /><solid android:color="@color/ivory" /></shape>

每一个引导页面都需要写一个XML文件,加入背景。

guide1.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="match_parent"android:background="@drawable/guide1"android:orientation="vertical" ></LinearLayout>

其他的三个guide.xml和这个一样,只是换掉背景图片。

最后,在manifest文件中也将GuideActivity添加全屏。和上一部分的步骤一样。

我们需要用按钮来控制打开、关闭蓝牙和连接、断开设备,只是简单得摆放几个按钮会显得很难看,我们需要布局一下主界面。我的想法是,将一些按钮放在一个线性布局中,将方向键放在一个相对布局中,再自定义一个title布局。主布局文件中包括title、按钮的线性布局、方向键的相对布局、ListView控件。效果图如下:

首先是title布局文件,来看看如何实现:

<?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:background="@drawable/bg_shape"android:layout_marginBottom="15dp"><Buttonandroid:id="@+id/title_back"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:layout_margin="5dp"android:background="@drawable/btn_select"android:text="@string/title_back" /><TextViewandroid:id="@+id/title_text"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_weight="1"android:gravity="center"android:text="@string/title"android:textSize="20sp" /><Buttonandroid:id="@+id/title_menu"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:layout_margin="5dp"android:background="@drawable/btn_menu" /></LinearLayout>

Button的效果通过drawable下的btn_select.xml实现,btn_menu.xml则是实现一个透明按钮的效果。代码如下:

btn_select.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" ><item android:drawable="@drawable/btn_shape"android:state_pressed="false" /><item android:drawable="@drawable/btn_shape_after"android:state_pressed="true" />
</selector>

其中还包括了点击事件前后的效果:btn_shape.xml和btn_shape_after.xml,代码如下:

btn_shape.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" ><solid android:color="#8FBC8F"/><!-- 暗海洋绿 --><corners android:radius="10dp"/>
</shape>

btn_shape_after.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" ><solid android:color="#2E8B57"/><!-- 海洋绿 --><corners android:radius="10dp"/>
</shape>

透明按钮的作用是使标题能够居中显示,下面看看如何实现:

btn_menu.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" ><solid android:color="#00ffffff"/><!-- 全透明 --><corners android:radius="10dp" />
</shape>

title布局完成,接下来是按钮的线性布局,方向键的相对布局,ListView控件,我都写在了主布局文件中,代码如下:

activity_main.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/follow_background"android:orientation="vertical" ><includeandroid:id="@+id/include_title"layout="@layout/title" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginBottom="5dp"android:layout_marginLeft="15dp"android:layout_marginRight="15dp"android:layout_marginTop="5dp"android:background="@drawable/bg_shape"android:orientation="vertical"android:padding="10dp" ><Buttonandroid:id="@+id/scan"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginBottom="5dp"android:layout_marginTop="5dp"android:background="@drawable/btn_select"android:text="@string/btn_scan" /><Buttonandroid:id="@+id/button_stop"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginBottom="5dp"android:layout_marginTop="5dp"android:background="@drawable/btn_select"android:text="@string/btn_tostop" /><Buttonandroid:id="@+id/stop"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginBottom="5dp"android:layout_marginTop="5dp"android:background="@drawable/btn_select"android:text="@string/btn_stop" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginBottom="5dp"android:layout_marginLeft="15dp"android:layout_marginRight="15dp"android:layout_marginTop="5dp"android:background="@drawable/btn_menu"android:orientation="horizontal"android:padding="10dp" ><Buttonandroid:id="@+id/follow"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="5dp"android:layout_marginTop="5dp"android:layout_weight="1"android:gravity="center"android:text="@string/btn_follow"android:background="@drawable/btn_select" /><Buttonandroid:id="@+id/maze"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="5dp"android:layout_marginTop="5dp"android:layout_weight="1"android:gravity="center"android:text="@string/btn_maze"android:background="@drawable/btn_select" /></LinearLayout><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="145dp" ><ImageButtonandroid:id="@+id/down"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true" android:layout_centerHorizontal="true"android:background="@drawable/down" /><ImageButtonandroid:id="@+id/left"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_above="@+id/down"android:layout_toLeftOf="@+id/down"android:background="@drawable/left" /><ImageButtonandroid:id="@+id/right"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_above="@+id/down"android:layout_toRightOf="@+id/down"android:background="@drawable/right" /><ImageButtonandroid:id="@+id/up"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_above="@+id/left"android:layout_toRightOf="@+id/left"android:layout_toLeftOf="@+id/right"          android:layout_centerHorizontal="true"android:background="@drawable/up" /></RelativeLayout><ListViewandroid:id="@+id/lv_item"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1" ></ListView></LinearLayout>

按钮的线性布局的背景是一个半透明的背景,由bg_shape.xml实现,父布局背景由follow_background.xml实现,按钮的设计同上,代码如下:

bg_shape.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" ><solid android:color="#55ffffff"/><!-- 半透明 --><corners android:radius="10dp" />
</shape>

follow_background.xml:

<shape xmlns:android="http://schemas.android.com/apk/res/android" ><solid android:color="#8FBC8F"/><!-- 暗海洋绿 -->
</shape>

方向键就是四个ImageButton和网上找的图片,ListView也没有什么改变。对于ListView中的item有一个布局,这里暂时用不上,代码如下:

Item.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="match_parent"android:orientation="vertical" ><TextView android:id="@+id/item_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/item_name"android:textColor="@color/black"android:textSize="18sp" /><TextView android:id="@+id/item_addr"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/item_addr"android:textColor="@color/black"android:textSize="18sp" /></LinearLayout>

UI篇结束,下一篇讲解蓝牙实现过程。

个人项目 小跟班——蓝牙小车控制(UI篇)相关推荐

  1. 个人项目 小跟班——蓝牙控制小车(蓝牙控制篇)

    5 蓝牙的配置 到了核心部分了,首先,想要控制手机蓝牙的打开和关闭,需要在manifest中添加相应的权限: <uses-permission android:name="androi ...

  2. 基于MSP432P401R的串口屏蓝牙小车控制

    目录 前言 一.串口屏蓝牙助手设计 二.keil5代码设计 1.main.c 2.串口1中断程序 总结 前言 前段时间兴趣使然用串口屏做了个基于MSP432蓝牙串口屏控制的小车车,现在记录一下,话不多 ...

  3. iOS超全开源框架、项目和学习资料汇总:UI篇

    2017-01-30 iOS巍 CocoaChina 原文 上下拉刷新控件 1. MJRefresh --仅需一行代码就可以为UITableView或者CollectionView加上下拉刷新或者上拉 ...

  4. 小眼游戏架构:UI篇:系统功能(新手引导)

    前言 这个引导它又臭又长,就像这面... 说实话我本人也很讨厌新手引导,感觉把玩家当成弱智一样,什么都要交,比ta妈还要对ta好. 关键是程序不想做妈啊,一个游戏不改个三到五次的新手引导,你好意思上线 ...

  5. 小眼游戏架构:UI篇:三层架构(UI层)

    上一篇我们分析了UI的架构原则以及为什么要这么架构的一些原因,这篇会具体实现架构的方方面面,东西会有点多.我辈求道,岂能求快! 为了避免框架的干扰我们先来配置一下开发环境. LuaFrameWork的 ...

  6. 【微信小程序控制硬件14 】 微信小程序蓝牙+WiFi双控制ESP32-C3应用示范;(附带Demo)

    文章目录 一.前言 二.设备核心代码 2.1 蓝牙控制 2.2 WiFi控制 2.3 外设驱动 三.微信小程序核心代码 3.1 蓝牙搜索 3.2 蓝牙服务发现 四.感谢 另外,不要把我的博客作为学习标 ...

  7. 微信小程序控制硬件第17篇 : 腾讯连连小程序通过LLSync蓝牙协议控制安信可PB-02模组,无需网络实现蓝牙本地通讯。(附带源码)

    文章目录 前言 一.注册腾讯物联开发平台设备 新建项目 新建产品 创建数据模板 选择设备开发方式 交互开发配置 新建设备 二.设备端操作 硬件简介与连接 准备软件环境 工程目录 烧录步骤 三.腾讯连连 ...

  8. arduino 蓝牙 android 小车,arduino智能蓝牙小车

    大家好!这是小编第二次做小项目~ 小编目前专业是电气自动化的,不搞点硬件方面的东西,不学点控制技术,有点对不起自己所学的专业. 小编这次打算做arduino多功能智能小车~ 首先,为啥选择arduin ...

  9. 【微信小程序控制硬件 第12篇-项目篇】微信小程序蓝牙控制硬件应如何开始动手?为您全面解析微信小程序蓝牙API的使用;(附带demo)

    [微信小程序控制硬件第1篇 ] 全网首发,借助 emq 消息服务器带你如何搭建微信小程序的mqtt服务器,轻松控制智能硬件! [微信小程序控制硬件第2篇 ] 开始微信小程序之旅,导入小程序Mqtt客户 ...

最新文章

  1. android用java_原来android不是只能用java写软件
  2. c语言课程设计链表 文件,C语言课程设计第三节课:指针和链表使用     150809205...
  3. 终于把论文Check完了
  4. 《Pro ASP.NET MVC 3 Framework》学习笔记之十六【示例项目SportsStore】
  5. 008_Redis的ZSet数据类型
  6. ios UIWebView 播放优酷土豆视频
  7. 一个身份证号码验证接口[2]
  8. 汇编 编程实现从键盘输入三位以内的十进制负数_macOS上的汇编入门(二)——数学基础...
  9. 2018高中计算机会考知识点,2018高中物理会考知识点总结
  10. win7如何修改dns服务器地址,Win7系统DNS怎么设置?Win7系统DNS设置方法
  11. 比特币可视化工具_这个比特币交易“可视化”网站,用一辆公交车带你“上车”...
  12. centos 7.2 安装php56-xml
  13. 巧用G6FTPServer账号***台湾某图书服务器
  14. CH32F103C8T6核心板三种程序下载方式简介
  15. python正弦函数幂级数展开_函数展开成正弦级数或余弦级数的奇延拓
  16. 实验三.局域网的组建
  17. ESP8266连接网络,获取网络天气api
  18. 电影图标-黑客帝国(The Matrix)
  19. 基于Python的深度神经网络的中文期刊分类系统
  20. 详解Django的CSRF认证

热门文章

  1. 采药(c语言贪心算法)
  2. 2022Java面试心得,35岁的程序员被裁
  3. 手机html端悬浮球,大屏手机绝配!一款轻巧强大的悬浮球App
  4. illustrator字体设计教程 刘兵克Illustratorai字体设计日记
  5. 火焰焰心matlab,火焰心_刘德华_高音质在线试听_火焰心歌词|歌曲下载_酷狗音乐...
  6. 国学*周易*梅花易数 代码实现效果展示 - 梅花心易
  7. CD-ICBC-常见问题或开发过程备份记录
  8. SEO优化是什么意思,如何理解并学好它
  9. OpenGL--------读取PLY格式的bunny兔子文件以便画出兔子
  10. Duang~Shark 闪跌 99%! Fork 了 Bunny 的代码还 Fork 了它的攻击