个人项目 小跟班——蓝牙小车控制(UI篇)
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篇)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用户名不在sudoers文件中此事将被报
- 下一篇: 爬取bilibili视频