2014年2月24日 星期一

如何不透過email 傳送資料給自己的手機或電腦


不要再使用email傳送檔案給自己了,使用pushbullet吧!!

甚麼是pushbullet?

當你在手機上有一些資料想要傳到電腦或者有些資料想從電腦傳到手機時,
通常我們都會用facebook ,email 或 藍芽 ....等方式傳資料給自己。
pushbullet想做的事情很簡單


用最好理解的方式說明,你可以把他想成是可以跟自己對話的 line or whatsapp


現在介紹pushbullet

登入之後會出現上方的圖,只要在自己的裝置上安裝他專屬的app 就可以傳送檔案,文件,文字了,在chrome上必須安裝extension。

pushbullet還支援api,有機會再來分享這部份給大家




2014年2月17日 星期一

Android 開發 (三十一) layer-list 使用

Layer-list 讓我們可以層疊客制多層的layer,由於android手機的解析度非常眾多,這對UE來說是非常大的負擔,很難用一張圖來滿足所有的解析度,通常比較簡單的button 或線都會用畫的,這樣的好處是,圖的解析度比較不會跑掉,只是這也就苦了RD了。


如何使用layer-list?

如下方的按鈕

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <item>
        <shape android:shape="rectangle" >
            <corners android:radius="10dp" />

            <solid android:color="#2caabb" />
        </shape>
    </item>
    <item
        android:bottom="3dp"
        android:left="3dp"
        android:right="3dp"
        android:top="3dp">
        <shape android:shape="rectangle" >
            <corners android:radius="10dp" />

            <solid android:color="#222244" />
        </shape>
    </item>
    <item
        android:bottom="7dp"
        android:left="7dp"
        android:right="7dp"
        android:top="7dp">
        <shape android:shape="rectangle" >
            <corners android:radius="10dp" />

            <solid android:color="#333333" />
        </shape>
    </item>
    <item
        android:bottom="9dp"
        android:left="9dp"
        android:right="9dp"
        android:top="9dp">
        <shape android:shape="rectangle" >
            <corners android:radius="10dp" />

            <solid android:color="#2cbb77" />
        </shape>
    </item>

</layer-list>

每個item都代表一層
上面那張圖是由四層圖層疊出來的
corners使方型的角變成圓角
shape 擁有四種形狀  ["rectangle" | "oval" | "line" | "ring"] 

更詳細的說明可以觀看 android developer的網址
http://developer.android.com/guide/topics/resources/drawable-resource.html#LayerList

Android 開發 (三十) Selector 使用

Selector讓我們可以客製化我們想要的UI色彩,
例如我希望按鈕在正常的情況下是灰色,在按下去時為藍色
又或者我希望checkbox在正常的情況下是灰色,被check的時候是藍色
要實作這個功能首先必須先在drawable-xxxx folder中創造一個

myselector.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@color/mycolor1" android:state_pressed="true"></item>
    <item android:drawable="@color/mycolor2" android:state_pressed="false"></item>

</selector>

在上面的程式裡,我設定當view 的state為 pressed的時候  會顯示 mycolor1的drawable
當view的state為 not pressed的時候,會顯示mycolor2的drawable。

接著只需要設定 android:background="@drawable/myselector" 之後當客製化色彩的button就完成了

接著要客製化checkbox

checkboxselector.xml


<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@color/mycolor1" android:state_checked="true"/>
    <item android:drawable="@color/mycolor2" android:state_checked="false"/>
    <item android:drawable="@color/mycolor2"/>

</selector>

上面的程式碼設定了當view 被 check的時候 顯示mycolor1 ,沒有check的時候顯示mycolor2
, 預設的色彩為 mycolor2
接著只需要設定 android:background="@drawable/checkboxselector"  就完成了

使用selector讓我們可以設定不同state時我們想要的色彩或者圖案。
在android developer網頁有更詳細的描述
http://developer.android.com/guide/topics/resources/drawable-resource.html#StateList

2014年2月16日 星期日

Android 開發 (二十九) imagelevel

為何要使用setimagelevel?

在設定圖片時,android 有一種方式讓我們可以在不同的level顯示不同的圖片,
這樣的好處是不需要重新去尋找圖檔,只需要在一開始做好設定,之後就利用定義好的level去切換就好了,例如  press 就是 level 1     release 就是level 2   check就是level3 ... etc


要如何使用setimagelevel的功能呢?

首先,我們必須先設定level-list  如下

imagelevel.xml
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:maxLevel="1" android:drawable="@drawable/c" />
    <item android:maxLevel="2" android:drawable="@drawable/b" />
    <item android:maxLevel="3" android:drawable="@drawable/d" />
    <item android:maxLevel="4" android:drawable="@drawable/e" />
    <item android:maxLevel="5" android:drawable="@drawable/a" />
</level-list>

接著設定imageview的src


    <ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/imagelevel" />

接著只需要在條件符合時呼叫 setImageLevel(1)   or  setImageLevel(2)
這樣就可以讓圖片隨著不同的state變更圖片了,這樣的好處是,這個頁面的圖片一目瞭然,
看程式的時候不再需要整個程式碼一張一張尋找了。

2014年2月13日 星期四

Android 開發 (二十八) onInterceptTouchEvent 和 onTouchEvent 的處理

為何要瞭解event的處理

有些時候會在viewgroup裡放其他View,然後會希望某些view的touch event不動作,這時候就必須設法去處理onInterceptTouchEvent  和  onTouchEvent。
例如在viewpager裡面放 imageview,當click在imageview時不希望viewpager有動作,又或者listview 裡放button,但是只希望接收到listview click event。


甚麼是onInterceptTouchEvent  和  onTouchEvent

onInterceptTouchEvent就是用來攔截事件,而onTouchEvent是用來處理事件。
當事件被InterceptEvent攔截之後就不會再往下傳遞給childLayout,
然而當事件被Touchevent處理過後就不會再向ParentLayout傳遞。


當所有的event回傳值都是false時
可以看到debug log 從
 listview OninterceptEvent -> TextView OninterceptEvent
->TextView OnTouchEvent -> listview OnTouchEvent
假設 textview 的 onTouchevent 回傳值為 true
Debug log會變成
 listview OninterceptEvent -> TextView OninterceptEvent ->TextView OnTouchEvent
由於事件被textview處理完成 ,所以listview就不需再處理。
假設 listview 的 onInterceptEvent 回傳值為 true
Debug log會變成
 listview OninterceptEven ->ListView OnTouchEvent
由於事件被Listview攔截 ,所以textview就不會接收到event。

結論

利用onInterceptTouchEvent  和  onTouchEvent這兩個event,
就可以輕鬆客制化自己想要的行為。

2014年2月11日 星期二

Android 開發 (二十七) tabhost 加上viewpager 使用

Tabhost以及ViewPager介紹

如下圖,在設計app時,常常會使用到這種分頁方式,
例如我寫了一個email app, tab a為  hotmail  , tab b 為 gmail  ....以此類推,
tabhost就是上面的tab,而viewPager讓我們能夠利用滑動切換頁面
兩個加在一起的話,有較好的使用者經驗。


要如何使用

首先必須先創建 main.xml
在xml可以看到,layout裡面同時擁有 tabhost 以及viewpager

<TabHost android:layout_height="fill_parent" android:layout_width="fill_parent" android:id="@+id/tabhost" xmlns:android="http://schemas.android.com/apk/res/android">


<LinearLayout android:layout_height="fill_parent" android:layout_width="fill_parent" android:orientation="vertical">

<TabWidget android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@android:id/tabs" android:layout_marginRight="3dp" android:layout_marginLeft="3dp"> </TabWidget>

<android.support.v4.view.ViewPager android:layout_height="fill_parent" android:layout_width="fill_parent" android:id="@+id/viewpager"/>

<FrameLayout android:layout_height="fill_parent" android:layout_width="fill_parent" android:id="@android:id/tabcontent" android:visibility="gone"> </FrameLayout>

</LinearLayout>

</TabHost>

接著在 tabFragment內


	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View view = inflater.inflate(R.layout.login_tab_layout, container,false);
		mPager  = (ViewPager) view.findViewById(R.id.viewpager);
		mTabHost = (TabHost)  view.findViewById(R.id.tabhost);
		mTabHost.setup();	
		mTabHost.setOnTabChangedListener(new OnTabChangeListener() {
            @Override
            public void onTabChanged(String tabId) {
            	mTabHost.setOnTabChangedListener(new OnTabChangeListener() {
                        @Override
                        public void onTabChanged(String tabId) {                           	
                        		mPager.setCurrentItem(mPager.getAdapter().getItemPosition(fragmentMap.get(tabId)));
                        }
                    });
                
            }
        });
		
        mPager.setOnPageChangeListener(new OnPageChangeListener() {
            
        	@Override
            public void onPageSelected(int position) {            	
            		mTabHost.setCurrentTab(position);
            }
            
            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) {}
            
            @Override
            public void onPageScrollStateChanged(int arg0) {}
        });
		return view;
	}		

在點擊tabhost時同時切換viewpager
在切換viewpager時同時切換tabhost

接著要添加fragment在viewpager內,以及添加tab在Tabhost內

public void addFragmentTab(int titleResId, int tabViewResId, Fragment fragment , String tag){
		list.add(fragment);
		fragmentMap.put(tag, fragment);
		TextView tabView = (TextView) LayoutInflater.from(getActivity()).inflate(tabViewResId, null);
		tabView.setText(titleResId);

		TabSpec tabSpec = mTabHost.newTabSpec(tag).setIndicator(tabView);
	    tabSpec.setContent(new TabFactory(getActivity()));
	    mTabHost.addTab(tabSpec);
	   
	}


接著就完成了
搭配 Android 開發 (二十五) how to change bottom color of tabhost 
就可以完成客製化tab

附上 git 的project url

Android 開發 (二十六) handle hyperlink in textView(二)

在 handle hyperlink in textView(一) 中有提到如何使 textview 能夠處理url 使之能夠被點擊。
但是如果僅使用那邊的寫法,當將這個textview放到 listview內會造成 itemclick無法被點擊的問題。

為何會造成這個問題?

由於設定 setmovementmethod會同時 
  • setFocusable(true);
  • setClickable(true);
  • setLongClickable(true);
簡單的說就是 Event 都被 Textview處理掉了,所以listview拿不到itemclick event。
所以我們必須客製化touch event,只有在url被點擊的時候,才使用Textview去處理,其他時候就將event 往下傳遞。


首先要稍微提一下 onTouchEvent的 override
return true  代表這個事件在這邊被處理,所以不會再往下傳遞。
return false 代表事件並未被處理,會繼續向下傳遞。




首先先客製化 LinkMovementMethod 只有在url 被點擊時才處理 (return true)

 public static class LocalLinkMovementMethod extends LinkMovementMethod{
     static LocalLinkMovementMethod sInstance;


     public static LocalLinkMovementMethod getInstance() {
         if (sInstance == null)
             sInstance = new LocalLinkMovementMethod();

         return sInstance;
     }

     @Override
     public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
         int action = event.getAction();

         if (action == MotionEvent.ACTION_UP ||
                 action == MotionEvent.ACTION_DOWN) {
             int x = (int) event.getX();
             int y = (int) event.getY();

             x -= widget.getTotalPaddingLeft();
             y -= widget.getTotalPaddingTop();

             x += widget.getScrollX();
             y += widget.getScrollY();

             Layout layout = widget.getLayout();
             int line = layout.getLineForVertical(y);
             int off = layout.getOffsetForHorizontal(line, x);

             ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);

             if (link.length != 0) {
                 if (action == MotionEvent.ACTION_UP) {
                     link[0].onClick(widget);
                 } else if (action == MotionEvent.ACTION_DOWN) {
                     Selection.setSelection(buffer,
                             buffer.getSpanStart(link[0]),
                             buffer.getSpanEnd(link[0]));
                 }

                 if (widget instanceof LinkEnabledTextView){
                     ((LinkEnabledTextView) widget).linkHit = true;
                 }
                 return true;
             } else {
                 Selection.removeSelection(buffer);
                 Touch.onTouchEvent(widget, buffer, event);
                 return false;
             }
         }
         return Touch.onTouchEvent(widget, buffer, event);
     }
 }


接著在客製化的 textView 裡面 override touchevent 和 focus


 @Override
 public boolean hasFocusable() {
  // TODO Auto-generated method stub
  return false;
 }
 
 @Override
 public boolean onTouchEvent(MotionEvent event) {
     linkHit = false;
     boolean res = super.onTouchEvent(event);

     if (dontConsumeNonUrlClicks)
         return linkHit;
     return res;

 }


經過這樣的修改,listview的onitemclick event就不會再被textview吃掉了。