2015年2月10日 星期二

從逆襲到稱王

由於公司讀書會的緣故,讓我有機會能夠從做產品的角度去閱讀一本書,這也是我第一次覺得一本書讀起來那麼有份量,總共六次的分享討論,還有每個人的意見分享,讓我獲益良多,對於作者的一些想法也有相當的認同,在這邊就稍微述說一下這本書讓我特別有印象的幾個part吧!!


解決用戶的問題 -> 累積到海量用戶 -> 賺錢模式自然會出現

周鴻禕提到,要用心觀察使用者的行為,想辦法去解決使用者的痛點,這樣就會有用戶來使用你的服務,這時候通常賺錢模式還不是很清楚,但是等到累積到了大量的用戶時,賺錢模式就會自然出現.

就像是line,提供了我們非常方便的傳訊聊天功能,但是這些服務都不用錢,那line怎麼賺錢呢?賣貼圖,廠商onAir,廠商廣告,他打破了以前傳訊息的商業模式,同時也創造了新的模式.

使用者體驗

周鴻禕提到,使用者體驗很重要,使用者體驗很重要,使用者體驗很重要,因為很重要所以要講三次,他利用了大量的篇幅告訴我們使用者體驗很重要,舉個最近的例子好了,最近有一個app提供每個月100分鐘的免費市話,這相當的吸引我,我知道的當天就下載了,可是點進去隨便點幾下就crash了,然後放在背景還會不斷crash,然後....我用完第一次之後就刪掉了,雖然他解決了我的痛點,可是他的用戶體驗真的不是很好,所以被我用完就刪掉了...

就如同周鴻禕提到的360衛士並不會在開機時掃毒,或者使用者在玩遊戲時掃毒,我覺得這個真的很重要,以前我就有幾次在中路pk的時候防毒軟體跳出來害死我,那種感覺真的很!#@$#,還會被隊友罵,如果那個時候就有360的話我或許會直接換防毒軟體.


看完這本書之後對互聯網有了新的認識,當然對於自家的產品也有不一樣的想法,還有身為一個RD重新對”需求“的定義有了新的想法.

這時候又忽然想起了多年前朋友跟我說的一句話,要讓RD能夠理解需求的原由就是把RD帶到用戶面前他就會懂了XD



2015年2月8日 星期日

Android開發(八十一) 如何使用recyclerview 畫出多種span的layout 例如gridview Header

先看一下下面的圖

在recyclerview出現以前要畫出上面這樣的layout其實是比較困難的,那時候必須要自己想辦法刻,如果是更複雜的layout就需要花更多時間來設法客製化了.

但是在recyclerview出現之後,要畫出這樣的layout就變得相對簡單了許多,
recyclerview強大的地方在於他有layoutmanger
使用gridlayout manager就可以讓layout長的像gridview一樣,
不過要如何才能動態控制我們想要的Span呢?

gridlayoutmanager有提供一個method叫做 setSpanSizeLookup
在callback裡面只需要回傳某個位置所需要的spansize,最終在layout被畫出來時就會是我們所指定的size,就是那麼簡單就可以完成我們所想要的功能了!!

那要完成gridview header呢?...我想也是相當容易的事情~
只需要將position = 0 的 span size 設為 colum size 即可


最後附上sample code
https://gist.github.com/nightbear1009/bd09fdbd30f92504290f

Android 開發(八十) kotlin GettingStart

什麼是kotlin?

http://kotlinlang.org/

kotlin settingup

http://kotlinlang.org/docs/reference/using-gradle.html

如何將程式碼轉換















轉換後的結果















要學kotlin其實就像是必須學新的語言,雖然必須花點時間才能學會but...
學會之後的好處還蠻多的,例如我相信下面的程式碼是大多數人會遇到的情況

    val obj2: MyObject? = null
        obj2?.getMethod("2")


    MyObject obj2 = null;
    obj2.getMethod("2");
        
第一個程式碼並不會crash,但是第二個程式碼會crash, 原因是並沒有做null check,
在這裡使用kotlin的好處就是....我們再也不需要寫一堆if來判斷是否為null
學會了kotlin之後
 if(data !=null && data.list !=null && data.list.get(0).name) 
相信這樣的程式碼就不會再出現了 bravo!!

2015年1月7日 星期三

Android 開發(七十九) How to handle Deeplinking in Android (Facebook, Native Browser)


前陣子facebook改版,導致我們的deeplinking的功能無法使用, 當時有想出一個暫時的解法,不過這幾天facebook再度改版,之前的做法又不能用了,這是只好花點時間來看文件找解法,最後有找到一些相關的解決方法,在這邊分享給各位


facebook deeplinking

關於facebook deeplinking 在最近一次改版之後,假設沒有按照facebook官方文件設定的話,都會出現粉絲頁無法載入的問題,所以我們只好依照官方文件實作了

<head>
    ...
    <meta property="al:android:url" content="sharesample://story/1234">
    <meta property="al:android:package" content="com.facebook.samples.sharesample">
    <meta property="al:android:app_name" content="ShareSample">
    ...
</head>

在html的header加入上面這些meta即可,
基本上我覺得主要是看al:android:url 裡面的參數
其他兩個似乎沒什麼用處(for now)

如上範例,在app的activity裡面就必須要有對應的code

<activity android:name=".MainActivity"
    android:label="@string/app_name" >
    ...
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:scheme="sharesample" />
    </intent-filter>
</activity>

基本上這樣實作之後facebook導頁就不會有問題了.....
but....內建的browser還是不會work啊怎麼辦??


Native Browser

在google 文件的深處,有一個關於deep linking文件裡面有教我們該如何做相關的導頁動作

<a href="intent://gizmos#Intent;scheme=example;package=com.example.android;end;">example://gizmos</a>
只要點擊網頁中的超連結就可以開啟監聽特定scheme的app了

but......deeplink就是希望user點擊完某特定連結之後就可以直接開啟app啊!!!
怎麼能夠讓user再點完一次連結之後再點令一次連結呢?

相信有做過實驗的人都知道使用 window.location 和  setTimeout
在內建瀏覽器是不work的,那.......該怎麼辦?

<meta http-equiv="refresh" content="5;url=intent://gizmos#Intent;scheme=example;package=com.example.android;end;/>




將上面的meta加到header裡就可以完成自動導頁的功能囉!!!

2014年12月18日 星期四

Android 開發(七十八) GoogleCalendar ListView


不知道大家是否有看過這個特效,在滑動的時候listview裡面的圖片會跟著畫面移動
如下圖


第一次看到的時候真的覺得這個特效很特別,很想知道怎麼做的,
所以就花了幾天研究了這個功能.

在經過了初步的研究之後,發現這個功能應該很容易可以達到,

首先需要抓到該 item在畫面的位置,接著只需要針對位置做相對應的滑動即可,

所以列了兩個任務

  1. 可滑動的ImageView
  2. 抓到item在畫面中的位置

關於可滑動的ImageView
一開始的想法是 SlideImage_FirstVersion 
利用改變drawBitmap top的 position來改變圖片顯示的高度,
這個方法實際用起來的感覺有點頓頓的,所以後來這個寫法就被改寫了

第二個想法是 SlideImage_SecondVersion
利用改變scrollY 去改變可視的範圍
這個方法看起來是可行的,也不會造成額外的performance issue

當完成了上面的功能時,我以為可以很快的完成這個功能,
殊不知困難的會是在第二點,如何抓到item在畫面中的位置是非常困難的,

一開始是使用 recyclerView.getChildAt(index).getTop()
在看了debug log之後就知道這個方法是行不通的,這個方法取得的getTop並不是某個index的view的高度. 所以必須另尋他法,

接著使用了getLocationInWindow(location); 
這個方法也行不通,取得的高度也不是所預想的高度
在所有的方法都不可行的情況下,只好先暫緩這個功能的開發.

就在暫停開發的隔天,在逛Github的時候碰巧看到了ItemDecoration的 implements
覺得很有趣所以就稍微點進去看了一下,
不看還好,看了一下就發現這不就是我尋找已久的解法嗎,
就可以取得view的位置.

有了這兩項工具,就可以完成該功能了

最後,附上該 openSource

https://github.com/nightbear1009/GoogleCalendarListView

2014年12月15日 星期一

AngularJS - two way binding

小弟跟Html 以及javascript其實是完全不熟,由於最近公司有提供AngularJS的教程,
小弟從以前就對網頁就有極大的興趣但是一直找不到機會切入這個領域,所以這次就順便去學了AngularJS,在這邊就稍微記錄一些筆記囉!!


今天要講的是Binding的功能,由於以前就寫過windows app 所以對於binding這個功能並不陌生,binding有分為 one-way binding ,two-way binding, one-time binding
one-way binding 和 two-way binding最大的差別就是在於,資料被設定之後是否會被更新到view ,

例如  sample 的輸入框被鍵入文字時,顯示框會同時顯示鍵入的文字,
這個就是two-way binding 的功能

至於 one-time binding 在於,該資料只會被設定一次,之後就不會再被更動.

2014年12月2日 星期二

Android 開發(七十七) Activity Animations

先看一下下面的功能


我相信大部分的人都知道在5.0的時候有新增一個新的activity transaction的功能
讓我們可以在Activity 替換之間有一些動畫,but......what about 5.0以下呢?

今天就是要來說我們如何可以在5.0以下完成這個功能
首先我們可以將這個動作分成兩個部分
1.enter animation
2.exit animation

Enter animation

首先我們先看enter animation ,讓我們將速度放慢再看一次


我相信仔細看之後可以發現,enter animation(粉紅色塊)
其實是從button大小漸漸地放大到整個畫面,

所以我們要做的事情其實很簡單


  • 先將下一個view縮小到跟button一樣大的size
  • 將view恢復到跟原本的view一樣大的size


but 我們是要startActivity耶,這並不是單純的把view 縮小並且恢復正常而已
所以必須要有額外的步驟

1.首先我們必須取消activity原本的transaction功能

            // Override transitions: we don't want the normal window animation in addition
            // to our custom one
            overridePendingTransition(0, 0);


所以我們必須 開啟粉紅色activity之後呼叫上面的程式碼,避免startactivity之後的default animation

2.接著我們必須將下一個activity用成透明的

    <style name="Transparent"  parent="android:Theme.Holo.Light.DarkActionBar">>

        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowBackground">@android:color/transparent</item>
    </style>


3.接著就到了將view縮小到跟button一樣大然後再慢慢恢復的動作了
為了達到這個目的我們必須先取得button的位置以及size

        int[] screenLocation = new int[2];
        view.getLocationOnScreen(screenLocation);
        intent.putExtra("left", screenLocation[0]).
                putExtra("top", screenLocation[1]).
                putExtra("width", view.getWidth()).
                putExtra("height", view.getHeight());


然後再將粉紅色activity的view 轉換到跟button一樣大的size和一樣的起始位置,

        mView.setPivotX(0);
        mView.setPivotY(0);
        mView.setScaleX(mWidthScale);
        mView.setScaleY(mHeightScale);
        mView.setTranslationX(mLeftDelta);
        mView.setTranslationY(mTopDelta);

setPivotX/setPivotY  設定animation的動畫起始點,
setScaleX/setScaleY 將粉紅色的view縮小到跟button一樣大
setTranslationX/setTranslationY 將粉紅色的view移動到跟button一樣的位置
在初始設定完成之後,接著就是要將他恢復到原本的大小

      mView.animate().setDuration(duration).
                scaleX(1).scaleY(1).
                translationX(0).translationY(0).
                setInterpolator(sDecelerator);


這部分就相對簡單許多.
這樣enter animation的部分就完成了
接下來就要談exitAniamtion

Exit animation


exit animation相對於enter animation單純許多,
我們要做的動作就是

1.將粉紅色的view縮小到button的size以及位置並且漸漸的變透明
2.finish activity

所以程式碼如下


        mView.animate().setDuration(duration).
                scaleX(mWidthScale).scaleY(mHeightScale).
                translationX(mLeftDelta).translationY(mTopDelta);

        ObjectAnimator bgAnim = ObjectAnimator.ofFloat(mView, "alpha", 0);
        bgAnim.setDuration(duration);
        bgAnim.start();


這個動作就是將粉紅色的view縮小並位移到button的位置,
接著將activity finish掉即可


最後附上sourceCode

reference可以去參考Chet Haase 的
https://www.youtube.com/watch?v=CPxkoe2MraA
基本上這篇文章是聽完他的youtube再花點時間研究程式碼之後的成果