2015年6月29日 星期一

Android GestureOverlayView 辨識 手勢 繪圖

之前下載一個遊戲App Magic Touch ,使用GestureOverlayView 辨識手勢繪圖來消氣球,還蠻好玩的!

1.使用模擬器的Gesture Tool或是用手機前往Google Play下載Gesture Tool
安裝完成後,打開輸入對應的文字與繪圖

2.將該成是儲存的gestures檔案複製,建立一個新專案,在res資料夾建立raw資料加,丟到raw資料夾裡面

3./res/layout/activity_main.xml fadeDuration為繪圖顯示停留時間(毫秒)


    
    


4.MainActivity.java
package tw.android;

import java.util.ArrayList;

import android.app.Activity;
import android.gesture.Gesture;
import android.gesture.GestureLibraries;
import android.gesture.GestureLibrary;
import android.gesture.GestureOverlayView;
import android.gesture.GestureOverlayView.OnGesturePerformedListener;
import android.gesture.Prediction;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

public class MainActivity extends Activity implements
  OnGesturePerformedListener {

 private GestureOverlayView gesture;
 private GestureLibrary gLibrary;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  gesture = (GestureOverlayView) findViewById(R.id.gestureOverlayView1);

  // GestureOverlayView監聽事件
  gesture.addOnGesturePerformedListener(this);

  // 讀取製作的gestures檔案
  gLibrary = GestureLibraries.fromRawResource(this, R.raw.gestures);
  gLibrary.load();

 }

 public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
  
  ArrayList<Prediction> predictions = gLibrary.recognize(gesture);

  if (predictions.size() > 0) {

   Prediction prediction = predictions.get(0);
   Log.i("1111111", predictions.get(1) + "");
   if (prediction.score > 1.5) {// 符合 顯示對應訊息
    Toast.makeText(this, prediction.name, Toast.LENGTH_SHORT).show();
   } else { // 不符合
    Toast.makeText(this, "無法識別", Toast.LENGTH_SHORT).show();
   }
  }
 }
}



檔案下載:
https://github.com/terryyamg/GuestureOverlayViewTest
參考連結:
http://www.tutorialeshtml5.com/2013/02/tutorial-crear-y-reconocer-gestos-con.html
http://developer.android.com/reference/android/gesture/GestureOverlayView.html

2015年6月25日 星期四

Android Overlay WindowManager 覆蓋 小圖示 仿Fackbook Messager

Fackbook Messager收到訊息時會跳出一個小圖示,
此功能使用到WindowManager +Service
1.AndroidManifest.xml 加入權限與Service



    

    
    

    
        
            
                
                

                
                
            
        

        
        
    


2./res/layout/activity_main.xml 主畫面


    

    


3./res/layout/overlay.xml 小圖示


    
    


4.MainActivity.java
package tw.android;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;

public class MainActivity extends Activity {

 private Button btOpen, btClose;
 WindowManager wm;

 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  btOpen = (Button) findViewById(R.id.btOpen);
  btClose = (Button) findViewById(R.id.btClose);

  // 啟動小圖示
  btOpen.setOnClickListener(new Button.OnClickListener() {
   public void onClick(View v) {
    Intent overlayIntent = new Intent();
    overlayIntent.setClass(MainActivity.this, OverlayService.class);
    MainActivity.this.startService(overlayIntent);
   }
  });

  // 關閉主畫面
  btClose.setOnClickListener(new Button.OnClickListener() {
   public void onClick(View v) {
    finish();
   }
  });

 }
}
5.OverlayService.java
package tw.android;

import android.app.Service;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.os.SystemClock;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.widget.ImageButton;

public final class OverlayService extends Service {

 private static final int LayoutParamFlags = WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
   | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
   | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
   | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
   | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;

 private LayoutInflater inflater;
 private Display mDisplay;
 private View layoutView;
 private WindowManager windowManager;
 private WindowManager.LayoutParams params;
 private View.OnTouchListener touchListener;
 private View.OnClickListener clickListener;

 private DisplayMetrics calculateDisplayMetrics() {
  DisplayMetrics mDisplayMetrics = new DisplayMetrics();
  mDisplay.getMetrics(mDisplayMetrics);
  return mDisplayMetrics;
 }

 @Override
 public IBinder onBind(Intent intent) {
  return null;
 }

 @Override
 public void onCreate() {
  super.onCreate();
  params = new WindowManager.LayoutParams(
    WindowManager.LayoutParams.WRAP_CONTENT,
    WindowManager.LayoutParams.WRAP_CONTENT,
    WindowManager.LayoutParams.TYPE_PRIORITY_PHONE,
    LayoutParamFlags, PixelFormat.TRANSLUCENT);
  params.gravity = Gravity.TOP | Gravity.LEFT; // 圖片按鈕的初始位置
  windowManager = (WindowManager) this.getSystemService(WINDOW_SERVICE);
  mDisplay = windowManager.getDefaultDisplay();
  inflater = LayoutInflater.from(this);
  layoutView = inflater.inflate(R.layout.overlay, null); // 取得layout
  windowManager.addView(layoutView, params);

  final ImageButton button = (ImageButton) layoutView
    .findViewById(R.id.toggle); // 取得圖片按鈕
  // 圖片按鈕-點擊監聽事件
  clickListener = new OnClickListener() {
   public void onClick(View view) {
    try {
     Log.i("Service", "stop!");
     // 關閉service
     Intent intent = new Intent(OverlayService.this,
       OverlayService.class);
     stopService(intent);
    } catch (Exception ex) {
    }
   }
  };

  // 圖片按鈕-移動監聽事件
  touchListener = new View.OnTouchListener() {
   private int initialX;
   private int initialY;
   private float initialTouchX;
   private float initialTouchY;
   private long downTime;

   public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN: // 按下圖片按鈕尚未放開時
     Log.i("downTime", downTime + "");
     downTime = SystemClock.elapsedRealtime();
     initialX = params.x;
     initialY = params.y;
     initialTouchX = event.getRawX();
     initialTouchY = event.getRawY();
     return true;
    case MotionEvent.ACTION_UP: // 放開圖片按鈕時
     long currentTime = SystemClock.elapsedRealtime();
     Log.i("currentTime - downTime", currentTime - downTime + "");
     if (currentTime - downTime < 200) { // 當按下圖片按鈕時
      v.performClick(); // 自動點擊事件
     } else {
      // updateViewLocation(); //黏住邊框功能
     }
     return true;
    case MotionEvent.ACTION_MOVE: // 按住移動時
     params.x = initialX
       + (int) (event.getRawX() - initialTouchX);
     params.y = initialY
       + (int) (event.getRawY() - initialTouchY);
     windowManager.updateViewLayout(layoutView, params);
     return true;
    }
    return false;
   }

   // 黏住邊框功能
   private void updateViewLocation() {
    DisplayMetrics metrics = calculateDisplayMetrics();
    int width = metrics.widthPixels / 2;
    if (params.x >= width)
     params.x = (width * 2) - 10;
    else if (params.x <= width)
     params.x = 10;
    windowManager.updateViewLayout(layoutView, params);
   }
  };

  button.setOnClickListener(clickListener); // 圖片按鈕-點擊監聽事件
  layoutView.setOnTouchListener(new OnTouchListener() {
   public boolean onTouch(View view, MotionEvent arg1) {
    return false;
   }
  });
  
  button.setOnTouchListener(touchListener);// 圖片按鈕-移動監聽事件
 }

 @Override
 public void onDestroy() {
  super.onDestroy();
  windowManager.removeView(layoutView);
 }
}



 點擊開啟小圖示後,出現小圖示,點選"離開畫,小圖示仍然存在,可移動,點擊後關閉service,小圖示消失

檔案下載:
 https://github.com/terryyamg/WindowManagerTest
參考連結:
https://github.com/keremkusmezer/OverlayDemo
http://developer.android.com/reference/android/view/WindowManager.LayoutParams.html

2015年6月18日 星期四

Android Skype 功能

運行Skype,並使用Skype API
1.res/layout/activity_main.xml


    
    

    
    

    

    

    

    


2.MainActivity.java
package tw.android;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {

 private EditText edt_skypeusername;
 private Button openskype, skypemsg, skypecall, skypevideocall;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  edt_skypeusername = (EditText) findViewById(R.id.edt_skypeusername);
  openskype = (Button) findViewById(R.id.openskype);
  skypemsg = (Button) findViewById(R.id.skypemsg);
  skypecall = (Button) findViewById(R.id.skypecall);
  skypevideocall = (Button) findViewById(R.id.skypevideocall);

  // 開啟skype

  openskype.setOnClickListener(new OnClickListener() {
   public void onClick(View v) {
    String mySkypeUri = "skype:"; // 傳入要啟動的動作
    SkypeUri(MainActivity.this, mySkypeUri);
   }
  });

  // 傳送訊息
  skypemsg.setOnClickListener(new OnClickListener() {

   public void onClick(View v) {
    String skypeName = edt_skypeusername.getText().toString()
      .trim();
    if (skypeName.length() <= 0) {
     Toast.makeText(getApplicationContext(), "請於上方輸入對方ID...",
       Toast.LENGTH_SHORT).show();
    } else {
     String mySkypeUri = "skype:" + skypeName + "?chat";// 傳入要啟動的動作
     SkypeUri(MainActivity.this, mySkypeUri);
    }
   }
  });

  // Skype Audio call button click event code here
  skypecall.setOnClickListener(new OnClickListener() {

   public void onClick(View v) {
    String skypeName = edt_skypeusername.getText().toString()
      .trim();
    if (skypeName.length() <= 0) {
     Toast.makeText(getApplicationContext(), "請於上方輸入對方ID...",
       Toast.LENGTH_SHORT).show();
    } else {
     String mySkypeUri = "skype:" + skypeName + "?call";// 傳入要啟動的動作
     SkypeUri(MainActivity.this, mySkypeUri);
    }
   }
  });

  // Skype Video call button click event code here
  skypevideocall.setOnClickListener(new OnClickListener() {

   public void onClick(View v) {
    String skypeName = edt_skypeusername.getText().toString()
      .trim();
    if (skypeName.length() <= 0) {
     Toast.makeText(getApplicationContext(), "請於上方輸入對方ID...",
       Toast.LENGTH_SHORT).show();
    } else {
     String mySkypeUri = "skype:" + skypeName
       + "?call&video=true";// 傳入要啟動的動作
     SkypeUri(MainActivity.this, mySkypeUri);
    }
   }
  });
 }

 public void SkypeUri(Context myContext, String mySkypeUri) {

  if (!isSkypeClientInstalled(myContext)) { // 判斷是否有安裝skype
   goToMarket(myContext); // 沒有安裝前往商店安裝
   return;
  }
  Uri skypeUri = Uri.parse(mySkypeUri);
  Intent myIntent = new Intent(Intent.ACTION_VIEW, skypeUri);
  myIntent.setComponent(new ComponentName("com.skype.raider",
    "com.skype.raider.Main"));
  myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  myContext.startActivity(myIntent);

  return;
 }

 // 判斷是否有安裝skype
 public boolean isSkypeClientInstalled(Context myContext) {
  PackageManager myPackageMgr = myContext.getPackageManager();
  try {
   myPackageMgr.getPackageInfo("com.skype.raider",
     PackageManager.GET_ACTIVITIES);
  } catch (PackageManager.NameNotFoundException e) {
   return (false);
  }
  return (true);
 }

 // 前往商店安裝

 public void goToMarket(Context myContext) {
  Uri marketUri = Uri.parse("market://details?id=com.skype.raider");
  Intent myIntent = new Intent(Intent.ACTION_VIEW, marketUri);
  myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  myContext.startActivity(myIntent);
  return;
 }
}

檔案下載:
https://github.com/terryyamg/SkypeTest
參考連結:
https://msdn.microsoft.com/zh-tw/library/office/dn745882.aspx
http://www.limbaniandroid.com/2014/01/how-to-make-skype-audiovideo-call-and.html

2015年6月17日 星期三

iOS Swift Login 練習 登入系統

iOS開發開始
先練習一個登入功能頁面
用到
Label元件
Button元件
TextField元件
頁面切換功能

1.先建立一個Single View Application空白專案

2.打開Main.storyboard 拉一個登入畫面

在右方再拉一個登入成功頁面,並在identity的Storyboard ID 輸入任意名稱,下方Use Storyboard ID 打勾。


3.ViewController.swift
import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var account: UITextField! //輸入帳號
    @IBOutlet weak var password: UITextField! //輸入密碼
    @IBOutlet weak var info: UILabel! //訊息
    let myAccount = "apple" //驗證帳號
    let myPassword = "123" //驗證密碼
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    //登入
    @IBAction func login(sender: UIButton) {
        if account.text == myAccount && password.text == myPassword {
            self.info.text = "成功"
            
            //傳至下一頁面
            let viewController:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("MainActivity")
            
            self.presentViewController(viewController, animated: false, completion: nil)
            // 返回 self.dismissViewControllerAnimated(true, completion: nil)
            
        }else{
            self.info.text = "輸入錯囉"
        }
    }
    
    //清除
    @IBAction func reset(sender: UIButton) {
        account.text = ""
        password.text = ""
    }
    
}

參考連結: https://coderwall.com/p/cjuzng/swift-instantiate-a-view-controller-using-its-storyboard-name-in-xcode

2015年6月14日 星期日

Android LeetCode Happy Number 解題

動動腦,不會老
題目: https://leetcode.com/problems/happy-number/
Write an algorithm to determine if a number is "happy".
A happy number is a number defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy numbers.
Example: 19 is a happy number
  • 12 + 92 = 82
  • 82 + 22 = 68
  • 62 + 82 = 100
  • 12 + 02 + 02 = 1

用Android app試著做一個
1./res/layout/main.xml


    
    

    
    

    

    
    


2.MainActivity.java
package tw.android;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class Main extends Activity {

 private EditText etNumber;
 private Button btSend;
 private TextView tvInfo;

 private int[] numberArray;

 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  etNumber = (EditText) findViewById(R.id.etNumber);
  btSend = (Button) findViewById(R.id.btSend);
  tvInfo = (TextView) findViewById(R.id.tvInfo);

  btSend.setOnClickListener(new Button.OnClickListener() {
   public void onClick(View v) {
    int number = Integer.parseInt(etNumber.getText().toString()); // 輸入數字
    if (isHappy(number)) {
     tvInfo.setText(number + "是 Happy Number");
    } else {
     tvInfo.setText(number + "不是 Happy Number");
    }

   }
  });

 }

 /*
  * Write an algorithm to determine if a number is "happy".
  * 
  * A happy number is a number defined by the following process: Starting
  * with any positive integer, replace the number by the sum of the squares
  * of its digits, and repeat the process until the number equals 1 (where it
  * will stay), or it loops endlessly in a cycle which does not include 1.
  * Those numbers for which this process ends in 1 are happy numbers.
  * 
  * Example: 19 is a happy number
  * 
  * 1^2 + 9^2 = 82 
  * 8^2 + 2^2 = 68 
  * 6^2 + 8^2 = 100 
  * 1^2 + 0^2 + 0^2 = 1
  */

 /* 回傳驗證是否為happy number */
 public boolean isHappy(int n) {
  Log.i("keyNumber:", n + "");
  int sum, length;
  do {
   sum = getNumber(n, Integer.toString(n).length());
   length = Integer.toString(sum).length(); // 總和數字長度
   n = sum;
  } while (length != 1);// 重複執行到剩個位數
  
  Log.i("sum:", sum + "");
  if (sum == 1) { // 個位數等於1 happy number!!
   return true;
  } else { // 不是happy number...
   return false;
  }
 }

 /* 取得每個數字 放入數字陣列 計算總合 */
 public int getNumber(int n, int length) {
  /* 建立每個數字陣列 */
  numberArray = new int[length];
  int quotient = 0;// 商數
  int sum = 0; // 總合
  for (int i = 0; i < length; i++) {
   if (i == 0) { // 一開始輸入的數字計算
    numberArray[i] = n % 10; // 獲得餘數
    quotient = n / 10; // 獲得商數
   } else { // 計算後的總合再計算
    numberArray[i] = quotient % 10; // 獲得餘數
    quotient = quotient / 10; // 獲得商數
   }
   sum += (int) Math.pow(numberArray[i], 2); // 計算總和

  }
  return sum; // 回傳總和
 }

}



檔案下載:https://github.com/terryyamg/HappyNumberTest

2015年6月8日 星期一

Android SlidingDrawer 滑動 視窗

上下左右的滑動視窗
1.res/layout/activity_main.xml


    

        
        

        
        

        
        

        
        

        
        

        
        

        
        

        
        

        
        

        
        

        
    

    

        

        
        
    


2.MainActivity.java
package tw.android;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.SlidingDrawer;
import android.widget.SlidingDrawer.OnDrawerCloseListener;
import android.widget.SlidingDrawer.OnDrawerOpenListener;
import android.widget.Toast;

@SuppressWarnings("deprecation")
public class MainActivity extends Activity {

 private EditText etT, etB, etL, etR, etRotation;
 private Button btConfirm;
 private SlidingDrawer sd;
 private int left, top, right, bottom;

 /** Called when the activity is first created. */
 @SuppressLint("ShowToast")
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  etT = (EditText) findViewById(R.id.etT);
  etB = (EditText) findViewById(R.id.etB);
  etL = (EditText) findViewById(R.id.etL);
  etR = (EditText) findViewById(R.id.etR);
  etRotation = (EditText) findViewById(R.id.etRotation);
  btConfirm = (Button) findViewById(R.id.btConfirm);
  sd = (SlidingDrawer) findViewById(R.id.sd);

  /* 確認輸入 */
  btConfirm.setOnClickListener(new Button.OnClickListener() {

   public void onClick(View v) {
    /* 輸入SlidingDrawer距離上方位置 */

    left = Integer.parseInt(etL.getText().toString()); // 左
    top = Integer.parseInt(etT.getText().toString()); // 上
    right = Integer.parseInt(etR.getText().toString()); // 右
    bottom = Integer.parseInt(etB.getText().toString()); // 下

    if (left > 1000 || top > 1000 || right > 1000 || bottom > 1000) {
     Toast.makeText(getApplicationContext(), "不可大於1000",
       Toast.LENGTH_SHORT).show();

    } else {
     RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
       RelativeLayout.LayoutParams.WRAP_CONTENT,
       RelativeLayout.LayoutParams.WRAP_CONTENT);

     lp.setMargins(left, top, right, bottom);
     sd.setLayoutParams(lp);
     /* 輸入SlidingDrawer旋轉角度 */
     sd.setRotation(Integer.parseInt(etRotation.getText()
       .toString()));

     Toast.makeText(getApplicationContext(), "輸入完成",
       Toast.LENGTH_SHORT).show();
    }

   }
  });

  /* 打開監聽動作 */
  sd.setOnDrawerOpenListener(new OnDrawerOpenListener() {
   public void onDrawerOpened() {

    Toast.makeText(getApplicationContext(), "我被拉開了",
      Toast.LENGTH_SHORT).show();
    ;
   }
  });

  /* 關閉監聽動作 */
  sd.setOnDrawerCloseListener(new OnDrawerCloseListener() {

   public void onDrawerClosed() {
    Toast.makeText(getApplicationContext(), "我被關閉了",
      Toast.LENGTH_SHORT).show();
   }
  });

 }
}



參考來源:
http://examples.javacodegeeks.com/android/core/widget/slidingdrawer/android-slidingdrawer-example/
http://stackoverflow.com/questions/3695856/android-slidingdrawer-from-top

2015年6月4日 星期四

Android Studio Import libs 專案 匯入 套件 UI 美化

Android Studio專案套件匯入與eclipse匯入方式不同
1.首先建立一個空白專案,建立完成後打開在app下的build.gradle檔案

2.以https://github.com/rey5137/material UI 為例,在build.gradle檔案加入
compile 'com.android.support:appcompat-v7:21.0.3' 
compile 'com.github.rey5137:material:1.1.1'
compile 'com.android.support:cardview-v7:21.0.3'





3.基本上在這裡點選Build -> Clear Project 就會下載匯入在你的專案裡


4.在專案點右鍵 -> Open Module Settings中的Dependencies裡可以看到匯入的lib



5.下載https://github.com/rey5137/material/archive/master.zip 拿裡面的demo檔來測試
位置在下載的資料夾material-master\app\src\main,在這裡先測試button原件
將material-master\app\src\main\res除了layout資料夾其他資料夾複製到你的專案底下 res的位置


6.在專案res/下建立layout資料夾,建立activity_main.xml,複製material-master\app\src\main\res\layout\fragment_button.xml裡的程式碼


    

        

        

            

            

            

        

        

            

            

            

        

        

        

            

            

            

        

        

            

            

            

        

        

        

            

            

            

        

        

            

            

            

        

    



    
7.建立MainActivity.java
import android.app.Activity;
import android.os.Bundle;
import android.view.View;

import com.rey.material.drawable.RippleDrawable;
import com.rey.material.widget.Button;
import com.rey.material.widget.FloatingActionButton;

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button bt_flat = (Button) findViewById(R.id.button_bt_flat);
        Button bt_flat_color = (Button) findViewById(R.id.button_bt_flat_color);
        Button bt_flat_wave = (Button) findViewById(R.id.button_bt_flat_wave);
        Button bt_flat_wave_color = (Button) findViewById(R.id.button_bt_flat_wave_color);
        Button bt_raise = (Button) findViewById(R.id.button_bt_raise);
        Button bt_raise_color = (Button) findViewById(R.id.button_bt_raise_color);
        Button bt_raise_wave = (Button) findViewById(R.id.button_bt_raise_wave);
        Button bt_raise_wave_color = (Button) findViewById(R.id.button_bt_raise_wave_color);
        FloatingActionButton bt_float = (FloatingActionButton) findViewById(R.id.button_bt_float);
        FloatingActionButton bt_float_color = (FloatingActionButton) findViewById(R.id.button_bt_float_color);
        FloatingActionButton bt_float_wave = (FloatingActionButton) findViewById(R.id.button_bt_float_wave);
        FloatingActionButton bt_float_wave_color = (FloatingActionButton) findViewById(R.id.button_bt_float_wave_color);

        /*左邊正常速度*/
        View.OnClickListener listener = new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                if (v instanceof FloatingActionButton) {
                    FloatingActionButton bt = (FloatingActionButton) v;
                    bt.setLineMorphingState((bt.getLineMorphingState() + 1) % 2, true);
                }

                System.out.println(v + " " + ((RippleDrawable) v.getBackground()).getDelayClickType());
            }
        };
        /*右邊DELAY速度*/
        View.OnClickListener listener_delay = new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                if (v instanceof FloatingActionButton) {
                    FloatingActionButton bt = (FloatingActionButton) v;
                    bt.setLineMorphingState((bt.getLineMorphingState() + 1) % 2, true);
                }

                System.out.println(v + " " + ((RippleDrawable) v.getBackground()).getDelayClickType());
            }
        };

        /*監聽事件*/
        bt_flat.setOnClickListener(listener);
        bt_flat_wave.setOnClickListener(listener);
        bt_raise.setOnClickListener(listener);
        bt_raise_wave.setOnClickListener(listener);
        bt_float.setOnClickListener(listener);
        bt_float_wave.setOnClickListener(listener);

        bt_flat_color.setOnClickListener(listener_delay);
        bt_flat_wave_color.setOnClickListener(listener_delay);
        bt_raise_color.setOnClickListener(listener_delay);
        bt_raise_wave_color.setOnClickListener(listener_delay);
        bt_float_color.setOnClickListener(listener_delay);
        bt_float_wave_color.setOnClickListener(listener_delay);

    }

}
8.最後修改一下AndroidManifest.xml


    
    

        
            
                

                
            
        
    




其餘的UI就依樣畫葫蘆

檔案下載: https://github.com/terryyamg/ASLibTest
參考連結:https://github.com/rey5137/material

2015年6月3日 星期三

Android Expandablelistview 展開列表

基本功能Expandablelistview,展開列項目的子項目列表,附加圖示
1./res/layout/activity_main 主畫面


    
    


2./res/layout/list_group.xml 標題layout


    
    

    
    


3./res/layout/list_item.xml 內容layout


    

        
        
    


4.ExpandableListAdapter.java
package tw.android;

import java.util.HashMap;
import java.util.List;

import android.content.Context;
import android.graphics.Typeface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class ExpandableListAdapter extends BaseExpandableListAdapter {

 private Context context;
 private int[] listIv; // 標題圖示
 private List<String> listDataHeader; // 標題
 private HashMap<String, List<String>> listDataChild; // 內容

 /**
  * @param listIv
  *            -標題圖示
  * @param listDataHeader
  *            -標題
  * @param listChildData
  *            -內容
  */
 public ExpandableListAdapter(Context context, int[] listIv,
   List<String> listDataHeader,
   HashMap<String, List<String>> listChildData) {
  this.context = context;
  this.listIv = listIv;
  this.listDataHeader = listDataHeader;
  this.listDataChild = listChildData;
 }

 /* -------------------- 內容 -------------------- */
 public Object getChild(int groupPosition, int childPosititon) {
  return this.listDataChild.get(this.listDataHeader.get(groupPosition))
    .get(childPosititon);
 }

 public int getChildrenCount(int groupPosition) {
  return this.listDataChild.get(this.listDataHeader.get(groupPosition))
    .size();
 }

 public long getChildId(int groupPosition, int childPosition) {
  return childPosition;
 }

 /* 內容View */
 public View getChildView(int groupPosition, final int childPosition,
   boolean isLastChild, View convertView, ViewGroup parent) {

  final String childText = (String) getChild(groupPosition, childPosition); // 取得內容

  /* 設置內容layout */
  if (convertView == null) {
   LayoutInflater infalInflater = (LayoutInflater) this.context
     .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
   convertView = infalInflater.inflate(R.layout.list_item, null);
  }

  /* 設置內容 */
  TextView txtListChild = (TextView) convertView
    .findViewById(R.id.lblListItem);

  txtListChild.setText(childText);
  return convertView;
 }

 /* -------------------- 標題 -------------------- */
 public Object getGroup(int groupPosition) {
  return this.listDataHeader.get(groupPosition);
 }

 public int getGroupCount() {
  return this.listDataHeader.size();
 }

 public long getGroupId(int groupPosition) {
  return groupPosition;
 }

 /* -------------------- 標題圖示 -------------------- */
 public Object getGroupView(int groupPosition) {
  return Integer.toString(this.listIv[groupPosition]);
 }

 public int getGroupViewCount() {
  return this.listIv.length;
 }

 public long getGroupViewId(int groupPosition) {
  return groupPosition;
 }

 /* 標題View */
 public View getGroupView(int groupPosition, boolean isExpanded,
   View convertView, ViewGroup parent) {
  String headerIv = (String) getGroupView(groupPosition); // 取得圖示
  String headerTitle = (String) getGroup(groupPosition); // 取得標題
  /* 設置標題layout */
  if (convertView == null) {
   LayoutInflater infalInflater = (LayoutInflater) this.context
     .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
   convertView = infalInflater.inflate(R.layout.list_group, null);
  }

  /* 設置圖示 */
  ImageView iv = (ImageView) convertView.findViewById(R.id.iv);
  iv.setImageResource(Integer.parseInt(headerIv));
  /* 設置標題 */
  TextView lblListHeader = (TextView) convertView
    .findViewById(R.id.lblListHeader);
  lblListHeader.setTypeface(null, Typeface.BOLD);
  lblListHeader.setText(headerTitle);

  return convertView;
 }

 /* ------------------------------------------------ */
 public boolean hasStableIds() {
  return false;
 }

 public boolean isChildSelectable(int groupPosition, int childPosition) {
  return true;
 }
}

5.MainActivity.java
package tw.android;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.ExpandableListView.OnGroupCollapseListener;
import android.widget.ExpandableListView.OnGroupExpandListener;
import android.widget.Toast;

public class MainActivity extends Activity {

 ExpandableListAdapter listAdapter;
 ExpandableListView expListView;
 int[] listIv; //圖示
 List<String> listDataHeader; //標題
 HashMap<String, List<String>> listDataChild; //內容

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  // 取得ExpandableListView
  expListView = (ExpandableListView) findViewById(R.id.lvExp);

  // 列表資料
  prepareListData();

  /* listIv-圖示, listDataHeader-標題, listDataChild-內容*/
  listAdapter = new ExpandableListAdapter(this,listIv, listDataHeader,
    listDataChild);

  // 將列表資料加入至展開列表單
  expListView.setAdapter(listAdapter);

  // 點選標題 展開 監聽事件
  expListView.setOnGroupExpandListener(new OnGroupExpandListener() {

   public void onGroupExpand(int groupPosition) {
    Toast.makeText(getApplicationContext(),
      "您正在收看:" + listDataHeader.get(groupPosition),
      Toast.LENGTH_SHORT).show();
   }
  });

  // 點選標題監聽事件
  expListView.setOnChildClickListener(new OnChildClickListener() {

   public boolean onChildClick(ExpandableListView parent, View v,
     int groupPosition, int childPosition, long id) {
    Toast.makeText(
      getApplicationContext(),
      "開始閱讀:"
        + listDataHeader.get(groupPosition)
        + " : "
        + listDataChild.get(
          listDataHeader.get(groupPosition)).get(
          childPosition), Toast.LENGTH_SHORT)
      .show();
    return false;
   }
  });

  // 點選標題 收回 監聽事件
  expListView.setOnGroupCollapseListener(new OnGroupCollapseListener() {

   public void onGroupCollapse(int groupPosition) {
    Toast.makeText(getApplicationContext(),
      "放回書架:" + listDataHeader.get(groupPosition),
      Toast.LENGTH_SHORT).show();

   }
  });

 }

 /* 列表資料 */
 private void prepareListData() {
  listIv = new int[]{R.drawable.p1,R.drawable.p2,R.drawable.p3}; //圖示
  listDataHeader = new ArrayList<String>(); // 標題
  listDataChild = new HashMap<String, List<String>>(); // 內容

  listDataHeader.add("水滸傳");
  listDataHeader.add("紅樓夢");
  listDataHeader.add("三國演義");

  // Adding child data
  List<String> first = new ArrayList<String>();
  first.add("第一回  張天師祈禳瘟疫 洪太尉誤走妖魔");
  first.add("第二回  王教頭私走延安府 九紋龍大鬧史家村");
  first.add("第三回  史大郎夜走華陰縣 魯提轄拳打鎮關西");
  first.add("第四回  趙員外重修文殊院 魯智深大鬧五臺山");
  first.add("第五回  小霸王醉入銷金帳 花和尚大鬧桃花村");

  List<String> second = new ArrayList<String>();
  second.add("第一回  甄士隱夢幻識通靈 賈雨村風塵懷閨秀");
  second.add("第二回  賈夫人仙逝揚州城 冷子興演說榮國府");
  second.add("第三回   託內兄如海薦西賓 接外孫賈母惜孤女");
  second.add("第四回  薄命女偏逢薄命郎 葫蘆僧判斷葫蘆案");
  second.add("第五回  賈寶玉神遊太虛境 警幻仙曲演紅樓夢");

  List<String> end = new ArrayList<String>();
  end.add("第一回  宴桃園豪傑三結義,斬黃巾英雄首立功");
  end.add("第二回  張翼德怒鞭督郵,何國舅謀誅宦豎");
  end.add("第三回  議溫明董卓叱丁原,餽金珠李肅說呂布");
  end.add("第四回  廢漢帝陳留為皇,謀董賊孟德獻刀");
  end.add("第五回  發矯詔諸鎮應曹公,破關兵三英戰呂布");

  listDataChild.put(listDataHeader.get(0), first); // 標題, 內容
  listDataChild.put(listDataHeader.get(1), second);
  listDataChild.put(listDataHeader.get(2), end);
 }
}
檔案下載: https://github.com/terryyamg/ExpandablelistviewTest
參考連結: http://www.androidhive.info/2013/07/android-expandable-list-view-tutorial/