2015年7月11日 星期六

【Android】Android studio 如何新增drawable

如何在Android Studio 中 新增drawable


首先

右鍵點選drawable資料夾 --> new --> Image Asset





















然後

點選進入,並選擇你要新增的圖片檔案



















在drawable的資料夾就會新增你剛剛新增的圖檔了,並且會分別製成不同大小的圖檔,供你使用。


官方所製作的圖檔:
https://www.google.com/design/icons/index.html
官方提供製作圖檔的工具:
http://romannurik.github.io/AndroidAssetStudio/index.html

2015年7月7日 星期二

【Android】Android Studio assets資料夾& fonts 新增外部字型


這次要解決一個簡單的小問題,以前使用Eclipce時有一個assets資料夾,
但使用Android studio時要如何建立這個資料夾?

並且新增完assets資料夾後新增外部字型。


首先

assets資料夾在Android studio中以Android 專案顯示方式來看,是與Manifiest & Java 在同一層


所以

我們直接於 app 右鍵-->new --> folder --> assets 
就能夠找到。


建立起來之後就能在新增fonts資料夾來使用外部字型


將字型檔案放入後就能夠以下面的code來使用外部字型

TextView WebTitleText;
WebTitleText = (TextView) Custom.findViewById(R.id.WebTitleText);
//設定字型
Typeface face = Typeface.createFromAsset(FragmentContext.getAssets(),"fonts/Roboto-Bold.ttf");
WebTitleText.setTypeface(face);


參考網址:
http://stackoverflow.com/questions/18302603/where-to-place-assets-folder-in-android-studio

2015年5月29日 星期五

【Android】ListView 自訂畫面 簡易電話簿

這次要利用ListView來製作一個簡單的電話簿,
主要會用到這兩項知識:
  • ListView
  • BaseAdapter
我的範例主要是搭配fragment_navigation_drawer,所以我會建立在fragment裡,如果你是要寫在Activtiy裡就稍作修改就可以了 ! !

那我們會建立出:
  • myFragmet.java:用於顯示listview
  • PhoneNumberAdpater.java:listview的資料轉接器
  • myfragmet_layout.xml:fragment的layout
  • phonenumber_listview.xml:因為我們要自訂畫面所以要額外使用一個xml來設定我們要的畫面
  • listview_header.xml:來建立出listview的標頭header
  • item_select.xml:放置在drawable底下,用於點選後變色的設定
  • color.xml:放置在value底下用於建立要變的顏色

完成後的畫面:
























以下是code的部分

  • myFragment.java
先建立出需要的資料
String [] Name = new String[]{"陳oo","林oo","溫oo","施oo","胡oo"};
String [] Number = new String[]{"0970135531","0937232323","0928123456","0987987789","0988123423"};

用setAdapter這個方法去將資料送給BaseAdapter
PhoneNumberListView.setAdapter(new PhoneNumberAdapter(getActivity(),Name,Number));

public class Meun1Fragment extends Fragment {

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

}
View RootView;
private ListView PhoneNumberListView;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
RootView = inflater.inflate(R.layout.meun1_fragment,container,false);
//自己塞的資料
String [] Name = new String[]{"陳oo","林oo","溫oo","施oo","胡oo"};
String [] Number = new String[]{"0970135531","0937232323","0928123456","0987987789","0988123423"};
PhoneNumberListView = (ListView) RootView.findViewById(R.id.listView);
//取得header layout
View header = inflater.inflate(R.layout.listviewsms_header, PhoneNumberListView, false);
PhoneNumberListView.addHeaderView(header, null, false);
//自訂layout頁面並利用Baseadater來轉接
PhoneNumberListView.setAdapter(new PhoneNumberAdapter(getActivity(),Name,Number));

//用android本身設計得好的樣式
//ArrayAdapter aa= new ArrayAdapter(getActivity(),android.R.layout.simple_expandable_list_item_1,value);



return RootView;
}
}




  • PhoneNumberAdpater.java
建立出一個轉接器來讓我們能夠自訂listview的呈現方式以及將資料丟給listview


public class PhoneNumberAdapter extends BaseAdapter {
    private LayoutInflater inflater;
    String [] Name;
    String [] Number;
    private Context FragmentContext;
    //建構子
    public  PhoneNumberAdapter (Context FragmentContext, String[] Name, String [] Number){
        inflater = LayoutInflater.from(FragmentContext);
        this.Name = Name;
        this.Number = Number;
        this.FragmentContext = FragmentContext;
    }
    @Override
    public int getCount() {
        return Name.length;
    }

    @Override
    public Object getItem(int i) {
        return null;
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        //利用view去設定我們自訂的layout
        view = inflater.inflate(R.layout.phonenumber_listview,viewGroup,false);
        TextView NameText,NumberText;
        NameText = (TextView) view.findViewById(R.id.textView4);
        NumberText = (TextView) view.findViewById(R.id.textView3);
        NameText.setText(Name[i]);
        NumberText.setText(Number[i]);
        //設置監聽
        view.setOnClickListener(new OnClickListener(Name[i],Number[i]) {});
        return view;
    }
    class OnClickListener implements View.OnClickListener{
        private String Name;
        private String Number;
       //利用建構子取得內容
        public OnClickListener(String Name,String Number){
            this.Name = Name;
            this.Number = Number;
        }
        @Override
        public void onClick(View view) {
            AlertDialog.Builder builder = new AlertDialog.Builder(FragmentContext);
            builder.setTitle(FragmentContext.getString(R.string.callphone_yes_no))
                   .setMessage(Name +"\n"+ Number)
                    .setPositiveButton("撥打", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
                            Intent call = new Intent(
                                    Intent.ACTION_CALL, Uri.parse("tel:" + Number));
                            FragmentContext.startActivity(call);
                        }
                    })
                    .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {

                        }
                    });
            AlertDialog PhoneCallDialog = builder.create();
            PhoneCallDialog.show();
        }
    }
}




  • item_select.xml
主要用於設定click後變色的狀態,android:state_pressed="true"只要有按下則會去改變畫面的顏色


selector xmlns:android="http://schemas.android.com/apk/res/android">
item android:drawable="@color/lightskyblue" android:state_pressed="true">
item android:drawable="@android:color/transparent">
/item>


並且要記得在phonenumber_listview.xml上增加 android:background="@drawable/item_select"才會改變


linearlayout
xmlns:android="http://schemas.android.com/apk/res/android">
android:background="@drawable/item_select"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="horizontal"

參考連結:

ListView+BaseAdapter應用 I ─ onLongClick與Clipboard

http://a6350202.pixnet.net/blog/post/241188445-%E3%80%90android%E3%80%91listview%2Bbaseadapter%E6%87%89%E7%94%A8-i-%E2%94%80-onlongclick%E8%88%87














2015年5月10日 星期日

【JAVA】String的內容值不可變

我們來探討一下關於String的內容指與比較



String s = "DOG";
s ="CAT";

在我們看來值好像改變了,但其實他並不是改變值,

因為String是一個參考類別,賦予他值後,他是將 s 指向 "DOG"這個這個實體,

當你又賦予了一個新的值"CAT", s 是直接重新指向"CAT"的實體,並非將DOG實體改為CAT


改變的是位址並不是實體!!!!



這就是所謂 String的內容值不可變 的意思。


延伸思考一:



既然String s 是指向位置

那麼當

String str1 = new String("Dog");
String str2 = new String("Dog");

System.out.println(str1 == str2);

會回傳甚麼?

答案是:false
因為他們指向的是不同的位置,用 == 是在比較str他們的值,而他們的值都是位置並非字串,所以當你使用 == 來做比較字串會發生錯誤!!!!

要利用equals()這個方法才能比較字串。



延伸思考二:

那麼當


String str1 = "Dog";
String str2 = "Dog";

System.out.println(str1 == str2);

會回傳甚麼?

答案是:true


因為我們是直接指向相同的字串,而在Java中有一個
StringPool他會先去找是否有相同的字串,有的話直接指向,不在重新創造實體出來。

如果你想先檢查是否在
StringPool有相同字串,你可以利用intern()這個方法。


範例:(取自良葛格blog)

public class StringIntern { 
    public static void main(String[] args) { 
        String str1 = "fly"; 
        String str2 = "weight"; 
        String str3 = "flyweight"; 
        String str4; 

        str4 = str1 + str2; 
        System.out.println(str3 == str4); 
        //false
        str4 = (str1 + str2).intern(); 
        System.out.println(str3 == str4); 
       //true
    } 
} 


參考連結:http://openhome.cc/Gossip/JavaGossip-V1/ImmutableString.htm

2015年3月30日 星期一

【Android】Widget製作時鐘

這次要來用Widget來製作一個小時鐘,主要會用到下面幾個項目知識

  • Widget
  • Handler
  • Service
我們的目標是顯示現在的時刻
Ex : 2015/05/12 17:00

需要在code裡不斷的重新更新時間,下面這段code就是new出一個新的時間並設定我們需要的格式。

new SimpleDateFormat( "yyyy/MM/dd HH:mm:ss" ).format( new Date())

在Widget的部分主要是要intent Service交由Service去處理我們的每秒更新與背景。

Widget.java

public class SmsWidget extends AppWidgetProvider {
   
    Context context_main ;
    AppWidgetManager app_manager;
    int []appWidgetId;
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
       
        
        app_manager = appWidgetManager;
        context_main = context;
        appWidgetId = appWidgetIds;

       //new出一個 intent並將Widget的context傳入
        Intent intent = new Intent(context_main,WidgetService.class);
 //Intent執行service服務
context_main.startService(intent);


    }

    @Override
    public void onEnabled(Context context) {
       
    }

    @Override
    public void onDisabled(Context context) {
        //當WidgetDisable時關閉service服務
        Intent intent = new Intent(context_main,WidgetService.class);
        context_main.stopService(intent);
    }
}


那我們要如何不斷的new出新的時間並更新widget的view ?
其實只要用handler來處理即可,並搭配Service讓code在背景執行,執行一次就更新一秒。


Service.java

public class WidgetService extends Service {
    private Handler mHandlerBoss = null;
    private HandlerThread mHandlerEmployee = null;
    private String EmployeeName = "John";
    public WidgetService() {
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        //service結束,結束handler
        mHandlerBoss.removeCallbacks(mRunnable);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //建立Handler
        //Handler簡單來說就是需要老闆、員工、工作
        //建立一個員工
        mHandlerEmployee = new HandlerThread(EmployeeName);
        //員工上班
        mHandlerEmployee.start();
        //建立一個老闆,老闆聘員工上班
        mHandlerBoss = new Handler(mHandlerEmployee.getLooper());
        //老闆指派工作給員工
        mHandlerBoss.post(mRunnable);
        return super.onStartCommand(intent, flags, startId);
    }
    private Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            //更新Widget畫面
            buildUpdate();
            //每秒跑一次
            mHandlerBoss.postDelayed(this,1000);
        }
    };
    private void buildUpdate()
    {
        
        RemoteViews view = new RemoteViews(getPackageName(), R.layout.sms_widget);
        view.setTextViewText(R.id.appwidget_text, new SimpleDateFormat( "yyyy/MM/dd HH:mm:ss" ).format( new Date()));

        ComponentName thisWidget = new ComponentName(this, SmsWidget.class);

        AppWidgetManager manager = AppWidgetManager.getInstance(this);

        manager.updateAppWidget(thisWidget, view);
    }
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

編譯成功後就能夠在,手機裡將Widget拉出來使用。

參考連結:
Widget Update http://stackoverflow.com/questions/4866305/android-widget-update
背景執行 http://cooking-java.blogspot.tw/2010/04/android-service.html



【Android】如何新增分隔線於layout中


在html中常見的分隔線,於android layout中要如何設置



相當簡單於xml檔中加入以下的code即可顯示出一條分隔線

<view
   android:background="#000000"
   android:layout_height="2dp"
   android:layout_width="fill_parent"
</view>






參考:

2015年3月28日 星期六

【Android】Widget 簡單範例



Widget就是在手機上常看到的小工具,可以放入主頁,使用Android Studio就可以簡單的建立一個Widget。

一、

建立一個project就照之前的方式建立起來,在選擇Activity的地方可以選擇add no ,就是不建立Activity。


二、

在java->你的package上點選右鍵,找到New新建一個Widget,











其中分別有
  • Class Name (名稱)
  •  Placement(放置位置)
    • Home screen (手機畫面位置) 
    • Keyguard(手機解鎖位置) 
    •  Home screen & Keyguard (兩者皆可)
  •  Resizable (是否能夠調整大小)
         ※放置桌面後是否能夠調整大小
  •  Width&Height(桌面佔用大小)

就依造自己的需求選擇,完成後按下FINSH,Android Studio就會幫你建立起來。



三、

建立後會看到新增了三項東西,分別是:
  • NewAppWidget.java 
  • NewAppWidget.xml (Widget介面設計)
  • NewAppWidget_Widget.info.xml (Widget的資訊)


參考連結: