2013年11月24日 星期日

六時書

以當和尚遇到鑽石為基礎的六時書APP,終於完成了,原先以為只要三天就可以完成了,但因基礎工不扎實,寫了近77 49 天。最近在思考要不要把鳥事筆記本的概念也加進來,但感覺這樣就會變成一鍋大雜燴的什錦湯,會不會失去原汁原味呢??
顧及這是一個陽春 的APP,在還沒有一定的質跟量之前,就先不花錢申請google 的play store 來放了
http://blog.yam.com/felafela/article/25361837。



2013年10月15日 星期二

GPS 範例

首先要先將權限打開
 <uses-permission  android:name="android.permission.INTERNET"/>
 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

在Layout 中放入4個TextView

 <TextView    
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/longitude" />
 
  <TextView    
    android:id="@+id/longitude"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
     />
 
  <TextView    
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/latitude" />
 
  <TextView    
    android:id="@+id/latitude"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
     />
    
在主程式中 繼承了Activity 並實作LocationListener 
public class MainActivity extends Activity implements LocationListener ,在LocationListener 中有幾個方法需實作。

@Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
getLocation(location);
}

@Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}

@Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}

在onCreate 中呼叫Init 函數來判斷GPS 或網路是否被打開,如果沒被打開則應用
Settings.ACTION_LOCATION_SOURCE_SETTINGS 來把介面用intent帶到android的設定頁面。
如果GPS 或網路被打開應用
Location location=lms.getLastKnownLocation(GPS_PROVIDER); 來抓取目前位置
Double longitude=location.getLongitude();
Double latitude=location.getLatitude();
longtitudeTv.setText(String.valueOf(longitude));
latitudeTv.setText(String.valueOf(latitude));





2013年10月8日 星期二

BaseAdapter 範例



使用ListView 搭配 BaseAdapter 類別,創造出來的功能

習慣性先作介面的部分。Layout 中設計一個list.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"        
    tools:context=".myList" >

<ListView
   android:id="@android:id/list"    
   android:layout_width="fill_parent"
   android:layout_height="fill_parent" >
   
</ListView>
    
</LinearLayout>

adapter.xml 中設計了一個ImageView,一個TextView與一個CheckBox

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="wrap_content"
  android:layout_height="fill_parent"
>
<ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="10px"
/>
   
<TextView 
android:id="@+id/tv" 
android:layout_width="fill_parent" 
android:layout_height="wrap_content"
android:layout_marginLeft="15px"
android:layout_toRightOf="@id/iv"
android:gravity="center_vertical"
android:textAppearance="?android:attr/textAppearanceLarge"
android:minHeight="?android:attr/listPreferredItemHeight"
  />
 
  <CheckBox android:id="@+id/cb"
android:layout_width="wrap_content"
android:layout_height="wrap_content" 
android:layout_marginRight="15px"
android:layout_alignParentRight="true"
android:minHeight="?android:attr/listPreferredItemHeight"
android:focusable="false"
android:clickable="false"
/>
</RelativeLayout>


在主程式listView中繼承一個ListActivity,在onCreate事件中,先使用
getResources().getStringArray(R.array.books)來讀取string.xml中的books陣列。使用setListAdapter函數來為listView  提供資料。MyAdapter為一個繼承BaseAdapter的自訂類別。



protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list);
CharSequence[] list=getResources().getStringArray(R.array.books);
setListAdapter(new MyAdapter(this,list));
}

MyAdapter為一個繼承BaseAdapter的自訂類別。 可自訂一個建構子 MyAdapter(Context ctxt,CharSequence[] list),
並需實作getCount()、getItem(int position)、getItemId(int position)與 
getView(int position, View convertView, ViewGroup parent)。


其中 MyAdapter可透過LayoutInflater 取得一個View

public MyAdapter(Context ctxt,CharSequence[] list)
{
// Obtains the LayoutInflater from the given context.
// myInflater=LayoutInflater.from(ctxt);
myInflater=LayoutInflater)ctxt.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.list=list;

}
public int getCount() { return list.length; }

public Object getItem(int position) {return list[position];}


public long getItemId(int position) {return position;}

getView 可透過 ViewTag 取得與adapter.xml的連結

public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub

ViewTag viewTag;
if(convertView==null)
{
//Inflate a new view hierarchy from the specified xml resource.
//Throws InflateException if there is an error.
convertView=myInflater.inflate(R.layout.adapter,null);
viewTag = new ViewTag(
(ImageView)convertView.findViewById(R.id.iv),
(TextView) convertView.findViewById(R.id.tv),
(CheckBox) convertView.findViewById(R.id.cb)
);
convertView.setTag(viewTag);
}
else{
viewTag = (ViewTag) convertView.getTag();
}
switch(position)
{
case Jobs: 
viewTag.iv.setBackgroundResource(R.drawable.jobs);
break;
case Swan: viewTag.iv.setBackgroundResource(R.drawable.blackswan);
break;
case Thinking: viewTag.iv.setBackgroundResource(R.drawable.thinking);
break;
}

viewTag.tv.setText(list[position]);
return convertView;

}


public class ViewTag {
ImageView iv;
TextView tv;
CheckBox cb;
public ViewTag(ImageView iv, TextView tv, CheckBox cb) {
// TODO Auto-generated constructor stub
this.iv=iv;
this.tv=tv;
this.cb=cb;

}


}
程式下載


SimpleAdapter 範例



使用ListView 與SimpleAdapter 來完成。

Layout 中使用一個<ImageView> 、 一個<TextView > 與一個<CheckBox>。

在程式中繼承ListActivity,
宣告一個字串陣列 private String[] books={"賈伯斯","黑天鵝","快思慢想"}; 與一個整數陣列
private int[] img={R.drawable.jobs,R.drawable.blackswan,R.drawable.thinking}; 其中jobs、blackswan 與thinking 為圖檔,置放在drawable* 的資料夾中,一個ListView 的變數  lview。
使用 getListView 來得到目前的listview。
宣告一個字串陣列 對應到ListView 所對應的陳列的<ImageView>、<TextView >、<CheckBox>。
一個整數陣列對應<ImageView>、<TextView >、<CheckBox>的id
private String[] from={"ivv","tvV","cb"};
private int[] to={R.id.iv,R.id.tv,R.id.cb};

宣告一個LinkedList 變數data,並以for 迴圈給值
  LinkedList<HashMap<String, Object>> data=new LinkedList<HashMap<String,Object>>();

for(int i=0;i<books.length;i++)
{
HashMap<String, Object> temp=new HashMap<String, Object>();
temp.put(from[0], img[i]);
temp.put(from[1], books[i]);
data.add(temp);
}
取得一個SimpleAdapter 的物件
adapter=new SimpleAdapter(this, data, R.layout.adapter, from, to);
lview.setAdapter(adapter);



2013年9月23日 星期一

CalendarView


在Android 3.0 之後支援CalendarView,可以簡單設計日曆的View

在layout 設計

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

    <CalendarView
        android:id="@+id/cv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

</LinearLayout>

Activity 中以 cv=(CalendarView)findViewById(R.id.cv);  得到CalendarView,在OnDateChangeListener  必須實作 onSelectedDayChange(CalendarView view, int year, int month,int dayOfMonth)。
因onSelectedDayChange 在日期變化才會有變動,因此可加入一init 的預設值

程式如下

public class MainActivity extends Activity {
private CalendarView cv;
private TextView tv;
    int Myear,Mmonth,Mday;
 
 
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv=(TextView)findViewById(R.id.tv);
init();
cv=(CalendarView)findViewById(R.id.cv);
cv.setOnDateChangeListener(listener);
// cv.setOnClickListener(l);

}

public void init()
{
Calendar c=Calendar.getInstance();
int year=c.get(Calendar.YEAR);
int Mmonth=c.get(Calendar.MONTH);
int Mday=c.get(Calendar.DATE);
tv.setText(new StringBuilder().append(year)
.append("-").append(Mmonth).append("-").append(Mday));
}

OnDateChangeListener listener=new OnDateChangeListener() {

@Override
public void onSelectedDayChange(CalendarView view, int year, int month,
int dayOfMonth) {
// TODO Auto-generated method stub
Myear = year;
Mmonth = month;
Mday = dayOfMonth;
tv.setText(new StringBuilder().append(year)
.append("-").append(Mmonth).append("-").append(Mday));
}
};



@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

}

程式下載

2013年9月1日 星期日

Delphi 學習筆記 Listbox 著色

Delphi 學習筆記 Listbox 著色


=============================================================
ListBox  property 中的 style lbOwnerDrawFixed

程式中加這一段

procedure TfrmPhotoDispatch2.ListBox1DrawItem(Control: TWinControl;
  Index: Integer; Rect: TRect; State: TOwnerDrawState);
var c:Tcanvas;
    l:integer;
    sr:string;
    cr:string;
begin

    c:=Listbox1.Canvas;
    if not (odSelected in state) then
    begin
        sr:=ListBox1.Items[Index];
        l:=Pos(',',sr);
        cr:=copy(sr,l+1,length(s)-l);

        if cr='PFS' then
        begin
              c.Brush.Color:=clgreen;
              c.Font.Color:=clWhite;
              c.FillRect(Rect);
              with Rect do
                c.textout(Left,Top,copy(sr,1,l-1));
        end;

        if cr='CD_PFS' then
        begin
              c.Brush.Color:=clyellow;
              c.Font.Color:=clblue;
              c.FillRect(Rect);
              with Rect do
                c.textout(Left,Top,copy(sr,1,l-1));
        end;

        if cr='OSI_PFS' then
        begin
              c.Brush.Color:=clPurple;
              c.Font.Color:=clWhite;
              c.FillRect(Rect);
              with Rect do
                c.textout(Left,Top,copy(sr,1,l-1));
        end;
    end;

end;

2013年8月28日 星期三

裝置的網路狀態


偵測目前行動裝置以何種方式連上網路(MOBILE 或 WIFI)

layout 部分使用一個Button 與一個TextView

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="NetWork"
        />
    <TextView
    android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

</LinearLayout>

在Activity 中透過getSystemService(CONNECTIVITY_SERVICE); 取得一個handle (物件實體)
接下來經由NetWorkInfo 物件,可得到網路相關訊息
NetworkInfo networkinfo=cMgr.getActiveNetworkInfo();
tv.append(networkinfo.toString());

完整Coding
package com.example.firstnetwork;

import android.app.Activity;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {
Button btn;
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn=(Button)findViewById(R.id.btn);
tv=(TextView)findViewById(R.id.tv);
btn.setOnClickListener(l);
}

OnClickListener l=new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
ConnectivityManager cMgr=(ConnectivityManager)
getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo networkinfo=cMgr.getActiveNetworkInfo();
tv.setText(networkinfo.getTypeName());
tv.append(networkinfo.toString());
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

}






2013年8月21日 星期三

Notification 簡介

這個例子是在工具列中出現一個提示字(Notification)




首先介面的部分 ,選用LinearLayout,包含2個Button,一個來產生通知,另外一個來清除通知,XML 如下
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"  
    tools:context=".MainActivity" >

    <Button 
      android:id="@+id/createNotification"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="產生通知"   
     />
    <Button 
      android:id="@+id/cleanNotification"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="清除通知"   
     />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />


</LinearLayout>

MainActivity中 
首先建設置一個NotificationManager
接著在MainActivity 中 使用Notification.Builder 來設置Notification 物件實例
myNotificationManager=(NotificationManager)

getSystemService(Context.NOTIFICATION_SERVICE);


接下來為Builder create PendingIntent

PendingIntent pi=PendingIntent.getActivity(this, 0, it, 0);

builder.setContentIntent(pi);

最後利用notify 方法傳送notification
myNotificationManager.notify(NOTIFICATION_ID, builder.getNotification())
取消通知時就用 cancel方法
myNotificationManager.cancel(NOTIFICATION_ID);

整段程式如下
package com.example.mynotificationexample;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity {
private NotificationManager myNotificationManager;
private Button btnCreate,btnClear;
private static final int NOTIFICATION_ID = 1;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnCreate=
(Button) findViewById(R.id.createNotification);
btnCreate.setOnClickListener(l);
btnClear=(Button)findViewById(R.id.cleanNotification);
btnClear.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
myNotificationManager.cancel(NOTIFICATION_ID);
}
});
}

OnClickListener l=new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
GenerateNotification();
}
}; 

public void  GenerateNotification()
{
myNotificationManager=
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification.Builder builder=new Notification.Builder(this);
builder.setContentTitle("****這是通知抬頭****");
builder.setTicker("***這是通知****");
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setContentText("這真的是通知");
Intent it=new Intent(this,MainActivity.class);
PendingIntent pi=PendingIntent.getActivity(this
, 0, it, 0);
builder.setContentIntent(pi);
myNotificationManager.notify(NOTIFICATION_ID
, builder.getNotification());
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}


}

程式下載

2013年8月19日 星期一

自訂Toast 圖示



以下的例子將呈現如何在Toast 秀出來的短訊中,加入小圖示



先來談一下一般的Toast 的用法,
Toast toast=Toast.makeText(context, text, duration);
toast.show();

而如果要設定Toast 的位置,則可以用
toast.setGravity(Gravity.TOP|Gravity.RIGHT, 0, 0);
來設定。

要在Toast 中加入圖示的方法為:

先設定一個layout: customtoast.xml,設定為LinearLayout ,id 為toast_layout_root。內含一個Image與TextView

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/toast_layout_root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="10dp"
android:background="#DAAA" android:orientation="horizontal">
<ImageView
    android:id="@+id/mandsm"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginRight="10dp"
/>
<TextView
    android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:textColor="#FFFF"
/>
   

</LinearLayout>

在Activity 中使用LayoutInflater;來解析XML檔,生成視圖元件,LayoutInflater 必須使用getLayoutInflater來取得正在運作的實體,
LayoutInflater inflater=getLayoutInflater();
利用Inflater.inflate 傳回一個View
也可以用
LayoutInflater inflater=LayoutInflater.from(ctxt);
或是
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
來獲得。


layout=inflater.inflate(R.layout.customtoast
,(ViewGroup) findViewById(R.id.toast_layout_root)); 

設定image 的圖檔與TextView 的文字。

ImageView image = (ImageView) layout.findViewById(R.id.mandsm);
image.setImageResource(R.drawable.ic_launcher);
TextView text = (TextView) layout.findViewById(R.id.text);
text.setText("Short custom message");

在OnClick 事件中,可以利用
Toast(getApplicationContext())取得 toast ,
toast.setView(layout);
toast.show() 

來呈現。

程式下載

2013年8月7日 星期三

View 淺說(一)

先New 一個專案 MyView,定義res/layout/main.xml,包含兩個LinearLayout容器。一個Button


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
   >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        >
    <Button 
        android:id="@+id/save"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:text="Save"
        /> 
</ LinearLayout >
</ LinearLayout >


在專案中的src 中 NEW 一個新的Class myview 繼承自View 這個類別。myview 必須實作建構子
myview。 利用Paint()函數,抓取一個預設的paint ,並用setBackgroundColor()為View 上色



public class myview extends View {
private Paint paint;
public myview(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
//Create a new paint with default settings.
paint=new Paint();
paint.setColor(Color.YELLOW);
paint.setStrokeWidth(4); 
setBackgroundColor(Color.BLACK);
}
}



存檔後,修改l/res/layout/main.xml ,於LinearLayout中加入自訂的View,取名為vv。

 <com.example.myview.myview

        android:id="@+id/vv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
    </com.example.myview.myview>






2013年8月6日 星期二

Handler 類別

Thread 執行緒中不能直接呼叫介面。因此若想將結果呈現在TextView 中,必須透過Handler類別協助。

private class MyHandler extends Handler
{
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
tv.setText(""+counter++);
super.handleMessage(msg);
}
}

其中tv 是一個Textview 。

在Thread 的run 事件中呼叫Handler 送出message,

public void run()
{
for(int i=1;i<20;i++)
{
handler.sendMessage(new Message());
try {
Thread.sleep(1000);  // 每隔一秒休息一下
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}



程式下載