2017年1月16日 星期一

Using phpMyAdmin and restrict root account login location

目的:

  • allowing all local users access
  • restricting root to local system access
  • restricting root to local network access

方法:

開啟C:\xampp\phpMyAdmin\config.inc.php,填入下方規則


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// disable root access to phpmyadmin
//$cfg['Servers'][$i]['AllowRoot'] = false;

// setting root only access from localhost
$cfg['Servers'][$i]['AllowDeny']['order'] = 'deny,allow';
$cfg['Servers'][$i]['AllowDeny']['rules'] = array(
 // deny everyone by default
 //'deny % from all',
 'deny root from all',

 // allow all users from the local system
 'allow % from localhost',
 'allow % from 127.0.0.1',
 'allow % from ::1',

 // allow all users from the server IP (commented out)
 // 'allow % from SERVER_ADDRESS',

 // allow user root from local system
 'allow root from localhost',
 'allow root from 127.0.0.1',
 'allow root from ::1',
 
 // allow user root from local network
 'allow root from 10.0.0.0/8',
 'allow root from 172.16.0.0/12',
 'allow root from 192.168.0.0/16',
 'allow root from fe80::/10', // IPv6 Link-local Addresses
 'allow root from fc00::/7' // IPv6 Unique Local Addresses

 // add more usernames and their IP (or IP ranges) here - 
    );


reference:
https://docs.phpmyadmin.net/en/latest/config.html#cfg_Servers_AllowDeny_rules
http://www.devside.net/guides/windows/phpmyadmin

2016年4月30日 星期六

Read text from raw file

目的

從android raw中取出文字資料

方法

使用org.apache.commons.io中的IOUtils功能

** org.apache.commons.io.Charsets.UTF_8 已經 deprecated
** 可以改用 java.nio.charset.StandardCharsets.UTF_8 ,但至少要 API 19


java

1
2
3
InputStream is = cxt.getResources().openRawResource(R.raw.car_type_list);
String content = IOUtils.toString(is, Charsets.UTF_8);
IOUtils.closeQuietly(is); // don't forget to close your streams


gradle

1
2
3
dependencies {
    compile 'commons-io:commons-io:2.5'
}


reference:
http://stackoverflow.com/a/13566950

http://mvnrepository.com/artifact/commons-io/commons-io

2016年4月21日 星期四

使用android:Theme.Holo.Dialog設定最小寬度

目的

使用 DialogFragment 添加 AlertDialog,並自訂內容畫面設計,直接設定最小畫面寬度

方法

PhotoDialogFragment.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class PhotoListDialogFragment extends DialogFragment {

    private String img;

    public PhotoListDialogFragment(String img) {
        this.img = img;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Use the Builder class for convenient dialog construction

        View content = LayoutInflater.from(getContext()).inflate(R.layout.photo_list_dialog_content, null, false);
        TextView iv = (TextView) content.findViewById(R.id.photoListDialogIV);
        iv.setText(img);

        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.DialogStyle);
        builder.setView(content)
                .setPositiveButton(R.string.dialog_ok, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        // FIRE ZE MISSILES!
                    }
                });
        // Create the AlertDialog object and return it

        return builder.create();
    }
}

style.xml

1
2
3
4
5
6
<resources>
    <style name="DialogStyle" parent="android:Theme.Holo.Dialog">
        <item name="android:windowMinWidthMajor">90%</item>
        <item name="android:windowMinWidthMinor">90%</item>
    </style>
</resources>




reference:
http://stackoverflow.com/a/28519059

2016年2月13日 星期六

Swift Class, Structure, Function

Some difference between classes and structs

ClassStructure
inheritanceO
passed by valueO
passed by referenceO
createclass CRectangle {
    var width = 200
}
struct SRectangle {
    var width = 200
}
constructvar cRet = CRectangle()
// class 不能直接用 CRectangle(width:300) 必需要定義一個 constructor
cRect.width // 為 200
var sRect = SRectangle(width:300)
sRect.width //  為 300
memoryvar cRect = CRectangle()
var cRect2 = cRect // copy reference

cRect2.width // 目前值是 200
cRect2.width = 500
cRect.width // cRect.width 也改變成了 500
var sRect = SRectangle()
var sRect2 = sRect // copy memory

sRect2.width // 目前值是 200
sRect2.width = 500
sRect.width // 不受 sRect2 影響還是 200
immutablelet cRect = CRectangle()
cRect.width = 500 
let sRect = SRectangle()
sRect.width = 500 // 會造成錯誤
mutating functionextension CRectangle {
    func changeWidth(width:Int){
        self.width = width
    }
}
extension SRectangle {
    mutating func changeWidth(width:Int){
        self.width = width
    }
}

Structures and Enumerations Are Value Types

A value type is a type whose value is copied when it is assigned to a variable or constant, or when it is passed to a function.

You’ve actually been using value types extensively throughout the previous chapters. In fact, all of the basic types in Swift—integers, floating-point numbers, Booleans, strings, arrays and dictionaries—are value types, and are implemented as structures behind the scenes.

All structures and enumerations are value types in Swift. This means that any structure and enumeration instances you create—and any value types they have as properties—are always copied when they are passed around in your code.

Assignment and Copy Behavior for Strings, Arrays, and Dictionaries

In Swift, many basic data types such as String, Array, and Dictionary are implemented as structures. This means that data such as strings, arrays, and dictionaries are copied when they are assigned to a new constant or variable, or when they are passed to a function or method.

This behavior is different from Foundation: NSString, NSArray, and NSDictionary are implemented as classes, not structures. Strings, arrays, and dictionaries in Foundation are always assigned and passed around as a reference to an existing instance, rather than as a copy.

Constant and Variable Parameters

Function parameters are constants by default. Trying to change the value of a function parameter from within the body of that function results in a compile-time error. This means that you can’t change the value of a parameter by mistake.

However, sometimes it is useful for a function to have a variable copy of a parameter’s value to work with. You can avoid defining a new variable yourself within the function by specifying one or more parameters as variable parameters instead. Variable parameters are available as variables rather than as constants, and give a new modifiable copy of the parameter’s value for your function to work with.

Define variable parameters by prefixing the parameter name with the var keyword:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
func alignRight(var string: String, totalLength: Int, pad: Character) -> String {
    let amountToPad = totalLength - string.characters.count
    if amountToPad < 1 {
        return string
    }
    let padString = String(pad)
    for _ in 1...amountToPad {
        string = padString + string
    }
    return string
}
let originalString = "hello"
let paddedString = alignRight(originalString, totalLength: 10, pad: "-")
// paddedString is equal to "-----hello"
// originalString is still equal to "hello"


In-Out Parameters

Variable parameters, as described above, can only be changed within the function itself. If you want a function to modify a parameter’s value, and you want those changes to persist after the function call has ended, define that parameter as an in-out parameter instead.




 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
func swapTwoInts(inout a: Int, inout _ b: Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}

var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// prints "someInt is now 107, and anotherInt is now 3"



reference:
http://iosdevelopersnote.blogspot.tw/2014/12/swift-struct-class.html
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html#//apple_ref/doc/uid/TP40014097-CH13-ID88
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html#//apple_ref/doc/uid/TP40014097-CH13-ID93
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Functions.html#//apple_ref/doc/uid/TP40014097-CH10-ID172
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Functions.html#//apple_ref/doc/uid/TP40014097-CH10-ID173

2016年2月12日 星期五

Compiler error: Method with Objective-C selector conflicts with previous declaration with the same Objective-C selector

使用相同函式,不同方法,會造成error

error code:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import UIKit

import UIKit

class ViewController: UIViewController
{
    func perform(operation: (Double) -> Double) {
    }

    func perform(operation: (Double, Double) -> Double) {
    }
}


complier error:
1
Method 'performOperation' with Objective-C selector 'performOperation:' conflicts with previous declaration with the same Objective-C selector


解決函式重載問題


加入@nonobjc即可

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import UIKit

import UIKit

class ViewController: UIViewController
{
    func perform(operation: (Double) -> Double) {
    }

    @nonobjc
    func perform(operation: (Double, Double) -> Double) {
    }
}


Using Swift with Cocoa and Objective-C (Swift 2.1)





reference:

2016年1月14日 星期四

ListView中使用多種版面

問題

ListView中使用多種版面時,需要使用getItemViewType()以及getViewTypeCount()

getItemViewType():default 0,用來判斷需要使用哪種版面

getViewTypeCount():default 1,有幾種版面

**getItemViewType() 必須 小於 getViewTypeCount() **


若 getItemViewType() >= getViewTypeCount(),將會發生 ArrayIndexOutOfBoundsException!!!

2016年1月3日 星期日

Android GCM permission GET_ACCOUNTS

On Android devices, GCM uses an existing connection for Google services. For pre-3.0 devices, this requires users to set up their Google accounts on their mobile devices. A Google account is not a requirement on devices running Android 4.0.4 or higher.

reference:

http://stackoverflow.com/a/18444343

https://developers.google.com/cloud-messaging/android/client

2016年1月1日 星期五

android 6.0 permission check

問題:

在android 6.0(Marshmallow)開始添加了權限控管的功能,用戶可以隨心所欲的在設定中,將APP的權限進行「允許」或「拒絕」,因此在功能使用之前,都必須檢查該功能是否處於「允許」的狀態下

步驟:

  1. 在 AndroidManifest.xml中必須添加該權限的聲明
    1
    <uses-permission android:name="android.permission.CAMERA" />
    
  2. 當該裝置的版本為android 6.0後續的版本才需要進行後續權限的處理
    1
    2
    3
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)  {
    //...進行權限檢查的後續處理
    }
    
  3. 使用檢查「checkSelfPermission()」進行檢查是否擁有該權限,若權限處於「拒絕」狀態(有可能第一次安裝後),則必須先進行允許權限的步驟
    1
    2
    3
    4
    5
    6
    7
    // Check if the Camera permission is already available.
    if ( ActivityCompat.checkSelfPermission( this, Manifest.permission.CAMERA ) == PackageManager.PERMISSION_GRANTED ) {
        // already available
    } else {
        // asking whether to allow permission...
        requestCameraPermission() ;
    }
    
  4. 當權限處於「拒絕」狀態,此時會使用到「shouldShowRequestPermissionRationale()」和「requestPermissions()」
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    /**
     * Requests the Camera permission.
     * If the permission has been denied previously, a SnackBar will prompt the user to grant the
     * permission, otherwise it is requested directly.
     */
    private void requestCameraPermission() {
        Log.i( TAG, "CAMERA permission has NOT been granted. Requesting permission." ) ;
    
        /**
         * shouldShowRequestPermissionRationale 回傳的規則如下:
         * 1.true:用戶在先前權限詢問的選項中,選擇了「拒絕」,但沒有勾選「不再詢問」
         * 2.false:第一次安裝APP後進入該功能
         * 3.false:用戶在先前權限詢問選項中,選擇了「允許」
         * 4.false:用戶在先前權限詢問的選項中,選擇了「拒絕」,但勾選「不再詢問」
         * 5.false:用戶在「設定」裡頭選擇「允許或拒絕」
         * 
         * 呼叫requestPermissions後,是否會跳出詢問視窗,規則如下:
         * 1.不會:用戶在先前權限詢問選項中,選擇了「允許」
         * 2.不會:用戶在先前權限詢問的選項中,選擇了「拒絕」,但勾選「不再詢問」,在後續onRequestPermissionsResult當中一律回傳PERMISSION_DENIED
         * 3.會:第一次安裝APP後進入該功能(第一次跳出不會有「不再詢問」的選項可以勾選)
         * 4.會:用戶在先前權限詢問的選項中,選擇了「拒絕」
         * 5.會:用戶在「設定」裡頭選擇「允許或拒絕」
         * 
         * 當呼叫requestPermissions後,不管用戶選擇允許或拒絕,又或者沒有跳出詢問視窗,後續都會進入onRequestPermissionsResult執行後續動作,規則如下:
         * 1.PERMISSION_GRANTED(允許):用戶選擇「允許」選項、設定中直接選擇「允許」
         * 2.PERMISSION_DENIED(拒絕):用戶選擇「拒絕」選項、設定中直接選擇「拒絕」
         */
        if ( ActivityCompat.shouldShowRequestPermissionRationale( this, Manifest.permission.CAMERA ) ) {
            // Provide an additional rationale to the user if the permission was not granted
            // and the user would benefit from additional context for the use of the permission.
            // For example if the user has previously denied the permission.
            Log.i( TAG, "Displaying camera permission rationale to provide additional context." ) ;
            
            // 「R.string.permission_camera_rationale」的內容可以多加一些說明提醒使用戶該功能必須允許該權限才可以使用
            Snackbar.make( mLayout, R.string.permission_camera_rationale, Snackbar.LENGTH_INDEFINITE ).setAction( R.string.ok, new View.OnClickListener() {
                @Override
                public void onClick( View view ) {
                    ActivityCompat.requestPermissions( MainActivity.this, new String[] { Manifest.permission.CAMERA }, REQUEST_CAMERA ) ;
                }
            } ).show() ;
        } else {
            // Camera permission has not been granted yet. Request it directly.
            ActivityCompat.requestPermissions( this, new String[] { Manifest.permission.CAMERA }, REQUEST_CAMERA ) ;
        }
    }
    
  5. 呼叫requestPermissions後,後續會有Callback繼續處理
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    /**
     * Callback received when a permissions request has been completed.
     */
    @Override
    public void onRequestPermissionsResult( int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults ) {
        if ( requestCode == REQUEST_CAMERA ) {
            // Received permission result for camera permission.
            Log.i( TAG, "Received response for Camera permission request." ) ;
    
            // Check if the only required permission has been granted
            if ( grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED ) {
                // Camera permission has been granted, preview can be displayed
                Log.i( TAG, "CAMERA permission has now been granted. Showing preview." ) ;
                Snackbar.make( mLayout, R.string.permision_available_camera, Snackbar.LENGTH_SHORT ).show() ;
            } else {
                Log.i( TAG, "CAMERA permission was NOT granted." ) ;
                Snackbar.make( mLayout, R.string.permissions_not_granted, Snackbar.LENGTH_SHORT ).show() ;
            }
        }
        // other callback
        else {
            super.onRequestPermissionsResult( requestCode, permissions, grantResults ) ;
        }
    }
    

reference:


android 6.0 remove apache lib solved method

當使用android 6.0進行專案撰寫,6.0版本移除了apache的功能

官網說明如下:
https://developer.android.com/intl/zh-tw/about/versions/marshmallow/android-6.0-changes.html#behavior-apache-http-client

eclipse project solved method

從SDK/platforms/android-23/optional裡頭的org.apache.http.legacy.jar複製到專案的lib資料夾

reference:
http://stackoverflow.com/a/32066606

解決的Eclipse更新ADT插件時遇到的Eclipse reports rendering library more recent than ADT plug-in問題


參照此文章更新ADT
http://wangcuijing.blog.51cto.com/7233352/1320155

2015年10月23日 星期五

Android / JavaScript color setting

目的:

使用色碼進行設定物件顏色

色碼產生:

http://www.color-hex.com/

添加透明度:

http://stackoverflow.com/a/25170174

Going off the answer from @BlondeFurious, here is some Java code to get each hex value from 100% to 0% alpha:

java code:

1
2
3
4
5
6
7
8
for (double i = 1; i >= 0; i -= 0.01) {
    i = Math.round(i * 100) / 100.0d;
    int alpha = (int) Math.round(i * 255);
    String hex = Integer.toHexString(alpha).toUpperCase();
    if (hex.length() == 1) hex = "0" + hex;
    int percent = (int) (i * 100);
    System.out.println(String.format("%d%% — %s", percent, hex));
}


output:

100% — FF
99% — FC
98% — FA
97% — F7
96% — F5
95% — F2
94% — F0
93% — ED
92% — EB
91% — E8
90% — E6
89% — E3
88% — E0
87% — DE
86% — DB
85% — D9
84% — D6
83% — D4
82% — D1
81% — CF
80% — CC
79% — C9
78% — C7
77% — C4
76% — C2
75% — BF
74% — BD
73% — BA
72% — B8
71% — B5
70% — B3
69% — B0
68% — AD
67% — AB
66% — A8
65% — A6
64% — A3
63% — A1
62% — 9E
61% — 9C
60% — 99
59% — 96
58% — 94
57% — 91
56% — 8F
55% — 8C
54% — 8A
53% — 87
52% — 85
51% — 82
50% — 80
49% — 7D
48% — 7A
47% — 78
46% — 75
45% — 73
44% — 70
43% — 6E
42% — 6B
41% — 69
40% — 66
39% — 63
38% — 61
37% — 5E
36% — 5C
35% — 59
34% — 57
33% — 54
32% — 52
31% — 4F
30% — 4D
29% — 4A
28% — 47
27% — 45
26% — 42
25% — 40
24% — 3D
23% — 3B
22% — 38
21% — 36
20% — 33
19% — 30
18% — 2E
17% — 2B
16% — 29
15% — 26
14% — 24
13% — 21
12% — 1F
11% — 1C
10% — 1A
9% — 17
8% — 14
7% — 12
6% — 0F
5% — 0D
4% — 0A
3% — 08
2% — 05
1% — 03
0% — 00



2015年10月14日 星期三

ListView滑動更換圖片

目的:

減少ListView上下滑動更換圖片時產生的Lag

操作:

在Main.java使用setOnScrollListener()偵測ListView是否滑動,若處於靜止的狀態時,就開始更換item上的圖片
**只要ListView初始化完成後,使用者開始滑動,一切更換圖片的code皆在setOnScrollListener()中的onScrollStateChange()中進行處理**

Main.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
MyAdapter adapter = null ;

ListView lv = new ListView(this) ;
lv.setAdapter(adapter = new MyAdapter()) ;

lv.setOnScrollListener( new OnScrollListener() {
                                        @Override
                                        public void onScrollStateChanged( AbsListView listview, int scrollState ) {
                                            // TODO Auto-generated method stub
                                            switch ( scrollState ) {
                                                case OnScrollListener.SCROLL_STATE_IDLE:
                                                    MyAdapter.scrolling = false ;

                                                    int first = listview.getFirstVisiblePosition() ;
                                                    int childCnt = listview.getChildCount() ; // listview可用的view總數
                                                    int listDataSize = lvAdapter.getListDataSize() ;
                                                    for ( int i = 0 ; i < childCnt ; ++i ) {
                                                        View convertView = listview.getChildAt( i ) ; // 取出目前需處理的item

                                                        // 取出ViewHolder後可以進行而外處理
                                                        MyAdapter.ViewHolder holder = (MyAdapter.ViewHolder) convertView.getTag() ;

                                                        convertView.setTag( R.image.used, "自訂此圖的記號" ) ;

                                                        //...更新item上的圖片
                                                    }
                                                    break ;
                                                default:
                                                    MyAdapter.scrolling = true ;
                                                    //...可以取消下載的進程
                                                    break ;
                                            }
                                        }

                                        @Override
                                        public void onScroll( AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount ) {
                                            // TODO Auto-generated method stub
                                        }
                                    } ) ;


在MyAdapter的getView()中處理當前使用item的圖片,是否與前一張圖是否相同,若相同就不處理,若不相同則代表需要更換新圖片在此item中
**畫面上起初所看到的幾張圖片在此處理並顯示,後續上下滑動事件時所更換圖片的code由ListView的setOnScrollListener()處理**

MyAdapter.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public static boolean scrolling = false ;

@Override
public View getView( int position, View convertView, ViewGroup parent ) {
    // TODO Auto-generated method stub
    ViewHolder holder = null ;

    if ( convertView == null ) {
        //...
        convertView.setTag( holder ) ;
    } else {
        holder = (ViewHolder) convertView.getTag() ;
    }

    if ( !scrolling ) {
        //...畫面上起初所看到的幾張圖片在此處理並顯示

        // 記錄此item目前被誰所用
        convertView.setTag( R.image.used, "自訂此圖的記號" ) ;
    } else {
        String nowTag = "自訂此圖的記號" ;
        String preTag = String.valueOf( convertView.getTag( R.image.used ) ) ;

        // preTag未產生過則為null,或者有手動清除過
        // item目前使用的圖跟前一張圖是否相同,若相同則代表此圖未滑出螢幕範圍
        if ( preTag != null && !nowTag.equals( preTag ) ) {
            convertView.setTag( R.image.used, null ) ; // 清除此圖的記號
            //...清除此圖,為了下次此item滑到螢幕範圍內後,不會顯示上一張圖
        }
    }

    return convertView ;
}

2015年10月13日 星期二

在Blogger中新增CodeBlock

目的:
在blogger中新增CodeBlock

操作:
使用 http://hilite.me/ 轉換code後,將產生的內容貼到Blogger文章中即可

2015年7月24日 星期五

android 由程式觸發點擊事件(OnClickListener)

目的:

如何藉由程式直接觸發元件的點擊事件?

Button

Button.performClick() ;

TextView



TextView.performClick() ;


直接這樣做會發現到會發生NullPointer Exception


原因是有可能點擊事件雖然有設定了,但TextView為準備完成,所以造成NullPointer Exceptino,因此使用以下方式進行解決,

TextView.post( new Runnable() {
    public void run() {
        TextView.performClick() ;
    }
} ) ;

利用Runnable直接在interface thread中執行

reference:
http://stackoverflow.com/a/11035166

2015年7月21日 星期二

android 實線虛線、實現、圓角矩形、兩角圓角矩形


虛線在4.0以上無法正常顯示,所以對顯示虛線的元件關閉硬體加速,讓其可以正常顯示
可以針對單一元件關閉硬體加速:

.java

TextView.setLayerType( View.LAYER_TYPE_SOFTWARE, null )  ;


.xml


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

    <!-- dashWith:破折限寬 -->
    <!-- dashGap:線與線的空隙寬,當dashGap為0則為實線 -->
    <stroke
        android:dashGap="5dp"
        android:dashWidth="5dp"
        android:width="1px"
        android:color="@color/blue" />


</shape>


reference:
http://www.cnblogs.com/ansionchen/archive/2013/04/08/3019086.html

2015年5月25日 星期一

ListView的item中設定元件layout_weight

目的:

在listview的item中設定元件layout_weight

操作:

  1. 在item的xml中,每個元件設定layout_weight
  2. listview的設定,layout_width="match_parent"

Code:

main.xml

    <ListView
        android:id="@+id/totalReview_detailLV"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>




item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="2" >
    </TextView>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1" >
    </TextView>

</LinearLayout>

reference:
http://stackoverflow.com/a/28078042

2015年5月18日 星期一

SQLite using rawQuery

目的:

在android中使用SQLiteDatabase.rawQuery( query, whereArgs ) 進行query。

操作:

            String query = "SELECT r.id FROM %s c INNER JOIN %s r ON c.name = r.name WHERE c.id = ?" ;
            query = String.format( query, src_table_name, change_table_name, 0 ) ;
            String[] whereArgs = new String[] { String.valueOf( id ) } ;
            Cursor c = db.rawQuery( query, whereArgs ) ;

Q1. 「?」使用在table name位置時,android 會出現SQLException,無法執行。

A1. 使用String.format,搭配「%s」方式導入table name,但其他條件仍使用whereArgs方式,在query時帶入。

2015年5月17日 星期日

SQLite 時間

目的:

在SQLite中insert時,default值填入current time。

操作:

CREATE TABLE IF NOT EXISTS `test` (
  `curr_time` TIMESTAMP DEFAULT (datetime('now','localtime')) -- 時間
)

  1. `curr_time` TIMESTAMP DEFAULT (datetime('now','localtime')) :目前手機時間
  2. `curr_time` TIMESTAMP DEFAULT (datetime(CURRENT_TIMESTAMP,'localtime')) :目前手機時間
  3. `curr_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP :時間有可能非手機目前的時間

insert時間:

in Android:

            ContentValues contentValues = new ContentValues() ;
            contentValues.put( "curr_time", new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" ).format( new Date() ) ) ;
            success = ( db.update( "test", contentValues, null, null ) > 0 ) ;

2015年5月10日 星期日

DrawerLayout搭配ActionBar,設定HomeAsUp

目的:

第一頁使用側拉抽屜,HomeAsUp根據抽屜是否開啟而自動變換icon。
第二頁使用側拉抽屜,HomeAsUp直接固定使用返回icon,抽屜拉開不會改變icon。

元件:

  1. android.support.v4.widget.DrawerLayout
  2. android.support.v7.widget.ActionBarDrawerToggle

操作:

  1. 設定DrawerLayout 和 ActionBarDrawerToggle
  2. 設定啟用HomeAsUp:
    getSupportActionBar().setDisplayHomeAsUpEnabled( true ) ;
    getSupportActionBar().setHomeButtonEnabled( true ) ;
  3. 第一頁:
    mDrawerToggle.setDrawerIndicatorEnabled( truue ) ; // 預設
  4. 第N頁:
    mDrawerToggle.setDrawerIndicatorEnabled( false ) ; 

reference:
http://stackoverflow.com/q/17258020

2015年5月8日 星期五

如何使用全高的側拉抽屜?(DrawerLayout)

目的:


側拉抽屜出來的效果要高度填滿整個螢幕高(同play商店)。

PS.側拉抽屜預設效果會在ActionBar底下滑出


元件:

  1. android.support.v4.widget.DrawerLayout
  2. android.support.v7.widget.Toolbar


操作:

  1. 針對Activity的style 設定<item name="windowActionBar">false</item>
  2. 針對Activity的style 設定<item name="windowActionModeOverlay">true</item>
  3. class中設定setSupportActionBar( toolbar ) ;
**但是這樣getSupportActionBar()就會回傳null**

Q1:

只有一個頁面使用側拉抽屜,但其它頁面不需使用,但需仍需要使用ActionBar。
但是Activity的style中不設定<item name="windowActionBar">false</item>又不行。
若不設定的話,在使用setSupportActionBar( toolbar ) 將會發生Exception。

Error message:
java.lang.IllegalStateException: This Activity already has an action bar supplied by the window decor. Do not request Window.FEATURE_ACTION_BAR and set windowActionBar to false in your theme to use a Toolbar instead.

A1:

  1. 另外設定一個style
  2. 在使用class頁面中的onCreate()的第一行、super.onCreate( savedInstanceState )前,設定額外的style
    setTheme( R.style.另外的style ) ;
  3. 其餘照舊

style code:

    <style name="HomeTheme" parent="AppBaseTheme">
        <item name="windowActionBar">false</item>
        <item name="windowActionModeOverlay">true</item>
    </style>



reference:
http://stackoverflow.com/a/12724687