2016年1月23日 星期六

Android 的 Segmented Control 介面


iOS 有一個好用的 UISegmentedControl;在 Android 下卻沒有。不過,世界這麼大,當然有人開發了 Android 版的 Segmented Control。對於我這個 Android 初哥來說,它的文件有個不明白的地方,就是那個 Style 的東西究竟放在哪?又要用甚麼包著?而且,在預覽中看到的 Tab 的圓角只套用到第一個 Tab,之後的 Tab 都沒有圓角;一直以為欠缺了 Style 的設定,搞了一輪也解決不了。直到在模擬器上執行,才知道根本不用設定。

fragment_browse.xml
<info.hoang8f.android.segmented.SegmentedGroup
    xmlns:segmentedgroup="http://schemas.android.com/apk/res-auto"
    android:id="@+id/browse_segment"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    android:orientation="horizontal"
    segmentedgroup:sc_tint_color="@color/COLOR_SEGMENT_BORDER"
    segmentedgroup:sc_checked_text_color="@color/COLOR_SEGMENT_HIGHLIGHT_TEXT"
    segmentedgroup:sc_border_width="@dimen/SEGMENTCONTROL_BORDER"
    segmentedgroup:sc_corner_radius="@dimen/SEGMENTCONTROL_CORNER">

    <RadioButton
        android:id="@+id/motion_editor"
        android:text="Motion Editor"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        style="@style/RadioButton" />

    <RadioButton
        android:id="@+id/controller"
        android:text="Controller"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        style="@style/RadioButton" />
</info.hoang8f.android.segmented.SegmentedGroup>

2016年1月22日 星期五

759 x TnG x Uber


朋友 Raymond 原本出席昨天的「創業"解難王"」活動,最終由我代他出席。吸引我的是可以認識 759 阿信屋老闆,以及跟久未接觸的行家 Alex Kong 碰過面。

今次活動有很多人參與,但安排得不好,流程及地點都沒有預先安排好,非常即興地在兩個房間走來走去。阿信屋老闆林生沒有準備就上台即場爆肚,實在可以做得更好。不過,還是分享了箇中心得。原來阿信屋最好賣的產品竟然是「米」。至於 Alex 的分享,則帶給我一點衝擊。原來 Alex 在 2012 年時破產,但他不選擇逃避,反而堅持把 HK$2000 萬的債務償還,創立 Sino Dynamic 不斷開發手機應用程式,一點一點把錢賺回來。對我來說,HK$2000 萬是一個足夠退休的金額,大到不知如何去掙。而 Alex 只花了四年時間便把所有債項還清,亦即是平均一年賺了 HK$500 萬。十分利害!最令我印象深刻的是他一句:「在睡覺是也能掙錢」。以前有智者也曾帶出過相同的概念;看書也說過要增加「被動式收入」;上關於創業的堂也教導「簡單的事重複做」。令我重拾起這樣的想法。我相信能依循這個方向,把喜歡的機械人科技融入其中。我想,下半年再次創業時,希望找到實質的方案。

2016年1月21日 星期四

在 Mac OS X 下安裝 cowpatty


在看關於保安的資料時,發現到 cowpatty 這個軟件,於是嘗試在 Mac OS X 安裝。方法如下:
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" < /dev/null 2> /dev/null
brew install openssl
brew link openssl --force
brew install cowpatty

2016年1月20日 星期三

不需要 ActionBar 的 Navigation Drawer 處理。


在惡補 Android 編程的過程中,嘗試製作左邊拉入式選單。有一個很好用的 Navigation Drawer 幫得上忙。可是在網絡上找得到的都範例都用到了 ActionBar,而我是不想使用。找呀找,終於找到了方法。原來只要在 Activity 中取得 Drawer 物件,然後調用 openDrawer(Gravity.LEFT); 顯示選單;調用 closeDrawer(Gravity.LEFT); 隱藏選單就行了。

HomeActivity.java
//------------------------------------------------------------------------------
public void showMenu()  {
 final DrawerLayout drawer = (DrawerLayout)findViewById(R.id.drawerLayout);
 drawer.openDrawer(Gravity.LEFT);
}

//------------------------------------------------------------------------------
public void hideMenu()  {
 final DrawerLayout drawer = (DrawerLayout)findViewById(R.id.drawerLayout);
 drawer.closeDrawer(Gravity.LEFT);
}

layout_home.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawerLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:background="@drawable/background"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <include layout="@layout/layout_header"/>

        <LinearLayout
            android:id="@+id/home_fragment"
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="fill_parent">
        </LinearLayout>
    </LinearLayout>

    <include layout="@layout/fragment_main_menu"/>
</android.support.v4.widget.DrawerLayout>

fragment_main_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mainmenu_container"
    android:layout_gravity="start"
    android:orientation="horizontal"
    android:background="@color/COLOR_MENU_FILTER"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:weightSum="1">

    <!--  Menu area  -->
    <LinearLayout
        android:background="@color/COLOR_MENU_BACKGROUND"
        android:orientation="vertical"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="0.7">

        <!--  Close menu button  -->
        <ImageButton
            android:id="@+id/mainmenu_close_button"
            android:background="@color/COLOR_MENU_TRANSPARENCY"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingTop="@dimen/MAINMENU_MARGIN_TOP"
            android:paddingLeft="@dimen/MAINMENU_MARGIN_LEFT"
            android:paddingRight="@dimen/MAINMENU_MARGIN_RIGHT"
            android:paddingBottom="@dimen/MAINMENU_MARGIN_BOTTOM"
            android:src="@drawable/button_close"/>

        <!--  Option 1:  -->
        <RelativeLayout
            android:id="@+id/mainmenu_01_cell"
            android:orientation="horizontal"
            android:layout_below="@id/mainmenu_close_button"
            android:paddingTop="@dimen/MAINMENU_MARGIN_SPACING"
            android:paddingBottom="@dimen/MAINMENU_MARGIN_SPACING"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <ImageView
                android:id="@+id/mainmenu_01_icon"
                android:layout_centerVertical="true"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/icon_01_on"/>
            <ImageView
                android:id="@+id/mainmenu_01_indicator"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="10dp"
                android:layout_alignParentRight="true"
                android:layout_alignParentEnd="true"
                android:src="@drawable/icon_indicator"
                android:visibility="invisible"
                android:layout_centerVertical="true"/>
            <TextView
                android:id="@+id/mainmenu_01_text"
                android:layout_centerVertical="true"
                android:text="@string/MENUVIEW_OPTION_00"
                android:textColor="@color/COLOR_MENU_TEXT_ON"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_toLeftOf="@id/mainmenu_01_indicator"
                android:layout_toRightOf="@id/mainmenu_01_icon"
                android:textAlignment="textStart"/>
        </RelativeLayout>

        <!--  Option 2  -->
        <RelativeLayout
            android:id="@+id/mainmenu_02_cell"
            android:orientation="horizontal"
            android:layout_below="@id/mainmenu_01_cell"
            android:paddingTop="@dimen/MAINMENU_MARGIN_SPACING"
            android:paddingBottom="@dimen/MAINMENU_MARGIN_SPACING"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <ImageView
                android:id="@+id/mainmenu_02_icon"
                android:layout_centerVertical="true"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/icon_02_on"/>
            <ImageView
                android:id="@+id/mainmenu_02_indicator"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="10dp"
                android:layout_alignParentRight="true"
                android:layout_alignParentEnd="true"
                android:src="@drawable/icon_indicator"
                android:visibility="invisible"
                android:layout_centerVertical="true"/>
            <TextView
                android:id="@+id/mainmenu_02_text"
                android:layout_centerVertical="true"
                android:text="@string/MENUVIEW_OPTION_01"
                android:textColor="@color/COLOR_MENU_TEXT_ON"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_toLeftOf="@id/mainmenu_02_indicator"
                android:layout_toRightOf="@id/mainmenu_02_icon"
                android:textAlignment="textStart"/>
        </RelativeLayout>

        <!--  Option 3  -->
        <RelativeLayout
            android:id="@+id/mainmenu_03_cell"
            android:orientation="horizontal"
            android:layout_below="@id/mainmenu_02_cell"
            android:paddingTop="@dimen/MAINMENU_MARGIN_SPACING"
            android:paddingBottom="@dimen/MAINMENU_MARGIN_SPACING"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <ImageView
                android:id="@+id/mainmenu_03_icon"
                android:layout_centerVertical="true"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/icon_03_on"/>
            <ImageView
                android:id="@+id/mainmenu_03_indicator"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="10dp"
                android:layout_alignParentRight="true"
                android:layout_alignParentEnd="true"
                android:src="@drawable/icon_indicator"
                android:visibility="invisible"
                android:layout_centerVertical="true"/>
            <TextView
                android:id="@+id/mainmenu_03_text"
                android:layout_centerVertical="true"
                android:text="@string/MENUVIEW_OPTION_02"
                android:textColor="@color/COLOR_MENU_TEXT_ON"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_toLeftOf="@id/mainmenu_03_indicator"
                android:layout_toRightOf="@id/mainmenu_03_icon"
                android:textAlignment="textStart"/>
        </RelativeLayout>

        <!--  Option 4  -->
        <RelativeLayout
            android:id="@+id/mainmenu_04_cell"
            android:orientation="horizontal"
            android:layout_below="@id/mainmenu_03_cell"
            android:paddingTop="@dimen/MAINMENU_MARGIN_SPACING"
            android:paddingBottom="@dimen/MAINMENU_MARGIN_SPACING"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <ImageView
                android:id="@+id/mainmenu_04_icon"
                android:layout_centerVertical="true"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/icon_04_on"/>
            <ImageView
                android:id="@+id/mainmenu_04_indicator"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="10dp"
                android:layout_alignParentRight="true"
                android:layout_alignParentEnd="true"
                android:src="@drawable/icon_indicator"
                android:visibility="invisible"
                android:layout_centerVertical="true"/>
            <TextView
                android:id="@+id/mainmenu_04_text"
                android:layout_centerVertical="true"
                android:text="@string/MENUVIEW_OPTION_03"
                android:textColor="@color/COLOR_MENU_TEXT_ON"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_toLeftOf="@id/mainmenu_04_indicator"
                android:layout_toRightOf="@id/mainmenu_04_icon"
                android:textAlignment="textStart"/>
        </RelativeLayout>

        <!--  Footer  -->
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <TextView
                android:id="@+id/mainmenu_version_code"
                android:text="@string/MENUVIEW_VERSION"
                android:textColor="@color/COLOR_MENU_TEXT_OFF"
                android:textAlignment="textEnd"
                android:textSize="12dp"
                android:layout_alignParentRight="true"
                android:layout_alignParentBottom="true"
                android:layout_marginRight="@dimen/MAINMENU_MARGIN_RIGHT"
                android:layout_marginBottom="@dimen/MAINMENU_MARGIN_BOTTOM"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
            </TextView>

            <TextView
                android:id="@+id/mainmenu_copyright"
                android:text="@string/MENUVIEW_COPYRIGHT"
                android:textColor="@color/COLOR_MENU_TEXT_OFF"
                android:textSize="12dp"
                android:layout_alignParentBottom="true"
                android:layout_marginLeft="@dimen/MAINMENU_MARGIN_LEFT"
                android:layout_marginBottom="@dimen/MAINMENU_MARGIN_BOTTOM"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
            </TextView>

            <View
                android:id="@+id/mainmenu_line"
                android:background="@color/COLOR_MENU_TEXT_OFF"
                android:layout_above="@id/mainmenu_copyright"
                android:layout_marginLeft="@dimen/MAINMENU_MARGIN_LEFT"
                android:layout_marginRight="@dimen/MAINMENU_MARGIN_RIGHT"
                android:layout_marginBottom="@dimen/MAINMENU_MARGIN_BOTTOM"
                android:layout_width="match_parent"
                android:layout_height="1dp"/>

            <TextView
                android:id="@+id/mainmenu_terms"
                android:text="@string/MENUVIEW_TERMS"
                android:textColor="@color/COLOR_MENU_TEXT_OFF"
                android:paddingTop="@dimen/MAINMENU_MARGIN_TOP"
                android:paddingLeft="@dimen/MAINMENU_MARGIN_LEFT"
                android:paddingBottom="@dimen/MAINMENU_MARGIN_BOTTOM"
                android:layout_above="@id/mainmenu_line"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
            </TextView>
        </RelativeLayout>

    </LinearLayout>
</LinearLayout>

2016年1月14日 星期四

TIPS 實戰編 #7 初創企業的會計常識


TIPS 實戰編因為聖誕及元旦而暫停了數星期,今晚再次繼續第七課實戰編。咦!?第六課去了哪?暫定調到月底...。

今次請來澤匯會計師樓創辦人 Constant Mo 為大家解決會計上的問題。Constant 沒有準備 Powerpoint,取而代之是跟每組逐一解答切身的疑難。像我問的是 Mobile App 以佣金方式支付,究竟是否需要報香港的稅。曾經問過會計師朋友,他以 TVB 劇集賣到新加坡作為例子,說明以佣金方式的交易是以交易地點作為準則,所以除非香港用戶購買 Mobile App 或 In-app Purchase,持有人才需要報香港的稅。但 Constant 的說法較為簡單,就是用哪個地方的商業登記就需繳付當地的稅。問題來了,兩個說法,哪個才是正確?我沒有深究,反正收入不多,報了無壞。

在場遇上了書法家:文龍。他還熱情地為大家送上親筆簽名的卡片,十分有心思。

2016年1月10日 星期日

滑板車加底燈


有一次帶女兒到公園玩耍,她踏著滑板車愉快地奔馳。冬季天黑得特別快,路很快也看不清。她問我能否裝裝車頭燈到滑板車,我說:「當然可以!還可以加底燈」。她用懷疑的目光對我說:「可以的嗎?」。

今天不想工作,於是計劃滑板車改裝的步驟。家中有顆長條形的鋰電池,量一量尺寸,剛好放得下滑板車底部的凹槽;鋰電池輸出 5V,跟平時看到的 12V LED 燈帶有著不同電壓,於是在網上找找看有沒有 5V 版本。確定有 5V 後,到深水埗黃金中心購買零件。找到 HK$79 兩條 LED 燈帶,可惜只有白燈;試過能用「尿袋」點著 LED 後便買了下來。回家後,量好尺寸及走線方法,把 LED 燈帶貼好,再利用溶膠槍固定 USB 線及鋰電池。工序十分簡單。

把燈點著,較果不錯!女兒也很喜歡。

2016年1月7日 星期四

天下無不散之筵席


2016.01.07 是一個難忘的日子。有緣再會。

2016年1月6日 星期三

Not-Bag 在《壹週 Plus》的報導


2015 年 12 月 1 日,《壹週 Plus》來到 BeyondZ 辦公室對 Not-Bag 進行採訪。今天,報導刊登了:
http://nextplus.nextmedia.com/news/latest/20160106/329280

報導說「...幾位八十後...」,朋友指我扮細。其實今次報導我參與的不多,記者沒有問過我的年齡,應該是聯想到大家跟被訪者年紀相約而已。將於二月份在 RTHK 31 台播放的紀錄片,如果沒被剪掉的話,當中是有誠實的自我介紹呢!

2016年1月5日 星期二

臨老學 Android Java


同事們離職,需要接收最近的項目,當中少不免有 Android 客戶端。一直都提不起勁去學習,今次沒法逃避。還好,有不明白的地方可以立即向同事請教,吸收力比自學快很多。

透過閱讀及理解同事的代碼,是其中一個方法;然而,我通常會想像出一個應用的介面,從參考中抓取合適的部份,然後套用到項目中。這是融匯貫通的方法。學到了把一個 XML 嵌入另一個 XML,得實現一下。還有好用的 Fragment,也嘗試了更換 Fragment 的測試。用起上來也很簡單。不難學,但很容易出錯。
@Override
protected void onResume()  {
  super.onResume();

  //----------------------------------------------------------------------------------------
  // Set header font
  TextView textView = (TextView)findViewById(R.id.header_title);
  _headerTitleView = textView;

  if (textView != null)  {
    AssetManager manager = getAssets();
    if (manager != null)  {
      try  {
        // createFromAsset will throw exception if font file not found
        Typeface font = Typeface.createFromAsset(manager, "fonts/Arapey-Italic.ttf");
        if (font != null)  {
          textView.setTypeface(font);
        }
      } catch (Exception e)  {
        Log.d("RootActivity", "### Typeface.createFromAsset error...");
      }
    }
  }

  //----------------------------------------------------------------------------------------
  // Set header title
  if (textView != null)  {
    textView.setText("Hello");
  }

  //----------------------------------------------------------------------------------------
  // Add listener to button
  ImageButton button = null;

  button = (ImageButton)findViewById(R.id.header_left_button_01);
  if (button != null)  {button.setOnClickListener(_onClickListener);}

  button = (ImageButton)findViewById(R.id.header_left_button_02);
  if (button != null)  {button.setOnClickListener(_onClickListener);}

  //----------------------------------------------------------------------------------------
  // Replace fragment
  WelcomeFragment fragment = new WelcomeFragment();
  changeFragment(fragment);

  //----------------------------------------------------------------------------------------
  // View.INVISIBLE = Allocated the space but just invisible
  // View.GONE = Without allocate the space and invisible
  RelativeLayout layout = (RelativeLayout)findViewById(R.id.header_container);
  layout.setVisibility(View.GONE);
}

2016年1月3日 星期日

《簡單思考》讀後感


聖誕前夕,友人一家跟隨丈夫到台灣出差;她是個愛閱讀之人,於是托她購買了四本書。省了運費便宜很多。

昨天假期,我們兩家人碰過面,順便領取圖書。四本書之中,《簡單思考》最簿、出版最新、每頁的文字最少,相信很快能看完,於是挑了這本書來讀。花了兩天時間,已經看畢。作者嘗試把事情簡單化,到了基本上自生自滅的情況。我認為在一般情況下很難實現。如果書中內容是真的話,只覺得作者是僥倖。不過,化煩為簡及提供用戶價值,還是值得參考。看了可提醒自己已知的事,不看也沒損失。