2017年11月22日 星期三

Notification icon flash on status bar

Problem:


當需要在短時間內持續更新notification的內容時
在建立Notification時,記得使用同一個Notification Builder物件,並且設定 setOnlyAlertOnce(true)
以免SystemUI一直在update notification,造成status bar UI一直在跳動

Code snippet:


return new Notification.Builder(context, NOTIFICATION_CHANNEL_ID)
            mBuilder
                        .setContentTitle(title)
                        .setContentText(contentText)
                        .setContentIntent(contentIntent)
                        .setSmallIcon(R.drawable.noti_icon)
                        .setLargeIcon(appIcon)
                        .setSubText(appLabel)
                        .setColor(color)
                        .setOnlyAlertOnce(true)
                        .addAction(stopAction)
                        //.addAction(optionsAction)

                        .build();

2017年9月22日 星期五

Change ActionBar text color

Reference:

Code sinppet:
AppCompactActivity
<style name="AppBaseTheme" parent="@style/Theme.AppCompat.Light.DarkActionBar">
    <item name="actionBarStyle">@style/MyActionBar</item>
</style>

<style name="MyActionBar" parent="@style/Widget.AppCompat.ActionBar.Solid">
    <item name="titleTextStyle">@style/MyTitleTextStyle</item>
</style>

<style name="MyTitleTextStyle" parent="@style/TextAppearance.AppCompat.Widget.ActionBar.Title">
    <item name="android:textColor">CHANGE_COLOR_HERE</item>
</style>


Settings Activity
<style name="AppTheme" parent="@android:style/Theme.DeviceDefault.Settings">
        <item name="android:colorAccent">@color/your_color</item>
</style>

2017年8月25日 星期五

How to disable scrolling on ViewPager

Reference:

https://stackoverflow.com/questions/7814017/is-it-possible-to-disable-scrolling-on-a-viewpager

Code snippet:

1. Create a new CustomViewPager class
public class CustomViewPager extends ViewPager {

    private boolean isPagingEnabled = true;

    public CustomViewPager(Context context) {
        super(context);
    }

    public CustomViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return this.isPagingEnabled && super.onTouchEvent(event);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return this.isPagingEnabled && super.onInterceptTouchEvent(event);
    }

    public void setPagingEnabled(boolean b) {
        this.isPagingEnabled = b;
    }
}

2. Replace the <com.android.support.V4.ViewPager> tag with <your_package_name.CustomViewPager > tag in layout.xml

3. Call setPagingEnabled(true) when you want to disable Scrolling and call setPagingEnabled(false) to enable it.

How to disable click event on TabLayout

Reference:

https://stackoverflow.com/questions/37809538/how-can-i-disable-click-on-tablayout-in-android

Code snippet:

mTabLayout = (TabLayout) findViewById(R.id.tab_layout);

LinearLayout tabStrip = (LinearLayout) mTabLayout.getChildAt(0);
for(int i = 0; i < tabStrip.getChildCount(); i++) {
    tabStrip.getChildAt(i).setOnTouchListener(new View.OnTouchListener() {
        @Override        public boolean onTouch(View v, MotionEvent event) {
            return true;
        }
    });
}

2017年7月24日 星期一

Rename a directory in a Git repository

Reference:

https://stackoverflow.com/questions/11183788/in-a-git-repository-how-to-properly-rename-a-directory

Command:

git mv <old name> <new name>

Example:
Rename the directory from source to target

git mv source tmp
git mv tmp target

2017年7月20日 星期四

How to check if system is 12 or 24 hour time format

Reference:

https://stackoverflow.com/questions/4392636/how-do-i-check-if-system-is-12-or-24-hour
https://stackoverflow.com/questions/23222199/12-24-hour-mode-conflict
https://stackoverflow.com/questions/8834452/androidchanging-time-format-as-per-the-devices-current-time-format

Code snippet:

private boolean mIs24HourFormat = false;
private TextView mTime;

MainActivity.java
@Overrideprotected void onCreate(Bundle savedInstanceState) {
    ......
    mIs24HourFormat = android.text.format.DateFormat.is24HourFormat(mContext);
    ....
    mTime.setText(getTime());
}

private String getTime() {
    DateFormat df =
null;
   
if(mIs24HourFormat){
        df =
new SimpleDateFormat(mContext.getResources().getString(R.string.time_format_24hr), Locale.getDefault());
    }
else{
        df =
new SimpleDateFormat(mContext.getResources().getString(R.string.time_format_12hr), Locale.getDefault());
    }
   
return df.format(Calendar.getInstance().getTime());
}


strings.xml
<string name="time_format_24hr" translatable="false">HH\uee01mm</string>
<
string name="time_format_12hr" translatable="false">h\uee01mm</string>



Note:

If you want to show the time format followed by system, you can use android widget TextClock.

2017年6月7日 星期三

Crash when set TYPE_DISPLAY_OVERLAY type by inflection

Error:
android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@71dc214 -- permission denied for window type 2026

Solution:
TYPE_DISPLAY_OVERLAY需要
android.Manifest.permission.INTERNAL_SYSTEM_WINDOW

AndroidManifest.xml
<permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" android:protectionLevel="signature" />

app要 sign platform key才可使用


Call stack:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.hueijheyu.reflectiondemo/com.example.hueijheyu.reflectiondemo.MainActivity}: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@71dc214 -- permission denied for window type 2026
                                                       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
                                                       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
                                                       at android.app.ActivityThread.-wrap12(ActivityThread.java)
                                                       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
                                                       at android.os.Handler.dispatchMessage(Handler.java:102)
                                                       at android.os.Looper.loop(Looper.java:154)
                                                       at android.app.ActivityThread.main(ActivityThread.java:6119)
                                                       at java.lang.reflect.Method.invoke(Native Method)
                                                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
                                                    Caused by: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@71dc214 -- permission denied for window type 2026
                                                       at android.view.ViewRootImpl.setView(ViewRootImpl.java:703)
                                                       at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:342)
                                                       at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:94)
                                                       at android.app.Dialog.show(Dialog.java:322)
                                                       at com.example.hueijheyu.reflectiondemo.MainActivity.onCreate(MainActivity.java:39)
                                                       at android.app.Activity.performCreate(Activity.java:6723)
                                                       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
                                                       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
                                                       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
                                                       at android.app.ActivityThread.-wrap12(ActivityThread.java)
                                                       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
                                                       at android.os.Handler.dispatchMessage(Handler.java:102)
                                                       at android.os.Looper.loop(Looper.java:154)
                                                       at android.app.ActivityThread.main(ActivityThread.java:6119)
                                                       at java.lang.reflect.Method.invoke(Native Method)
                                                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)