顯示具有 android studio 標籤的文章。 顯示所有文章
顯示具有 android studio 標籤的文章。 顯示所有文章

2022年5月19日 星期四

android studio:ProgressBar 進度條

 一、xml設定 

<ProgressBar

    android:id="@+id/progressBar"
style="?android:attr/progressBarStyle"
android:layout_width="100sp"
android:layout_height="100sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.41" />

二、宣告類型及引用

private ProgressBar pb;

pb = (ProgressBar) findViewById(R.id.pb);


三、設定進度表進度

pb.setProgress(pg);


四、進度條顯示及隱藏
pb.setVisibility(View.GONE);
pb.setVisibility(View.VISIBLE);


2022年4月22日 星期五

android studio:字串處理的一些方法

有時候,取回來的文字資料,需要進行適當的處理,才可以再度利用,這時候就會用到java處理文字的方法。

(1)replace 用新的數值取代字串中的舊數值

String Text="這個字是a,要取代成b";
//以參數2的文字取代參數1的文字,只可替換文字
Text.replace("a","b");
//以參數2的值取代參數1的值,可替換其它如空白、\\d等參數式,此範例為將兩個空白取代成一個空白
Text.replaceAll(" "," ");
//只更換第一個,以參數2的值取代參數1的值,可替換其它如空白、\\d等參數式,此範例為將兩個空白取代成一個空白
Text.replaceFirst(" "," ");

(2)split 將有固定分隔號的字串,轉為清單形式
String Text="3 4 5";
//利用空格將字串分成[3,4,5],這樣利用取得清單的方式取得其中的某個值,中間要加中括號
Text.split("[ ]");
String[] words = Text.split("[ ]");
//遇特殊的符號,正則運算式,要加兩個反斜線\\,這很重要
List<String> list2=new ArrayList();
list2= Arrays.asList(Text.split("[ ]"));

如果要區隔的元件是正則表示式,像是.(連接符號)、^(限制開頭),要加兩個反斜線

(3)substring 取出某個位置到某個位置的字串
String str="我是一個天才";
//參數1是要取值的第一個位置,第二個是結束的位置,這個位置不包含第一個位置,以下取得"是"
str=str.substring(1,2);
//參數1是要取值的第1個位置,後面沒有設,因此到結尾,以下取得"一個天才"
str=str.substring(2);
//參數1為第1個位置,參數2為你要搜尋的那個字位置,以下取得"一個天"
str=str.substring(2,str.indexOf("才"));

(4)indexOf 搜尋某個字串的位置
String str="我是一個天才,你也是一個天才";
//參數一為你要搜尋的字串,搜尋字串"一"出現的第一位置
str.indexOf("一");
//參數一為你要搜尋的字串,參數二是搜尋的起始點,此為由第4個位置開始,搜尋字串"一"出現的第一位置
str.indexOf("一",4);
//參數一為你要搜尋的字串,搜尋字串"一"出現的最後一個位置
str.lastIndexOf("一");

(5)charAt
String str="我是一個天才,你也是一個天才";
//參數一為你要搜尋的位置,以下為搜尋第5個位置,得到的值為"天"
str.charAt(5);

(6)startsWith和endsWith

String str="我是一個天才,你也是一個天才";
//參數一為你要搜尋的前綴字串,傳回值為布林值,若符合是真,不符合是假"
str.startsWith("我是");
//參數一為你要搜尋的後綴字串,傳回值為布林值,若符合是真,不符合是假"
str.endsWith("天才");

(7)concat 連接兩個字串

string1.concat(string2); //以下連接string1和string2兩個字串


(8)compareTo 比較兩個字串的長度值,返回值為int,此int為兩個字串的長度差


(9)trim 去除字串前後的空白

String String = new String("   www.xxx.com    ");
String.trim(); //去除字串前後的空白

(10)contains 判斷字串裡是否包含某字串,若有則會傳回true值。
String string = "這是一個測試";
boolean b=string.contains("是"); //傳回True值

參考網頁:https://www.runoob.com/java/java-string.html
               https://www.w3schools.com/java/java_strings.asp


android studio:Timer

Timer為計時器,在執行android studio時,有時需要停下來一段時間,再執行活動,就會用到Timer,而它的用法大致如下:

(1)宣告

private Timer timer;

(2)實際運作方法

//於此處執行timer要執行的工作
TimerTask task =new TimerTask() {
@Override
public void run() {
//此處放要執行的工作
}
};
timer.schedule(task,2000); //執行計時器,參數1為要執行的TimerTask名稱,參數2為秒數
timer.cancel(); //釋放timer記憶體

2022年3月26日 星期六

android studio:BroadcastReceiver

 BroadcastReceiver 為廣播功能,就像是我們在日常生活中的廣播一樣,它有播放的一方,也有接收的一方。廣播有靜態註冊及動態註冊兩種方法。下面先說比較常用的動態註冊方法,再來說較少用的靜態註冊方法。

一、動態註冊的方法

(1)廣播的方法

Intent intent=new Intent("fromService"); //宣告一個intent,名稱為fromService
intent.putExtra("wherenow",mediaPlayer.getCurrentPosition());
//設定intent要傳送的資料,參數一為值的名稱,後為資料
sendBroadcast(intent); //透過廣播的方法送出

(2)接收的方法
myReceiver =new MyReceiver(); //建立接收器
IntentFilter filter=new IntentFilter("fromService");
//建立授收的過濾器,參數為過濾器選擇的名單,只接受intent傳過來名為"fromService"的資料
registerReceiver(myReceiver, filter);
//註冊接收器及過濾名單

上面myReceiver是MyReceiver類別的新建物件,MyReceiver的寫法如下,可在裡面處理讀取的數據。
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//參數一為內容,參數二為傳過來的intent
String name = intent.getStringExtra("wherenow"); //利用getStringExtra取得intent傳過來的值
}

(3)撤消Receiver
unregisterReceiver(MyReceive);

二、靜態註冊的方法
暫時不寫,請看參考網頁。



參考網頁:
https://xnfood.com.tw/android-broadcastreceiver/


android studio:handler

APP程式在執行時有主執行緒和副執行緒,而系統為避免主執行緒和副執行緒同時執行,導至呈現畫面的UI(User Interface使用者介面)產生錯亂,因此設計只能在主執行緒更新UI的畫面。那在背景執行副執行緒時,就必需透一個方法,告知主執行緒要更新了。兩者之間的溝通,會依靠handler,handler是一個控制器,提供了一處理與發送消息的方法。

handler在主執行緒中建立時,此時會默認執行一個Looper的方法,讓它重覆的監聽訊息,另外在Lopper創建時,也會自動生成一個MessageQueue,這裡面的Message類有what(定義如何操作此方法)、obj(物件的變量)、arg1(簡單的整數類型)、 arg2等變量,可以作為主副執行緒資料溝通的方法,在副執行緒中,當要處理的方法取得資料時,就透過Message類別方法傳訊息給主執行緒處理。

實作的方法大概如下:

(1)在主要的執行緒中建立handler,這個handler會做的工作是重覆執行,用以監聽副執行緒是否有傳入message:大概的方法如下:

handler = new Handler(){ //宣告一個新的hander
@Override
public void handleMessage(@NonNull Message msg) {
//super.handleMessage(msg);
switch (msg.what){ //利用message.what判斷是那個message傳入的訊息
case 1:
textView.setText(msg.obj.toString()); //此處要執行的程式
break;
case 2:
break;
}
}
};

(2)在副執行緒中適當的地方,當你完成你的工作時,可透過sendMessage的方法,將訊息傳回主要的執行緒,傳送的方法如下:

Message message=Message.obtain(); //宣告一個要傳送的message元件
message.what=1; //設定message.what=1 如果有很多不同的hander訊息,這個what可判斷是那一個hander
message.obj=data; //data為要傳送的資料
handler.sendMessage(message); //將想要傳出的訊息用sendMessage傳出,參數為要傳出的訊息。


其它補充:
(1)將 Runnable 添加Runnable在handler的監測列中。
handler.post(Runnable r),參數為要執行的Runable。
(2)Runnable 添加Runnable在handler的監測列中。,並指定執行延遲的時間。
handler.postDelayed(Runnable r, long delayMillis) 參數一為要執行的Runable,參數二為延遲的毫秒數。
(3)刪除handler中的Runnable監測
handler.removeCallbacks(Runnable r),參數一要停止的Runnable。
handler.removeCallbacks(Runnable r, Object token),參數一為要停止的Runnable,參數二為傳送的obj資料。
handler.removeCallbacksAndMessages(Object token) 參數為要傳送的obj
handler.removeMessages(int what),參數為要傳送的waht
(4)發送handler裡的thread處理完要發送的message
handler.sendMessage(Message msg),參數一要發送的訊息
handler.sendMessageDelayed(Message msg, long delayMillis),參數一要發送的訊息,參數二為延時傳送的時間
(5)於handler 中接收訊息的方法
handleMessage(Message msg) 參數一為副執行緒中回傳的Message。


參考網頁:
https://developer.android.com/reference/android/os/Handler
https://blog.csdn.net/wenzhi20102321/article/details/107888152
https://codertw.com/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80/737182/




2022年3月20日 星期日

android studio:Fragment

 Fragment有點像Activity,它必需放在Activity中,可以看作子Activity,一個activity裡可以放好幾個 Fragment,當Activity結束, Fragment也會跟著結束。

簡單使用Fragment的方法如下:

1.在MainActivity的xml設定一個FrameLayout,做為放置Fragment的地方:

<FrameLayout 
android:id="@+id/framelayout"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

2.建立你需要的Fragment <File> → <new> →<Fragment> →選擇你要的Fragment類型

3.建立FragmentManager做為設定器
4.利用beginTransation建立轉移的方法。
5.利用add 或是replace將你要放置的Fragment放入預先做好的FrameLayout中,其中的參數1是FrameLayout的id,參數2是你要放入的fragment
6.加入addToBackStack,將加入的fragment放入FragmentManager設定器中,這樣的好處是何以按上一頁按鍵,回到上一頁,而不是直接跳開。
7.利用commit執行畫面轉移。

FragmentManager fragmentManager=getSupportFragmentManager();
//設定fragmentManager的設定器
FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction();
//新建fragmentTransaction轉移方法
BlankFragment2 blankFragment2=new BlankFragment2();
fragmentTransaction.replace(R.id.framelayout,blankFragment2);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
其餘,可用的FragmentManager方法如下:
add() 增加Fragment於FragmentManager中,可同時增加很多個Fragment
show() 透過顯示,顯示你要的Fragment
hide()透過隱藏,隱藏不要的Fragment

8.若要在Fragment中互相傳遞資料
(1)需將資料放置在Bundle中,並利用setArguments這個方法傳出,如下:

BlankFragment2 blankFragment2=new BlankFragment2(); 
Bundle bundledata = new Bundle(); //新增一bundle放置資料
bundledata.putString("data", "要傳的資料"); //放置要傳送的資料至bundle中
blankFragment2.setArguments(bundledata); //將設置好的bundle資料放入你要傳送到的Fragment

(2)而取得的方法如下:
if (getArguments() != null) { //判斷是否取得傳入的值
String mParam1 = getArguments().getString("data"); //設定mParam1為傳送的值
TextView textView = view.findViewById(R.id.textview2); //引入TextView
textView.setText(mParam1); //將TextView的文字設為傳入的值
}

2022年3月19日 星期六

android studio:LayoutParams

 LayoutParams可設定視圖的長寬,以下示範LayoutParams的用法:

(一)設定LinearLayout長寬,並放入父視圖中

LinearLayout linearLayout=new LinearLayout(this);
//新建一個LinearLayout
LinearLayout.LayoutParams layoutParams=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT);
//將此linearlayout的長寬值設定於layoutParams中,參數1為長,參數2為寬,ViewGroup.LayoutParams.MATCH_PARENT為占滿父視圖的全部
linearLayout.setLayoutParams(layoutParams);
//將linearLayout的長寬依上面的layoutParams設定
setContentView(linearLayout);
//將此LinearLayout放進父視圖中。因此前面設成長寬都同父視圖,因此會佔滿父視圖
//setContentView(linearLayout ,layoutParams); 用此寫法可省略上面設定linearLayout長寬的步驟

(二)設定TextView視圖長寬,並放入父視圖中

TextView textView=new TextView(this);
//新建一個TextView
textView.setText("新建視圖");
//設定文字
LinearLayout.LayoutParams layoutParams2=new LinearLayout.LayoutParams(200,200);
//將此textview的長寬值設定於layoutParams2中,長200,寬200
linearLayout.setLayoutParams(layoutParams2);
//將linearLayout的長寬依上面的layoutParams設定
linearLayout.addView(textView);
//將textView加入父視圖中,此為上剛新建的linearLayout



android studio:Notification

這篇在說明顯示訊息於手機訊息列上的方法:

一、必需要有一個NotifictaioManager 做為控制器,控制訊息的傳送。

(1)宣告
private NotificationManager manager; //宣告一個NotificationManger
(2)建立一個NotifictaioManager
manager= (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
//宣告NotificationManager,它是一個服務的管理器。透過getSystemService這個方法,取得系統裡的訊息管理器

二、利用NotificationCompat.Builder,建立一個Notifictaio,處理要發送哪些訊息,以及如何發送。詳細的方法如下:(因中間需要一個頻道,所以要放在三的頻道建立之後。)
notification=new NotificationCompat.Builder(this,CHANNEL_ID)
.setContentTitle("哈囉你好!")
.setContentText("跟你打個招呼啊~")
.setSmallIcon(R.drawable.ic_stat_name) //圖標只能用alpha圖層,有顏色的不行
//builder的屬性必定要有title contentText和Smalll
.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.pngegg)) //設定開啟後,右邊大圖示
.setColor(Color.parseColor("#ff0000")) //設定小圖顏色
.setWhen(System.currentTimeMillis()) //設定時間
//.setContentIntent(pendingIntent) //設定點擊後,跳至某其它頁面,pendingIntent需自行設置
.addAction(R.drawable.ic_baseline_help_24, "說明", pendingIntent) // 增加「說明」
.setAutoCancel(true) //訊息點擊後自動取消
.build();
//透過NotificationCompat.Builder創建notification,以處理等會我們要發送的訊息,
// builder裡的參數1為Notification顯示內容的地方,參數2為頻道名稱

三、android studio 8.0之後,要自己建立一個Channel,接收訊息。建立的方法,如下:
(1)新建channel
(2)放置新建的channel放進channel
//android版本8.0版本以上需創建自己接收訊息的channel,因此一開始先判斷版本,若超過版本,再創建
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID, "DemoCode", NotificationManager.IMPORTANCE_HIGH);
//新建一個可以顯示訊息的頻道,NotificationChannel參數1為頻道名稱,可自己設置(需與builder的參數相同),
// 第二個是觀看者可以看到的訊息通知名稱,可自己設置,第三個是通知的重要性設定,預設為不跳出訊息,這裡設定high,為跳出
manager.createNotificationChannel(channel); //在NotificationManager管理器中,加入剛才新建的頻道,創建頻道
}


四、將取得的資料和頻道,透過NotificationManager利用.notify的方法,發送出去。

manager.notify(1,notification); //上面的只是設置,真正要發送,需透過notify,參數1可以自己設置,第二個為前面建立的notification.

五、若要清除訊息,利用下面的方法:
// 清除所有通知
manager.cancelAll();

//清除個別通知
//manager.cancel(1); 清除id為1的訊息


六、如果要點選訊息,而後跳頁,需於notification加入setContentIntent這個方法,並新建一個PendingIntent類型的intent,見如下的寫法。

Intent intent =new Intent(getApplicationContext(),MainActivity2.class); //新建一個intent
PendingIntent pendingIntent=PendingIntent.getActivity(MainActivity.this,0,intent,PendingIntent.FLAG_CANCEL_CURRENT);
//建立一個PendingIntent讓點擊Action時使用






2022年3月16日 星期三

android studio:List(Array、ArrayList、LinkedList )說明


List是所謂的陣列類別,是儲存資料的一種方式。在Android Studio中,只有介面,沒有實作,而若要實作,則要使用List下 ArrayList與Array及LinkedArray等類別。

一、ArrayList是一個List的子類別,可具體化,它與Array不同,它的大小可以改變,而因為裡面的元素很多,因此可以採用泛型的方式建立物件,不用先指定ArrayList()<>裡的元素類型,因為它是用Object[] elementData的方式運作,其中的元素必須是物件類型。

(一)新建ArrayList的方式如下:(1 2利用了ArrayList可泛型的特性,不給予元素類型)
1.以下四種方式皆可:
List arrayList= new ArrayList() //宣告arrayList為List類型的物件
ArrayList arrayList= new ArrayList(); //宣告arrayList為arrayList類型的物件
ArrayList<String> arrayList=new ArrayList<>(); //定義陣列的第一個值是String類型
ArrayList<String> arrayList=new ArrayList<String>(); //原兩邊都要寫類型,JAVA SE7後改成可省略。

2.原不可以加原始類型:
ArrayList<int> arrayList = new ArrayList<int>(); //這種寫法會報錯,因為int是原始型別
ArrayList<Integer> arrayList= new ArrayList<Integer>();  //可透過一些重新包裝的類別,進行宣告


(二)加入ArrayList陣列值的方法 .add("想加入的資料")
在此列表中的指定位置插入指定的元素。參數說明:index為要值入的位置,element為要插入的值,若沒有加入位置,則插入最後一個位置。

arrayList.add("1");
arrayList.add("2");
arrayList.add("3");


(三)取得ArrayList陣列值的方法 .get(int index);返回此列表中指定位置的元素。
arrayList.get(0); //取得陣列1的值
arrayList.get(1); //取得陣列2的值
arrayList.get(2); //取得陣列3的值


(四)計算陣列的長度 .size()
arrayList.size();

(五)查詢是否有某特定的值,有則回傳真,沒有為假 .contains() 
arrayList.contains(1);

(六)查詢某特定值位於那一個陣列中 indexOf()
arrayList.indexOf(1);


(七)刪除特定元素 .remove(1)
arrayList.remove(1);


(八)判斷是否為空 isEmpty()
arrayList.isEmpty();


(九)清除陣列所有資料 .clear()
arrayList.clear();

延伸連結:https://www.w3schools.com/java/java_arraylist.asp

二、Array陣列

Array是一個較為簡潔的List,它在宣告時要先給予大小,因為若你一開始就確定你陣列中要放幾個元素,就可以使用Array,裡面可以儲存原始類別及物件,
(一)新建的方法
String[]  array= new String[10]; //宣告一個類型為String的陣列,空間為11,0也算一個
int[]  array= new int[10]; //宣告一個類型為int的陣列,空間為11,0也算一個
int[]  array=new int[]{5,7,8}; // 新建一個int[]實體,並直接給賦值
int[]  array={5,7,8}; //直接給賦值


(二)加入陣列值的方法
可直接利用[陣列位置]將陣列的值加入
String[]  array= new String[2];
array[0]="第一個";
array[1]="第二個";

也可以在新建的時候直接加入
String array[] = new String[]{"第一個","第二個"};
int array2[] = new int[]{1,2};

(三)替換的方法,基本上透過[陣列位置]加上=來直接更換裡面的數值
array[0]="換的第一個";
array[1]="換的第二個";
(四) 搜尋數組中的某一個值的位置,找不到會回傳-1
Arrays.binarySearch(陣列,要搜尋的值);



延伸連結:https://www.w3schools.com/java/java_arrays.asp

三、Array和ArrayList兩個資料互換的方法
(1)arrayList轉成list,利用toArray方法,如下:
int size =list.size();
String[] array = list.toArray(new String[size]);  //轉換時要給予array空間大小,因此要先計算原來的ArrayList的空間大小。

(2)list轉成arrayList,利用asList方法,如下:
List<String> list=Arrays.asList(array); //arrayList不用管空間大小,因此利用asList方法將資料一個一個放進ArrayList就可以了。
 

四、LinkedList
LinkedList也是一個寫好的List類別,和ArrayList的差別在於,LinkedList裡儲存的陣列資料,可以排序,因此有一些需要排序才能運用的功能,使用LinkedList會比較方便,如指定新增最後一項資料,又如指定新增第一項資料等。

(一)新建LinkedList的方法如下:
不加陣列類型
LinkedList linkedList=new LinkedList();
加入陣列類型
LinkedList<String> linkedList2=new LinkedList<>();

(二)加入陣列的資料
linkedList.add("新增某一項"); //新增某一項
linkedList.addFirst("新增第一項"); //新增新一項
linkedList.addLast("新增最後一項"); //新增最後一項


(三)移除陣列的資料
linkedList.remove("某一項"); //移除某一項
linkedList.removeFirst(); //移除第一項
linkedList.removeLast(); //移除最後一項

(四)取得陣列資料
linkedList.get(0); //取得某一項
linkedList.getFirst(); //取得第一項
linkedList.getLast(); //取得最後一項

延伸連結:https://www.w3schools.com/java/java_linkedlist.asp

 














2022年3月15日 星期二

android studio:ListView

 ListView是一種陳列清單資料的視圖,如果需要陳列一些較規律性的資料,利用TextView慢慢編排,過於麻煩,便可利用ListView這個視圖,將資料快速顯現於營幕上面。

(一)使用用法一

可以於string.xml中設定string array,將想要於ListView列表的文字快速的設定好,而後在MainActivity.xml,或其它的xml,透過android:entries這個屬性,引入此string array即可。

如下:

string.xml 設定

<resources>
<string name="app_name">ListView</string> //此專案的名字
<string-array name="listview1"> //清單的名字,引用時為@array/listview1
<item>文字1</item> //清單項目一
<item>文字2</item> //清單項目二
<item>文字3</item> //清單項目三
</string-array>
</resources>


MainActivity.xml

<ListView
android:id="@+id/listview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="1dp"
android:layout_marginTop="1dp"
android:layout_marginBottom="584dp"
android:entries="@array/listview1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0" />
上面的屬性可以自由設定,重點是記得android:entries 這個屬性後面需放入上面你於String自己設定的array清單 @array/listview1 ,這樣執行後,便可在視圖中,看到你建立的listview

最後,若要於專案裡,使用listview,你可以引入listview後,利用setOnItemClickListener的方法監聽,如下:
package com.example.listview;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;

public class MainActivity extends AppCompatActivity {
private ListView listview;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listview=findViewById(R.id.listview);

//設定監聽listview時,進行以下的項目
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
//adapterView 元件,指Listview ,view指該元件視圖,i為點選的為第幾個項目,l指被點擊項目的id
Log.v("acao", String.valueOf(i)); //i為你選的第幾項
Log.v("acao",adapterView.getItemAtPosition(i).toString()); //adapterView.getItemAtPosition(i)為listview中i項的文字內容

}
});
}
}

(二)使用用法二(自製用法)
ListView若透過adapter(調變器)的控制可以有更多的變化,簡單的變化可以透過ArrayAdapter、SimpleCursorAdapter、SimpleAdapter這些類別,如果要有自定的視圖,可以透過繼承BaseAdapter這個類別,使用的方法如下:
(1)製作一個xml,這個xml與activity_main.xml不同,activity_main.xml是為了整個畫面規劃,而現在的xml,只為了自製ListView這個部份。在下面建立了一個名為mylistview.xml的檔案,裡面設定兩個textView顯示要呈現的資料。
。<?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:background="#DEF8FF">

<LinearLayout
android:id="@+id/myxml"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dp">

<TextView
android:id="@+id/mytext1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2"
android:text="TextView"
android:textColor="@android:color/black"
android:textSize="20sp" />

<TextView
android:id="@+id/mytext2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="TextView"
android:textColor="@android:color/black"
android:textSize="20sp" />

</LinearLayout>
</LinearLayout>

(2)製作一個繼承BaseAdapter 的adapter,這個adapter會有getCount()、getItem(int i)、getItemId(int i)、getView(int i, View view, ViewGroup viewGroup)四個方法。





2022年3月13日 星期日

android studio:canvas

Canvas為畫布,可以透過設定paint畫筆在上作畫。

要創建一個canvas ,自定義view時, 將要畫的圖寫在onDraw、dispatchDraw方法中,如下:

public class Myview extends View {

public Myview(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//在此方法中繪圖
Paint paint = new Paint(); //新建一個畫筆
paint.setStrokeWidth(3); //設定畫筆的寬度為3
canvas.drawLine(50, 50, 200, 200, paint); //drawLine為繪製一條線

}
}


另在xml 引入myveiw的視圖,這樣可以在畫面中出現了。

<com.example.canvas2.Myview
android:id="@+id/myview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button" />


如果需要調整可以用findViewById(R.id.myview)於程式中,進行調整。

以下為canvas 畫各種形狀的範例及參數說明

canvas.drawLine(50, 50, 200, 200, paint); //drawLine為繪製一條線 參數為(第一點x軸,第一點y軸,第二點x軸,第二點y軸,畫筆)
paint.setTextSize(50); //文字大小
canvas.drawText("你是來搞笑的麼!!!", 300, 300, paint); //打字 參數為(x軸,y軸)
canvas.drawCircle(500,500,200,paint); //畫圓 參數為(x軸,y軸,半徑長,畫筆)
//canvas.drawRect(600,600,800,800,paint); //方形
canvas.drawOval(200,400,600,900,paint); //繪製橢圓

//繪製路徑
Path path = new Path(); //新建路徑
path.moveTo(200f, 200f); //第一點X、Y軸
path.lineTo(400f, 200f); //第二點X、Y軸
path.lineTo(400f, 400f); //第三點X、Y軸
path.close();
canvas.drawPath(path, paint); //繪製路徑

canvas.drawPoint(800,800,paint); //繪製點 參數為(x軸,y軸)
canvas.drawRoundRect(900,900,1200,1200,20,20,paint); //圓角矩形

paint.setStyle(Paint.Style.FILL); // 畫筆為填充模式
//參數說明drawArc(float left, float top, float right, float bottom, 起始角度, 繪製範圍, 是否連結圓心, 畫筆內容)
canvas.drawArc(100, 100, 700, 400, -110, 100, true, paint); // 繪製扇形圖形
canvas.drawArc(100, 100, 700, 400, 20, 140, false, paint); // 繪制弧形圖形
paint.setStyle(Paint.Style.STROKE); // 畫筆為線段
canvas.drawArc(100, 100, 700, 400, 180, 60, false, paint); // 繪製不封口的弧形


參考網址:

https://www.twblogs.net/a/5b87691a2b71775d1cd6fd0d?lang=zh-cn

2022年3月11日 星期五

android studio:AsyncTesk

AsyncTask是一種不屬於主線的執行緒,目的在於提供簡單易用的方式來達成Handler+Thread的功能,因為它已經有寫好了的方法,因此在使用上會比自己重新寫Handler和Thread較為方便,比較適合進行短時間的執行緒工作。使用方法如下:

(一)建立一個內部或外部類別Thread繼承至AsyncTask這個thread,AsyncTask要定義的參數為<Params,Progress,Result>,第一個參數Params 為啟動任務時要傳入的資料類型,第二個參數為Progress為背景活動的進度類型,而第三個參數為Result類型為執行返回的結果。如果沒有要傳入,可用Void,如AsyncTask<Void, Void, Void>。

如下:

class mythread extends AsyncTask<String , Integer , Bitmap>{ }
(二)修改AsyncTask預設的方法中的內容,方法依序有onPreExecute doInBackground
onProgressUpdate onPostExecute等等的內容,如果沒有用到可以不修改。

(1)onPreExecute為執行AsyncTask背景活動前要做的事。

(2)doInBackground中的程式為你希望在背景默默執行的工作。其中的參數String... params為一陣列清單,params[0]可取出第一個參數值,其餘依此類推。此處的內容只在背景執行,因此不要在此處直接更新主執行序的介面。

(3)onProgressUpdate 在背景程式時,要手動呼叫的活動。如果要背景執行時,持續的更新主執行緒的數據,像是 執行進度條,又或是時間倒數等資訊,就可以將程式放在此處。其中的參數Integer... values也是陣列清單,values[0]可取出第一個參數值,其餘依此類推。

(4)onPostExecute 此處為進行完,你要執行的背景活動後,要執行的程式活動。


 
import androidx.appcompat.app.AppCompatActivity;

import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;

import java.net.URL;

public class MainActivity extends AppCompatActivity {

private ImageView imageView; //宣告imageview準備放圖片的地方
private ProgressBar pgBar; //宣告進度表
private Button button; //宣告button,點選後開啟



@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView=findViewById(R.id.imageView); //從xml取得imageview
pgBar=findViewById(R.id.pgbar); //從xml中取得progressbar
button=findViewById(R.id.button); //從xml中取得button

button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mythread task = new mythread(MainActivity.this,pgBar,imageView); //宣告task為自己新建一個thread,其中的參數第一個為MainActivity,第二個為進度軸,第三個為imageview,把這三個參數傳入thread,以便控劉
task.execute("https://images.pexels.com/photos/11319741/pexels-photo-11319741.jpeg?cs=srgb&dl=pexels-mathilde-langevin-11319741.jpg&fm=jpg"); //讓thread啟動,參數為網路的圖片網址,targetSdkVersion27版本以上不能用http連接,要用https
}
});

}
//結束後,釋放資料
@Override
protected void onDestroy() {
super.onDestroy();

imageView.setImageBitmap(null);

}
}

//自己建立的thread執行緒,命名為mythread
class mythread extends AsyncTask<String , Integer , Bitmap>{
private ImageView imageView; // 宣告imageview,以對應主執行緒丟過來的imageview
private Context context;
private ProgressBar progressBar; // 宣告progressBar,以對應主執行緒丟過來的progressBar
private Object Integer;

//mythread的建構式,參數有context, progressBar, imageView
public mythread(Context context,ProgressBar progressBar,ImageView imageView) {
this.context = context; //將傳入的數值於類別的數值相互綁定
this.progressBar=progressBar;
this.imageView=imageView;
}


//在此設定執行執行緒前要做的設定
@Override
protected void onPreExecute() {
super.onPreExecute();
progressBar.setVisibility(View.VISIBLE); //進度表顯現
imageView.setVisibility(View.GONE); //於主畫面中隱藏imageview

//初始化進度條並設定樣式及顯示的資訊。

}

//執行序要跑的工作在此運作,params為執行任務
@Override
protected Bitmap doInBackground(String... params) {
int progress = 0;
publishProgress(0);
String urlStr = params[0];
try {
URL url = new URL(urlStr);
publishProgress(50);
//progressBar.setProgress(50);
Log.v("acao", "1");
return BitmapFactory.decodeStream(url.openConnection().getInputStream()); //將取得的bitmap檔return回去,於結果裡運用

} catch (Exception e) {
e.printStackTrace();
progressBar.setProgress(50);
Log.v("acao", "2");
//最後達到100%
return null;
}
}

@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressBar.setProgress(values[0]);
//在doInBackground中,若呼叫publishProgress的時候會在這裡告知使用者進度,配合progressBar.setProgress,可以控制進度條

}

@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);



imageView.setVisibility(View.VISIBLE); //當完成的時候,顯示imageview
progressBar.setVisibility(View.GONE); //當完成的時候,隱藏進度條

imageView.setImageBitmap(bitmap); //將讀取的bitmap放在imageview

//執行完的設定
}




(三)呼叫的方法是在主執行序執行,如果只是一次使用,可以使用:

new thread().execute;

如果說要多次使用,可用下列的方法。

mythread task = new mythread(要丟入的參數);

task.execute("https://images.pexels.com/photos/11319741/pexels-photo-11319741.jpeg?cs=srgb&dl=pexels-mathilde-langevin-11319741.jpg&fm=jpg");


補充:thread中是否給值,要看你於mythread裡的建構式,public mythread(Context context,ProgressBar progressBar,ImageView imageView),有沒有給予值,如上面例子就要給予三個值;而execute裡是否要有值,要看之前在AsyncTask<Void, Void, Void>中的設定,如果是Void就不用給值,而如果是有加入型態,就依你加入的型態給與適當的值。



參考網址:

http://aiur3908.blogspot.com/2015/06/android-asynctask.html

https://oldgrayduck.blogspot.com/2013/01/androidasynctask-thread.html

https://www.aiwalls.com/android軟體開發教學/15/2156.html

https://dotblogs.com.tw/hanktom/2016/01/26/191154

2022年3月10日 星期四

android studio:thread

Thread是所謂的執行緒,所謂的執行緒就是每個程式執行的整個過程,而主要的執行緒(UI Thread),就是主要執行的過程。在寫程式的時候,若把每件事都寫在主要的執行序上,那會使整個程式花很多的時間,而且android 執行超過五秒後,就可能產生ANR(Application Not Responding)的問題,導致程式錯誤,因此會在背景寫其它的執行緒,當這些執行完把資料完成後,就把檔案丟給主要的執行緒處理,又或者在背景寫其它的執行緒,等主要的執行緒丟資料給它,再進行處理。

(一)一次性執行緒寫法如下,這種寫法就是執行緒完成後,就結束了:

Thread thread1=new Thread(thread1); //宣告新建一個新的執行緒為thread1,而它要跑的工作為thread1

thread1.start(); //讓thread1這個執行緒開始運作


而我們將要執行的方法寫Runnable這個類別的方法中。


private Runnable thread1=new Runnable () {

        public void run() {      

            //要在背景運作的程式

        }

    };

(二)第二種thread會一直常駐,等待程式去召喚這個thread,而因為是常駐,因此不使用要用quit關閉這個執行序。

myThread = new HandlerThread("handerThread");

//建立一個名為handerThread的新的Thread執行緒

myThread.start(); //讓myThread這個執行緒開始運作

myThreadHandler =new Handler(myThread.getLooper()); 

//handler是一個消息的控制器,在此可以發送與處理訊息。給這個執行序,一個控制器HandlerThread為getlooper,所以它會持續運作。


myThreadHandler.post(threa1); ///請控制器去執行threal這個工作


private Runnable thread1=new Runnable () {

        public void run() {      

            //要在背景運作的程式

        }

    };




補充:一般我們透過holder處理和發送主執行緒和副執行緒要溝通的訊息。而現在有一個更為簡便的方法,runOnUiThread( Runnable ),它可以把運作的程式放在Runnable中,然後在需要的時候ui,把這個Runnable對象傳給在主執行序中的runOnUiThread(Runnable)。因為要更新主執行緒的視圖,必須回到主執行緒中,而 runOnUiThread可放在主執行序中,如果執行時是在主執行緒中就立刻執行,若不是主執行序中,就排進副執行緒中,等待執行。實作runOnUiThread的寫法如下:

runOnUiThread(new Runnable() { void run() { // 要運作的程式 } });