上一篇ActionBarCompat 【Add Tab】講到了,你們可能會覺得很奇怪,
為什麼不管點tab1還是tab2,
怎麼內容都一樣?
因為我們的確沒有透過FragmentTransaction把Fragment加進來!
最後的結論是說,要透過ViewPager去把Fragment加進來!
所以這篇就是要教大家怎麼使用ViewPager,
使用ViewPager好處就是,使用者可以用swipe去換tab,
1. 首先請將你的class implement OnPageChangeListener 這個interfacepublic class MainActivity extends ActionBarActivity implements TabListener,OnPageChangeListener {
....
}
2. 增加對應的method因為在第一步的時候,你就已經implement一個interface進來,
所以在第二步驟我們必須增加下面的method
@Override
public void onPageScrollStateChanged(int arg0) {}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {}
@Override
public void onPageSelected(int iPosition) {
getSupportActionBar().setSelectedNavigationItem(iPosition);
}
我們在上面的onPageSeleced中實作了一段code,
它的目的就是當你swipe到該page,就顯示該page應顯示的Fragment!
3. 加入2個Fragment這步驟是新增兩個Fragment,
目的是為了要塞在tab裡面!
由於很簡單,就不貼example了!
反正就是兩個Fragment(先命名為FragmentTab1, FragmentTab2)
4. 加入FragmentPagerAdapterFragmentPagerAdapter目的就是待會要餵給viewPager使用的,
這樣viewPager才知道捲動到哪頁的時候,要顯示哪個Fragment.
我們可以在getItem看到,
當iPosition為1的時候,意思就是卷到第一個tab了!
所以我們就在這new上面新增的FragmentTab1出來!
public class HomeViewPagerAdapter extends FragmentPagerAdapter{
public HomeViewPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int iPosition) {
switch (iPosition) {
case 0:
return new FragmentTab1();
case 1:
return new FragmentTab2();
}
return null;
}
@Override
public int getCount() {
return 2;
}
}
5. 在layout中加入viewpager<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
6. 取得layout中的viewpager在這步驟就是取得剛剛上步驟新增的viewpager,
然後對它作設定,
首先要先設定adapter,這裡就是餵給他我們上面的HomeViewPagerAdapter,
接著就是設定listener,這裡我們指定this,指定this的話就會去抓第二步驟implement的method!
當然你也可以自己new!
至於第三步與第四步是optional的!當然你也可以不要設定!
這兩步驟只是為了讓畫面好看一點,在tab1和tab2之間swipe的時候,中間會有一個style在!
但理論上,你們第三步與第四步都會錯,因為沒有圖也沒有設定dimension!
private ViewPager viewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.pager);
if (viewPager!=null){
viewPager.setAdapter(new HomeViewPagerAdapter(getSupportFragmentManager()));
viewPager.setOnPageChangeListener(this);
viewPager.setPageMarginDrawable(R.drawable.grey_border_inset_lr); // optional
viewPager.setPageMargin(getResources().getDimensionPixelSize(R.dimen.page_margin_width)); // optional
}
}
7. hook onTabSelected 理論上完成上面的步驟,
你應該就可以完成用swipe換tab了!
可是你可能會發現,當你直接點tab時,
tab並不會更換!
所以最後一步驟就是要實作這一塊!
還記得上一篇嗎?
我們有implement onTabSelected這個method!
在裡面加入下面的code吧!
@Override
public void onTabSelected(Tab tab, FragmentTransaction arg1) {
viewPager.setCurrentItem(tab.getPosition());
}
大功告成!
恩,下一篇會教大家怎麼去style自己的actionbar(if i have time..)
多虧於公司intern的實驗室,
我才有榮幸玩到Arduino的wifi套件!
不然一塊三千多塊,實在是買不下去阿!
這篇主要教大家,
怎麼用這塊wifi shield去做到下列的事情
- scan network AP
- connect to a network AP
- send a request
- create a WebServer using exists connection
恩,在開始之前,請先準備好環境!
注意!在我寫文章的這個時候!
arduino已經出到了1.0.5版!
最一開始我是用1.0.1版開發,但1.0.1版是沒有wifi的lib,
所以我自己去github把wifi的lib抓下來,再放在我的lib裡面!
的確!大部份功能都可以work!
除了建立webserver以外!
但是不要天真的以為用1.0.5版就可以建立webserver,
根據撞牆了幾個小時,發現要downgrade至1.0.2版才能建立webserver...
其實1.0.5版也可以,只是要
做一些操作!實在太麻煩!
總而言之,請使用1.0.2
1. 把wifi shield直接插在你的arduino板上!官網其實有備註,如果你是用比較舊的板子(UNO R3),還要稍微接一下線!
請看這篇吧!
2. include necessary lib#include <WiFi.h>
3. 開始寫code3.1 掃描附近所有的apvoid setup(){
Serial.begin(9600);
}
void loop(){
fnScanNetwork();
}
void fnScanNetwork(){
int iNum = WiFi.scanNetworks();
Serial.print("=========number of available networks:");
Serial.print(iNum);
Serial.println("=========");
// print the each SSID and Signal
for (int i = 0; i<iNum; i++) {
Serial.print(WiFi.SSID(i)); // pring SSID
Serial.print("\tSignal: ");
Serial.print(WiFi.RSSI(i)); // print Signal
Serial.print(" dBm");
Serial.print("\tEncryption: ");
Serial.println(WiFi.encryptionType(i)); // print Encryption Type
}
}
上面比較需要注意的大概就是WiFi.RSSI(i),
這隻method就是回傳該AP訊號的強弱!
記得值越大訊號越強!
再來就是WiFi.encryptionType(i),
這是回傳該AP的加密形態是什麼?
內容如下:
* TKIP (WPA) = 2
* WEP = 5
* CCMP (WPA) = 4
* NONE = 7
* AUTO = 8
3.2 連線至某個apchar szSsid[] = "kerkerker"; // network SSID (name)
char szPass[] = "safesync"; // network password
int iStatus = WL_IDLE_STATUS;
void setup(){
Serial.begin(9600);
fnConnectToAP();
}
void loop(){
}
void fnConnectToAP(){
while ( iStatus != WL_CONNECTED) {
Serial.println("Connecting to network...");
Serial.print("SSID: ");
Serial.println(ssid);
delay(1000);
iStatus = WiFi.begin(ssid, pass); // connect
}
Serial.print("Connected successfully. IP address:");
IPAddress myAddress = WiFi.localIP();
Serial.println(myAddress);
}
WiFi.begin這個method就是在進行連線!
如果成功的話會看到下面兩張圖!
首先你的wifi shield上的link那顆燈會變成綠色!
而你的Serial Monitor會長得像下面一樣!
3.3 傳送一個request至一個server首先在setup裡面先連線至ap,
接著就送出一個request,
然後就在loop裡面進行讀資料的動作!
如果成功的話,你應該會在你的Serial Monitor看到一大堆回傳的資料才對!
// connect to ap
int iStatus = WL_IDLE_STATUS;
char szSsid[] = "kerkerker"; // network SSID (name)
char szPass[] = "safesync"; // network password
// send a request
char szServername[]="www.google.com"; // remote server we will connect to
WiFiClient client;
void setup(){
Serial.begin(9600);
fnConnectToAP();
fnSendRequest();
}
void loop(){
fnReadData();
}
void fnSendRequest(){
if (client.connect(szServername, 80)) {
Serial.println("connected");
// Send a HTTP request:
client.println("GET /search?q=arduino HTTP/1.1");
client.println("Host: www.google.com");
client.println();
}
}
void fnReadData(){
while (client.available()) {
char c = client.read();
Serial.print(c);
}
// if the server's disconnected, stop the client:
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting from server.");
client.stop();
// do nothing forevermore:
while(true);
}
}
3.4 建立一個webserver供人連線輸入下列的code以後,接著只要用browser輸入你的ip,
就會看到Hello World了!
// webserver
WiFiServer server(80);
void setup(){
Serial.begin(9600);
fnConnectToAP();
// fnSendRequest();
fnStartServer();
}
void loop(){
fnWaitingRequest();
// fnReadData();
}
void fnStartServer(){
delay(1000);
server.begin();
}
void fnWaitingRequest(){
WiFiClient client = server.available();
if (client) {
Serial.println("new client comming");
boolean bCurrentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
// if you've gotten to the end of the line and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && bCurrentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.print("Hello World ");
client.println("</html>");
break;
}
if (c == '\n') {
// you're starting a new line
bCurrentLineIsBlank = true;
} else if (c != '\r') {
// you've gotten a character on the current line
bCurrentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disonnected");
}
}
source code:
https://github.com/Ken-Yang/ArduinoWiFiShield基本上蠻簡單的,
code也很好理解!
只是有些tricky的地方,
像是1.0.5版需要update firmware!
官網上也有很多豐富的example!
有空可以去看看!
如果有空,下一篇會教大家怎麼結合wifi+遙控車!
上一篇ActionBarCompat 【Basic】教導大家怎麼使用Google提供的ActionBarCompat lib以後,
這篇要延續上篇實作的actionbar,來加入tabs!
最早在android要使用tab的layout,
必須使用tabhost這個object!
但現在被deprecated了!
後來推薦使用Fragment去控制tabwidget ui object.
但這篇是要教大家怎麼直接用actionbar加入tabs,
相較前面的兩種方法,用actionbar比較簡單!
1. 首先請將你的class implement TabListener 這個interfacepublic class MainActivity extends ActionBarActivity implements TabListener {
....
}
2. 加入應有的method因為你前一步驟implement了一個interface,
那麼在你的Class之中,也應該要有該interface底下的method,
所以你的class一開始應該會紅紅的一條,代表error,
那麼你只要將滑鼠移至該class名稱上,eclipse就會有選項幫你直接加入該有的method,
或者你也可以自己直接加入,如下
@Override
public void onTabReselected(Tab arg0, FragmentTransaction arg1) {
// TODO Auto-generated method stub
}
@Override
public void onTabSelected(Tab arg0, FragmentTransaction arg1) {
// TODO Auto-generated method stub
}
@Override
public void onTabUnselected(Tab arg0, FragmentTransaction arg1) {
// TODO Auto-generated method stub
}
3. 加入tab這邊是利用ActionBar去加入tab,
所以我們再加入之前應該先取得actiobar這個object,
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ActionBar actionbar = getSupportActionBar();
}
接著設定navigation mode,
這裡分成三種
- ActionBar.NAVIGATION_MODE_LIST (actionbar左上角會有spinner)
- ActionBar.NAVIGATION_MODE_TABS (就是tabs)
- ActionBar.NAVIGATION_MODE_STANDARD (什麼都不會有,只剩actionbar)
所以理論上我們要設成第二種!
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ActionBar actionbar = getSupportActionBar();
actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
}
最後一步就是加入tab了!
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ActionBar actionbar = getSupportActionBar();
actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// add tab
actionbar.addTab(actionbar.newTab().setText(R.string.tab1).setTabListener(this));
actionbar.addTab(actionbar.newTab().setText(R.string.tab2).setTabListener(this));
}
接著大家就可以deploy上去看看了!
應該就可以看到2個tab出現!
如下圖
這時候大家可能會覺得很奇怪,
不管點tab1還是tab2,
怎麼內容都一樣?
原因是因為你要在先前implement的method(onTabSelected)中,
透過FragmentTransaction把Fragment加進來!
好!這時候大家可能也會好奇一件事,我的Class明明是 extends ActionBarActivity,
怎麼可能在這個class之中把Fragment加進來?不是應該要透過FragmentActivity嗎?
恩,其實如果你們在往下層看,會發現ActionBarActivity這個class也是extends FragmentActivity!
所以自然而然可以在ActionBarActivity中把一個Fragment加進來!
但是!!!!在這裡我不會教你用這種方式!!!
為什麼?
其實在Google Standard之中,希望我們有tabs時,理應上要支援swipe to change tab!
那麼要怎麼做到呢?
就是靠ViewPager!
在
下一篇ActionBarCompat 【Swipe to change tab】中,會教大家怎麼用ViewPager去把Fragment加進來以及可以swipe!