1.Service 向Activity發送廣播,更新UI
一個小的案例,簡單的模擬的耗時工作,但是思路確實很常用的。
一個按鈕,一個textview,實現textview一秒更新一次。拓展方向實現了暫停和繼續。
在android中的主線程也就是UI線程,UI線程中纔可以操作界面元素。在主線程中執行耗時操作,會造成UI阻塞,導致ANR;在非主線程中更新UI,會直接報錯。
點擊按鈕,開啓一個服務,然後在service中進行耗時的操作,每隔一秒用廣播發送到activity中。service中開啓的線程是不能更新UI的,所以就需要service通過廣播發送數據到activity,然後activity取出數據,進行ui的更新。
後來我自己又想實現暫停和繼續,一開始,覺得應該暫停服務,在重新開啓服務,這樣不合適,後來就像將線程暫停和繼續執行就可以了。
我通過activity中的按鈕,向service中發送廣播,在service中接收到廣播,然後執行相應的暫停和繼續操作。
首先,我想到的是wait()和notifyAll()方法。所以,我直接調用了wait()方法,報錯了。錯誤信息:
<p>AndroidRuntime(2329): java.lang.IllegalMonitorStateException: object not locked by thread before wait()</p>
字面意思就能看出,在調用wait()前需要鎖定locked。
所以,在調用wait()和notifyAll()前,需要先synchronized鎖定,類似於下面這種
syncronized(this) { //把wait代碼放在synchronized塊中,鎖線程自己
wait(1000); //鎖一定的時間,要不然沒有notify就一直wait了
}
因爲,wait()針對的不是Thread/Runnable,而是針對的對象。
假設某個Object lock = new Object();
線程1(比如消費者線程)調用lock.wait()方法後,線程1就停下,直到其他某個線程(比如生產者線程)調用了lock.notify()或者lock.notifyAll();喚醒一個或者多個等待lock被喚醒的線程(此例中的線程1)。
調用wait之前,需要對lock同步synchronized (lock) {...}
private String control = "";
然後在synchronized中使用。這個control本身並沒有意義,只是隨便一個對象而已,因爲wait()和notify()之前,需要鎖定對象,而他們又必須保證是同一個對象,所以就隨便找了一個對象,保持一致性。否則就會報錯。
直接上代碼
MainActivity.java
package com.example.servicesendreceivertoactivity;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
public Button button;
public TextView textView;
public Intent serviceIntent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
textView = (TextView) findViewById(R.id.textView);
// 靜態註冊廣播,過濾"niejianjian"這個廣播
IntentFilter filter = new IntentFilter();
filter.addAction("niejianjian");
registerReceiver(njjReceiver, filter);
serviceIntent = new Intent(getApplicationContext(), MyService.class);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (button.getText().toString().equals("開始計時")) {
button.setText("暫停計時");
// 開啓服務
startService(serviceIntent);
} else if (button.getText().toString().equals("暫停計時")) {
button.setText("繼續計時");
// 向service發送暫停的廣播
Intent intent = new Intent();
intent.setAction("niejianjian.pause");
sendBroadcast(intent);
} else {
button.setText("暫停計時");
// 向service發送繼續的廣播
Intent intent1 = new Intent();
intent1.setAction("niejianjian.resume");
sendBroadcast(intent1);
}
}
});
}
BroadcastReceiver njjReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// 獲得接受到的數字,並進行設置
int count = intent.getIntExtra("Count", 0);
textView.setText("當前時間是: " + count);
}
};
}
MyService.java
package com.example.servicesendreceivertoactivity;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service {
int count = 0;
IntentFilter filter;
MyThread myThread;
Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case 1:
myThread.setSuspend(true);
break;
case 2:
myThread.setSuspend(false);
break;
default:
break;
}
};
};
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
// 初始化線程,並且start開啓線程
myThread = new MyThread();
myThread.start();
// 設置需要過濾的廣播,並註冊
filter = new IntentFilter();
filter.addAction("niejianjian.pause");
filter.addAction("niejianjian.resume");
registerReceiver(serReceiver, filter);
}
public BroadcastReceiver serReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String actionStr = intent.getAction();
if (actionStr.equals("niejianjian.pause")) {
handler.sendEmptyMessage(1);
} else if (actionStr.equals("niejianjian.resume")) {
handler.sendEmptyMessage(2);
}
}
};
public class MyThread extends Thread {
private boolean suspend = false;
private String control = ""; // 只是需要一個對象而已,這個對象沒有實際意義
public void setSuspend(boolean suspend) {
if (!suspend) {
synchronized (control) {
control.notifyAll();
}
}
this.suspend = suspend;
}
public boolean isSuspend() {
return this.suspend;
}
@Override
public void run() {
super.run();
while (true) {
synchronized (control) {
if (suspend) {
try {
control.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 執行發送廣播,傳遞count,實現計時的模塊,每秒發送一次
*/
count++;
Intent intent = new Intent();
intent.setAction("niejianjian");
intent.putExtra("Count", count);
sendBroadcast(intent);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 這個方法只是用來單純的實現計時,並不能實現暫停功能
*/
public Thread myThread11 = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
count++;
Intent intent = new Intent();
intent.setAction("niejianjian");
intent.putExtra("Count", count);
sendBroadcast(intent);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
activity_main.xml
<RelativeLayout 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="${relativePackage}.${activityClass}" >
<Button
android:id="@+id/button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="開始計時" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="jishi"
android:textSize="30sp" />
</RelativeLayout>
AndroidManifest.xml中註冊一下服務
<service android:name="com.example.servicesendreceivertoactivity.MyService" >
</service>
service的特點:
沒有用戶界面,
比activity的優先級高,不會請輕易的被android系統終止
即使service被系統終止,在系統資源恢復後,service也能自動回覆運行狀態
可用於IPC,解決兩個不通的android應用程序之間的調用和通信問題。
2.多進程模式
android對單個應用所使用的最大內存做了限制,可以利用多進程模式增大一個應用可使用的內存。
android中使用多進程的方法:
1).給四大組件在AndroidManifest.xml中指定android:process屬性。
2).非常規方法:通過JNI在native層去fork一個新的進程。
下面是個簡單的案例:<activity
android:name="com.example.processtestdemo.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.example.processtestdemo.SecondActivity"
android:process=":njj"
android:label="@string/app_name" >
</activity>
<activity
android:name="com.example.processtestdemo.ThridActivity"
android:process="com.example.njj"
android:label="@string/app_name" >
</activity>
3個activity,並通過android:process屬性來指定他們的進程。當activity啓動的時候,就會創建相應的進程。
分別啓動之後,可以通過DDMS查看
也可以在cmd中查看 abd shell ——> adb shell ps | grep com.example 後面 | 之後的屬於過濾信息,可以不加。
我們的SecondActivity和ThridActivity的android:process屬性的值分別是“:njj” 和”com.example.njj“。
首先,”:“有特殊的含義,它是值當前的進程名前面加上當前的包名,這是一個簡寫的方法。對於ThridActivity的寫法來說,是一種完整的命名方式。
其次,”:“開頭的進程屬於當前應用的私有進程,其他應用的組件不可以和它泡在同一個進程中,而不是以”:“開頭的進程屬於全局的進程,其他應用可以通過ShareUID方式和它跑在同一個進程中。
UID:Android系統會給每個應用分配一個唯一的UID,具有相同的UID的應用,才能共享數據。兩個應用通過ShareUID跑在同一個進程中是有要求的,需要這兩個應用有相同的ShareUID和簽名相同纔可以。
多進程模式也會遇到一些問題,例如我們隨便新建一個Contance.java類,其中有一個public靜態變量
public class Contance {
public static int tes = 1;
}
在MainAcitity中將Contance.tes修改爲2,打印出這個值後再跳轉到SecondActivity中再打印一遍tes的值,會發現,在SecondActivity中仍然爲1,也就是修改沒有生效。但是如果把SecondAcitity清單文件中的process刪除掉,就會打印出修改後的值。這就是多進程之間存在的一些問題。
上面的SecondActivity運行在一個單獨的進程中。Android爲每一個應用分配一個獨立的虛擬機,或者說爲每個進程分配一個獨立的虛擬機,不同的的虛擬機在內存分配上佔用不同的地址控件,這就導致不同的進程訪問同一個類的對象會產生多分副本。簡單的說就是自己處理好自己的事。
一般來說,使用多進程會造成如下的幾個方面的問題:
1) 靜態成員和單例模式完全失效
2) 線程同步機制完全失效
3) SharedPreferences的可靠性下降
4) Application會多次創建
第一個已經分析過了,對於第二個問題類似,既然已經不是同一塊內存了,那麼不管是鎖對象還是鎖全局類都無法保證線程同步,因爲不同進程鎖的不是同一個對象。第三個問題,SharedPreferences不支持兩個進程同時去執行寫操作,會有一定的機率數據導致數據丟失。第四個問題就是一個組件跑在一個新的進程中,由於系統要創建新的進程同時分配獨立的虛擬機,所以這個過程就相當於啓動一個應用的過程。
運行在同一個進程中的組件屬於同一個虛擬機和同一個Application的,然後添加自己的Application來測試:
package com.example.processtestdemo;
import android.app.ActivityManager;
import android.app.Application;
import android.content.Context;
public class MyApplication extends Application {
String processName = null;
@Override
public void onCreate() {
super.onCreate();
getProcessName();
System.out.println("application start , process name = " + processName);
}
public String getProcessName() {
ActivityManager am = (ActivityManager) getApplicationContext()
.getSystemService(Context.ACTIVITY_SERVICE);
int myPid = android.os.Process.myPid();
for (ActivityManager.RunningAppProcessInfo runningPro : am
.getRunningAppProcesses()) {
if (runningPro.pid == myPid) {
processName = runningPro.processName;
}
}
return processName;
}
}
然後在清單文件的application中添加name屬性
android:name="MyApplication"
分別點開三個Activity,打印如下log:
11-25 07:25:09.319: I/System.out(1272): application start , process name = com.example.processtestdemo
11-25 07:25:11.743: I/System.out(1288): application start , process name = com.example.processtestdemo:njj
11-25 07:25:13.775: I/System.out(1305): application start , process name = com.example.njj
根據log我們可以看出,不同的進程,分別創建一次Application。3.類似於android通訊錄的搜索功能,自動提示,快速定位
案例是有一個數據庫文件,有幾千個單詞,每個都包含中文和英文。
1).當輸入ab的時候,會自動提示全部以ab開頭的單詞,羅列出來。
2).還有就是,當輸入ab的時候,會自動定位到以ab開頭的第一個item。
資源下載:http://download.csdn.net/detail/u012975370/9367132
上部分代碼:
MainActivity.java:
package com.example.autocompleteedittext;
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.CursorAdapter;
import android.widget.TextView;
public class MainActivity extends Activity implements TextWatcher {
private AutoCompleteTextView auto_text;
private Util util;
public SQLiteDatabase database;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
util = new Util();
// 加載數據庫的數據,放入本地。增加讀取速度
util.initList(MainActivity.this);
database = util.getDatabase(MainActivity.this);
auto_text = (AutoCompleteTextView) findViewById(R.id.auto_text);
auto_text.addTextChangedListener(this);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, TwoActivity.class);
startActivity(intent);
}
});
}
public class MyAdapter extends CursorAdapter {
@Override
public CharSequence convertToString(Cursor cursor) {
return cursor == null ? "" : cursor.getString(cursor
.getColumnIndex("_id"));
}
public MyAdapter(Context context, Cursor c, boolean autoRequery) {
super(context, c, autoRequery);
}
private void setView(View view, Cursor cursor) {
TextView tView = (TextView) view;
tView.setText(cursor.getString(cursor.getColumnIndex("_id")));
tView.setTextSize(18);
tView.setPadding(15, 10, 10, 15);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = new TextView(MainActivity.this);
setView(view, cursor);
return view;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
setView(view, cursor);
}
}
@Override
public void afterTextChanged(Editable s) {
Cursor cursor;
// 獲取輸入的內容的byte數
byte[] bytes = s.toString().getBytes();
int m = bytes.length;
// 輸入內容的長度
int n = s.length();
if (m == n) { // 輸入的是英文字母
cursor = database.rawQuery(
"select english as _id from engtoch where english like ?",
new String[] { s.toString() + "%" });
} else { // 輸入的中文
cursor = database.rawQuery(
"select chinese as _id from t_words where chinese like ?",
new String[] { s.toString() + "%" });
}
MyAdapter myAdapter = new MyAdapter(MainActivity.this, cursor, true);
auto_text.setAdapter(myAdapter);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
}
TwoActivity.java:
package com.example.autocompleteedittext;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Base64;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
public class TwoActivity extends Activity {
ListView listView;
EditText editText;
WordListAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_two);
listView = (ListView) findViewById(R.id.listView);
adapter = new WordListAdapter(TwoActivity.this, Contance.list);
System.out.println("list.size" + Contance.list.size());
listView.setAdapter(adapter);
editText = (EditText) findViewById(R.id.editText);
editText.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void afterTextChanged(Editable s) {
int topPosition = 0;
for (int i = 0; i < Contance.list.size(); i++) {
WordBean words = Contance.list.get(i);
// 判斷有沒有那個字符串是以輸入的內容開頭的
if (words.getEnglish().startsWith(
editText.getText().toString())) {
topPosition = i;
break;
}
}
// 將列表移動到指定的position處
listView.setSelection(topPosition);
adapter.notifyDataSetInvalidated();
}
});
}
public class WordListAdapter extends BaseAdapter {
Context mContext;
List<WordBean> mList = new ArrayList<WordBean>();
LayoutInflater inflater;
public WordListAdapter(Context context, List<WordBean> list) {
this.mContext = context;
this.mList = list;
inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return mList.size();
}
@Override
public Object getItem(int position) {
return mList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.wordslist_item, null);
holder.chinese = (TextView) convertView
.findViewById(R.id.tv_chinese);
holder.english = (TextView) convertView
.findViewById(R.id.tv_english);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.chinese.setText(mList.get(position).getChinese());
holder.english.setText(mList.get(position).getEnglish());
return convertView;
}
}
class ViewHolder {
TextView english;
TextView chinese;
}
}
Util.java:
package com.example.autocompleteedittext;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
public class Util {
public void initList(final Context context) {
new Thread(new Runnable() {
@Override
public void run() {
Contance.list = getList(context);
System.out.println("list.size = " + Contance.list.size());
}
}).start();
}
public List<WordBean> getList(Context context) {
List<WordBean> list = new ArrayList<WordBean>();
Cursor cursor = getDatabase(context).rawQuery("select * from engtoch",
null);
cursor.moveToFirst();
int i = 0;
while (cursor.moveToNext()) {
System.out.println("move = " + i++);
String english = cursor.getString(cursor.getColumnIndex("english"));
String chinese = cursor.getString(cursor.getColumnIndex("chinese"));
WordBean word = new WordBean();
if (!(english == null) && !(chinese == null)) {
word.setEnglish(english);
word.setChinese(chinese);
list.add(word);
}
}
// while (!(cursor.getPosition() > 3785)) {
// System.out.println("move = " + i++);
// String english = cursor.getString(cursor.getColumnIndex("english"));
// String chinese = cursor.getString(cursor.getColumnIndex("chinese"));
//
// WordBean word = new WordBean();
// word.setEnglish(english);
// word.setChinese(chinese);
// list.add(word);
//
// cursor.moveToNext();
// }
return list;
}
/**
* 獲得一個SQLiteDatabase對象
*/
public SQLiteDatabase getDatabase(Context context) {
// 文件的絕對路徑
String dbFilePath = Contance.DATABASE_PATH + "/"
+ Contance.DATABASE_NAME;
/*
* 從raw文件夾下複製到sd下
*/
try {
File file = new File(Contance.DATABASE_PATH);
if (!file.exists()) {
file.mkdirs();
}
File file2 = new File(file, Contance.DATABASE_NAME);
if (!file2.exists()) {
file2.createNewFile();
}
// 獲得封裝dictionary.db文件的InputStream對象
InputStream iStream = context.getResources().openRawResource(
R.raw.dictionary);
FileOutputStream fos = new FileOutputStream(dbFilePath);
byte[] buff = new byte[8192];
int count = 0;
while ((count = iStream.read(buff)) != -1) {
fos.write(buff, 0, count);
}
fos.close();
iStream.close();
} catch (IOException e) {
e.printStackTrace();
}
// 打開數據庫文件
SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(
dbFilePath, null);
return database;
}
}
package com.example.autocompleteedittext;
import java.util.List;
import android.os.Environment;
public class Contance {
public static List<WordBean> list;
public final static String DATABASE_NAME = "dictionary.db";
public final static String DATABASE_PATH = Environment
.getExternalStorageDirectory().getAbsolutePath() + "/dictionary";
}
WordsBean.java:
package com.example.autocompleteedittext;
public class WordBean {
private String english;
private String chinese;
public WordBean() {
}
public WordBean(String english, String chinese) {
this.english = english;
this.chinese = english;
}
public String getEnglish() {
return english;
}
public void setEnglish(String english) {
this.english = english;
}
public String getChinese() {
return chinese;
}
public void setChinese(String chinese) {
this.chinese = chinese;
}
}
4.Activity之間傳遞ArrayList
傳遞的MainActivity.java
package com.example.activity_arraylist;
import java.util.ArrayList;
import java.util.Iterator;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Serializable 傳遞
Button button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
ArrayList<MyClass> arrayList = new ArrayList<MyClass>();
for (int i = 0; i < 10; i++) {
MyClass myClass = new MyClass();
myClass.userName = "a->" + i;
myClass.psw = "b->" + i;
myClass.age = 20 + i;
arrayList.add(myClass);
}
Intent intent = new Intent();
intent.putExtra("key", arrayList);
intent.setClass(MainActivity.this, ResultActivity.class);
startActivity(intent);
}
});
// Parcelable 傳遞
Button button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
ArrayList<MyClass2> arrayList = new ArrayList<MyClass2>();
for (int i = 0; i < 10; i++) {
MyClass2 myClass2 = new MyClass2();
myClass2.userName = "a->" + i;
myClass2.psw = "b->" + i;
myClass2.age = 20 + i;
arrayList.add(myClass2);
}
Intent intent = new Intent();
intent.putExtra("key", arrayList);
intent.setClass(MainActivity.this, ResultActivity2.class);
startActivity(intent);
}
});
}
}
1).使用Serializable方法
將類的實例序列化然後再做存儲或者傳輸在JAVA中較爲常見。
a.一個自定義類,實現了Serialization接口。
import java.io.Serializable;
public class MyClass implements Serializable {
private static final long serialVersionUID = 1L;
public String userName;
public String psw;
public int age;
}
b.接受的ResultActivity.java
public class ResultActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.result_main);
ArrayList<MyClass> arrayList = (ArrayList<MyClass>) getIntent()
.getSerializableExtra("key");
String result = "";
for (MyClass myClass : arrayList) {
result += (myClass.userName + "--" + myClass.psw + "--"
+ myClass.age + "\n");
}
TextView textView = (TextView) findViewById(R.id.textview);
textView.setText(result);
}
}
2).使用Parcelable方法
Android內存受限,迫使其封裝了Parcel容器來代替Serializale方法
a.一個自定義類,實現了Parcelable接口
package com.example.activity_arraylist;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Parcel類:封裝數據的容器,封裝後的數據可以通過intent或者IPC傳遞
* Parcelable接口:自定義類繼承該接口後,其實例化後能夠被寫入Paecel或從Parcel中恢復
* 如果某個類實現了該接口,那麼它的對象實例可以寫入Parcel中,並且能夠從中恢復,並且這個類必須要有一個static的feld,
* 並且名稱要爲CREATOR,這個field是某個實現了Parcelable.Creator接口類的對象實例。
*/
public class MyClass2 implements Parcelable {
public String userName;
public String psw;
public int age;
// 靜態的Parcelable.Creator接口
public static final Parcelable.Creator<MyClass2> CREATOR = new Creator<MyClass2>() {
// 創建出類的實例,並從Parcel中獲取數據進行實例化
@Override
public MyClass2 createFromParcel(Parcel source) {
MyClass2 myClass2 = new MyClass2();
myClass2.userName = source.readString();
myClass2.psw = source.readString();
myClass2.age = source.readInt();
return myClass2;
}
@Override
public MyClass2[] newArray(int size) {
return new MyClass2[size];
}
};
@Override
public int describeContents() {
return 0;
}
// 將數據寫入外部提供的Parcel中
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(userName);
dest.writeString(psw);
dest.writeInt(age);
}
}
b.接受的ResultActivity2.java
package com.example.activity_arraylist;
import java.util.ArrayList;
import java.util.Iterator;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class ResultActivity2 extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.result_main);
ArrayList<MyClass2> arrayList = (ArrayList<MyClass2>) getIntent()
.getSerializableExtra("key");
String result = "";
for (MyClass2 myClass2 : arrayList) {
result += (myClass2.userName + "---" + myClass2.psw + "---"
+ myClass2.age + "\n");
}
TextView textView = (TextView) findViewById(R.id.textview);
textView.setText(result);
}
}
5.自定義View
自定義View的步驟:
1.自定義View屬性。
2.在View的構造方法中獲取我們自定義的屬性
3.重寫onMeasure方法(非必須)
4.重寫onDraw。
1.自定義View屬性。首先在res/values下建立一個attrs.xml文件,在裏面定義我們的屬性和聲明我們的整個樣式。
1.<?xml version="1.0" encoding="utf-8"?>
2.<resources>
3.
4. <attr name="titleText" format="string" />
5. <attr name="titleTextColor" format="color" />
6. <attr name="titleTextSize" format="dimension" />
7.
8. <declare-styleable name="CustomTitleView">
9. <attr name="titleText" />
10. <attr name="titleTextColor" />
11. <attr name="titleTextSize" />
12. </declare-styleable>
13.
14.</resources>
我們定義了字體、字體顏色、字體大小。Format是該屬性的屬性值。
自定義View的步驟:
1.自定義一個CustomView(extends View)類
2.編寫values/attrs.xml,在其中編寫styleable和item等標籤元素
3.在佈局文件中customView使用自定義的屬性(注意namespace)
4.在CustomView的構造方法中通過TypedArray獲取。
http://blog.csdn.net/jdsjlzx/article/details/43452927
http://www.androidchina.net/2192.html
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:njjcustom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.jian.myapplication.CustomViewNjj
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:padding="10dp"
njjcustom:titleText="3712"
njjcustom:titleTextColor1="#2635ff"
njjcustom:titleTextSize="50sp" />
</RelativeLayout>
CustomViewNjj.java
package com.example.jian.myapplication;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import java.lang.reflect.Array;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
/**
* 如果系統中已經有了語義比較明確的屬性,我們還可以引用嗎(比如njj:text和android:text)。
* 可以。直接在attrs.xml中使用android:text屬性。<attr name="android:text" />
* 使用已經定義好的屬性,不需要去添加format屬性。(聲明和使用的差別就是有沒有format)
* 然後在類中這麼獲取:ta.getString(R.styleable.test_android_text);
* 佈局文件中直接android:text="@string/hello_world"即可。
* <p/>
* 參考文章:http://www.androidchina.net/2192.html
*/
public class CustomViewNjj extends View {
private static final String TAG = "NieJianJian_Log";
private String mTitleText;
private int mTitleTextColor;
private int mTitleTextSize;
private Rect mBound;
private Paint mPaint;
/**
* 如果三個構造函數都是super,就是報錯nullPointerException。
* 如果都是this,直接就編譯過不了。
* 必須是前兩個this,實現的super。
* this表示當前的view對象,也就是CustomViewNjj這個對象,this表示調用它的構造方法,一個參數調兩個參數,
* 兩個參數調三個參數,直到實現的地方調用super,重新父類view的方法。
* 如果三個都是this,那麼就沒有重寫父類的方法,直接報錯。
* 如果三個都寫super,那麼調用一個參數的構造參數的時候,就已經重寫了父類view的方法,可是卻沒有具體的實現,
* 此時就會報空指針的錯誤。
* (以上是我的個人總結)
* 不過好像三個構造函數都是super,只要每個構造函數中都有實現的方法,不至於是沒有初始化,導致空指針就好。
*/
/**
* public View (Context context)是在java代碼創建視圖的時候被調用,如果是從xml填充的視圖,就不會調用這個
* public View (Context context, AttributeSet attrs)這個是在xml創建但是沒有指定style的時候被調用
* public View (Context context, AttributeSet attrs, int defStyle)是指定style之後調用的
*/
/**
* 其實,從源碼來看,兩個參數的構造函數中,沒有做任何處理,只是調用了this(context, attrs, 0);
* 三個參數的構造函數中,第一句話就是 this(context);然後後面有做了一堆處理。
* 然後在一個參數的構造函數中,將context傳遞給了全局使用的mContext,用於全局使用
*
* @param context
*/
public CustomViewNjj(Context context) {
this(context, null);
Log.i(TAG, "one params");
}
public CustomViewNjj(Context context, AttributeSet attrs) {
this(context, attrs, 0);
Log.i(TAG, "two params");
// TypedArray ta1 = context.obtainStyledAttributes(attrs, R.styleable.CustomView);
}
/**
* 在有三個參數的構造函數中才能執行下列操作
*/
public CustomViewNjj(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
Log.i(TAG, "threee params");
TypedArray ta = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.CustomView, defStyleAttr, 0);
int n = ta.getIndexCount();
for (int i = 0; i < n; i++) {
int attr = ta.getIndex(i);
switch (attr) {
case R.styleable.CustomView_titleText:
mTitleText = ta.getString(attr);
break;
case R.styleable.CustomView_titleTextColor1:
mTitleTextColor = ta.getColor(attr, Color.BLACK);
break;
case R.styleable.CustomView_titleTextSize:
mTitleTextSize = ta.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));
break;
}
}
/**
* 下面的for循環只是爲了打印參數信息,不做任何實際用處
* 獲得的是CustomViewNjj所有屬性,包括自定義和非自定義的。
* 比如:njjcustom:titleText="@string/hello_world"
* 獲得的結果就是:attrName = titleText , attrVal = @2131099670
* 通過AttributeSet獲得是id,如果引用了更深一層,就無法直接解析了。
* 所以這時就要用TypedArray,它簡化了這個過程。
*/
int count = attrs.getAttributeCount();
for (int i = 0; i < count; i++) {
String attrName = attrs.getAttributeName(i);
String attrVal = attrs.getAttributeValue(i);
//Log.i("NieJianJian", "attrName = " + attrName + " , attrVal = " + attrVal);
}
ta.recycle();
mPaint = new Paint();
mPaint.setTextSize(mTitleTextSize);
mBound = new Rect();
mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound);
this.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
mTitleText = randomText();
postInvalidate();
}
});
}
private String randomText() {
Random random = new Random();
Set<Integer> set = new HashSet<Integer>();
while (set.size() < 4) {
int randomInt = random.nextInt(10);
set.add(randomInt);
}
StringBuilder builder = new StringBuilder();
for (Integer i : set) {
builder.append("" + i);
}
return builder.toString();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // 測量大小的方法
Log.i(TAG, "onMeasure");
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
/*
* EXACYTLY 一般是設置了明確的值或者是MATH_PARENT
* AT_MOST 表示子佈局限制在一個最大值內,一般爲WARP_PARENT
* UNSPECIFIED 表示子佈局想要多大就多大,很少使用
*/
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
} else {
width = getPaddingLeft() + getPaddingRight() + mBound.width();
}
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else {
height = getPaddingTop() + getPaddingBottom() + mBound.height();
}
setMeasuredDimension(width, height);
}
@Override
protected void onDraw(Canvas canvas) { // 繪製的方法
Log.i(TAG, "onDraw");
super.onDraw(canvas);
mPaint.setColor(Color.YELLOW);
// 繪製一個矩形
canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);
mPaint.setColor(mTitleTextColor); // 字體顏色
canvas.drawText(mTitleText, getWidth() / 2 - mBound.width() / 2,
getHeight() / 2 + mBound.height() / 2, mPaint);
}
}
/**
* 繪製VIew本身的內容,通過調用View.onDraw(canvas)函數實現
* 繪製自己的孩子通過dispatchDraw(canvas)實現
*/
/**
* View組件的繪製會調用draw(Canvas canvas)方法,draw過程中主要是先畫Drawable背景,
* 對 drawable調用setBounds()然後是draw(Canvas c)方法.
* 有點注意的是背景drawable的實際大小會影響view組件的大小,
* drawable的實際大小通過getIntrinsicWidth()和getIntrinsicHeight()獲取,
* 當背景比較大時view組件大小等於背景drawable的大小。
* 畫完背景後,draw過程會調用onDraw(Canvas canvas)方法,
* 然後就是dispatchDraw(Canvas canvas)方法, dispatchDraw()主要是分發給子組件進行繪製,
* 我們通常定製組件的時候重寫的是onDraw()方法。值得注意的是ViewGroup容器組件的繪製,
* 當它沒有背景時直接調用的是dispatchDraw()方法, 而繞過了draw()方法,當它有背景的時候就調用draw()方法,
* 而draw()方法裏包含了dispatchDraw()方法的調用。
* 因此要在ViewGroup上繪製東西的時候往往重寫的是dispatchDraw()方法而不是onDraw()方法,
* 或者自定製一個Drawable,重寫它的draw(Canvas c)和 getIntrinsicWidth(),getIntrinsicHeight()方法,
* 然後設爲背景。
*/
/**
* 執行順序是這樣onMeasure -> onLayout -> onMeasure -> onLayout -> draw -> onDraw -> dispatchDraw
*/
6.RxJava的使用
RxJava,RxAndroid,順便使用Java 8的Lambda表達式。使用的開發工具是Android Studio。
針對上面,BDAuction是一個Project,也就是一個項目,對應的app是一個module,一個project中可以有多個module。
每一個module中都有一個build.gradle,整個project只有一個build.gradle。
1).配置RxJava和RxAndroid
我們要使用,首先添加依賴,
在app module節點下的build.gradle文件中,dependencies中添加以下內容,
<pre style="font-family: Consolas; font-size: 12pt; background-color: rgb(199, 237, 204);">compile <span style="color:#008000;"><strong>'io.reactivex:rxandroid:1.0.1'
</strong></span>compile <span style="color:#008000;"><strong>'io.reactivex:rxjava:1.0.14'</strong></span>
然後Sync Now將gradle同步一下就可以了。
也可以在File -> Project Structure ->
選擇app,Dependencies,加號,選擇Library Dependency,然後在搜索框中輸入
io.reactivex:rxandroid:1.0.1
找到後點擊Ok就可以了。rxandroid添加完了,rxjava同理。
關於rx的就添加完了
2).lambda配置
lambda是java8的新特性,首先,得保證java版本,之後在配置。
第一步:在Project節點下的build.gradle中的dependencies中添加
classpath 'me.tatarka:gradle-retrolambda:3.2.4'
第二步:在app Module節點下的build.gradle中根節點中添加
apply plugin: 'me.tatarka.retrolambda'
第二步必須在第一步前面,順序不能點到,否則報錯第三步:在app Module節點下的build.gradle文件的androdi結點下,添加如下內容
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
到此爲止,lambda就配置完了7.播放Gif圖
GitHub框架地址:https://github.com/felipecsl/GifImageView
首先需要添加依賴
compile 'com.felipecsl:gifimageview:2.0.0'
佈局文件:
<?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">
<com.felipecsl.gifimageview.library.GifImageView
android:id="@+id/gifImageView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Activity
package com.example.administrator.rx_test;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.Button;
import android.widget.Toast;
import com.felipecsl.gifimageview.library.GifImageView;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
/**
* Created by Administrator on 2016/3/30.
*/
public class ThirdActivity extends Activity {
public GifImageView gifView;
public InputStream is = null;
public byte[] buffer = null;
static MyHandler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_third);
gifView = (GifImageView) findViewById(R.id.gifImageView);
handler = new MyHandler(this);
handler.sendEmptyMessage(0);
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onDestroy() {
super.onDestroy();
gifView.stopAnimation();
}
class MyHandler extends Handler {
Context mContext;
public MyHandler(Context context) {
this.mContext = context;
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
try {
is = getAssets().open("intro.gif");
int size = is.available();
buffer = new byte[size];
is.read(buffer);
is.close();
gifView.setBytes(buffer);
gifView.startAnimation();
} catch (Exception e) {
}
}
}
}
就是這麼簡單,項目框架的部分是從網上加載的gif圖,如果放在本地的話,就用流讀取成bytes,然後傳遞給getBytes就可以了。
8.AnimatorSet和ObjectAnimator製作引導界面動畫
下載地址:http://download.csdn.net/detail/u012975370/9482290
這兩張gif圖動畫只播放一次,速度比較快,要快速查看才行。這只是其中的一兩個界面。
其中的遠點是一直動的,周圍放大,透明度降低,一直循環,提示點擊。
其實可以查看ObjectAnimator和AnimatorSet的原碼,就知道有那些方法了,字面意思就可以看個大概,然後嘗試下,就能知道效果是什麼了。
佈局文件Activity_splash.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/introBtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:text="introPage" />
<ViewStub
android:id="@+id/intro_vs"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout="@layout/layout_intro" />
</RelativeLayout>
SplashActivity.java
package com.example.administrator.rx_test;
import android.app.Activity;
import android.os.Bundle;
import android.view.ViewStub;
import android.view.animation.AnimationSet;
import android.widget.Button;
/**
* Created by Administrator on 2016/3/31.
*/
public class SplashActivity extends Activity {
private Button introBtn;
private ViewStub intro_vs;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
intro_vs = (ViewStub) findViewById(R.id.intro_vs);
introBtn = (Button) findViewById(R.id.introBtn);
introBtn.setOnClickListener(v -> showIntro());
}
private void showIntro() {
UserInfoView userInfoView = (UserInfoView) intro_vs.inflate();
}
}
UserInfoView.java
package com.example.administrator.rx_test;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AnimationSet;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.Toast;
/**
* Created by Administrator on 2016/3/31.
*/
public class UserInfoView extends FrameLayout {
View intro0;
View intro1;
View intro2;
View intro3;
View intro4;
View intro5;
View intro6;
View intro7;
AnimatorSet set = new AnimatorSet();
public UserInfoView(Context context) {
this(context, null);
}
public UserInfoView(Context context, AttributeSet attrs) {
// 必須是this,不能是super
this(context, attrs, 0);
// super(context, attrs, 0);
}
public UserInfoView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
inflate(context, R.layout.intro_view_detail, this);
initView();
intBtn();
}
private void initView() {
intro0 = findViewById(R.id.view_intro_0);
intro1 = findViewById(R.id.view_intro_1);
intro2 = findViewById(R.id.view_intro_2);
intro3 = findViewById(R.id.view_intro_3);
intro4 = findViewById(R.id.view_intro_4);
intro5 = findViewById(R.id.view_intro_5);
intro6 = findViewById(R.id.view_intro_6);
intro7 = findViewById(R.id.view_intro_7);
((Button) findViewById(R.id.intro7_btn)).setOnClickListener(v -> Toast.makeText(getContext(), "aa", Toast.LENGTH_LONG).show());
}
private void intBtn() {
initClick(R.id.intro0_btn, intro1);
initClick(R.id.intro1_btn, intro2);
initClick(R.id.intro2_btn, intro3);
initClick(R.id.intro3_btn, intro4);
initClick(R.id.intro4_btn, intro5);
initClick(R.id.intro5_btn, intro6);
initClick(R.id.intro6_btn, intro7);
}
private void initClick(int id, View view) {
((Button) findViewById(id)).setOnClickListener(v -> {
view.bringToFront();
// if (set.isRunning()) {
// set.end();
// }
startAnime(view);
});
}
private void startAnime(View view) {
int id = view.getId();
switch (id) {
case R.id.view_intro_1:
intro1Anime();
break;
case R.id.view_intro_2:
intro2Anime();
break;
case R.id.view_intro_3:
intro3Anime();
break;
case R.id.view_intro_4:
intro4Anime();
break;
case R.id.view_intro_5:
intro5Anime();
break;
case R.id.view_intro_6:
intro6Anime();
break;
case R.id.view_intro_7:
intro7Anime();
break;
}
}
private void startPointAnime(View vBtn, long delay) {
// 透明動畫
ObjectAnimator alpha = ObjectAnimator.ofFloat(vBtn, "alpha",
1.0f, 0.8f, 0.6f, 0.4f, 0.2f, 0.0f);
alpha.setRepeatCount(ValueAnimator.INFINITE);
alpha.setRepeatMode(ValueAnimator.RESTART);
// 縮放動畫
ObjectAnimator scaleX = ObjectAnimator.ofFloat(vBtn, "scaleX", 1.0f, 1.2f, 1.4f, 1.5f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(vBtn, "scaleY", 1.0f, 1.2f, 1.4f, 1.5f);
scaleX.setRepeatCount(ValueAnimator.INFINITE);
scaleX.setRepeatMode(ValueAnimator.RESTART);
scaleY.setRepeatCount(ValueAnimator.INFINITE);
scaleY.setRepeatMode(ValueAnimator.RESTART);
set.setDuration(1000);
set.playTogether(alpha, scaleX, scaleY);
set.setStartDelay(delay);
set.start();
}
private void startViewAnime(View view, long delay, float... values) {
ObjectAnimator anime = ObjectAnimator.ofFloat(view, "alpha", values).setDuration(300);
anime.setStartDelay(delay);
anime.start();
}
private void intro1Anime() {
ImageView intro_1_1 = (ImageView) findViewById(R.id.intro_1_1);
ImageView intro_1_2 = (ImageView) findViewById(R.id.intro_1_2);
ImageView intro_1_3 = (ImageView) findViewById(R.id.intro_1_3);
ImageView intro_1_black = (ImageView) findViewById(R.id.intro_1_black);
Button intro1_btn = (Button) findViewById(R.id.intro1_btn);
startViewAnime(intro_1_black, 200, 0, 1);
startViewAnime(intro_1_2, 300, 0, 1);
startViewAnime(intro_1_3, 500, 0, 1);
startViewAnime(intro1_btn, 800, 0, 1);
startViewAnime(findViewById(R.id.intro1_btn_f), 800, 0, 1);
startPointAnime(intro1_btn, 1500);
}
private void intro2Anime() {
ImageView intro_2_2 = (ImageView) findViewById(R.id.intro_2_2);
ImageView intro_2_3 = (ImageView) findViewById(R.id.intro_2_3);
ImageView intro_2_4 = (ImageView) findViewById(R.id.intro_2_4);
ImageView intro_2_5 = (ImageView) findViewById(R.id.intro_2_5);
ImageView intro_2_black = (ImageView) findViewById(R.id.intro_2_black);
Button intro2_btn = (Button) findViewById(R.id.intro2_btn);
startViewAnime(intro_2_black, 200, 0, 1);
startViewAnime(intro_2_2, 300, 0, 1);
startViewAnime(intro_2_3, 400, 0, 1);
startViewAnime(intro_2_2, 2000, 1, 0);
startViewAnime(intro_2_3, 2000, 1, 0);
startViewAnime(intro_2_4, 2200, 0, 1);
startViewAnime(intro_2_5, 2500, 0, 1);
startViewAnime(intro2_btn, 2500, 0, 1);
startViewAnime(findViewById(R.id.intro2_btn_f), 2200, 0, 1);
startPointAnime(intro2_btn, 2800);
}
private void intro3Anime() {
ImageView intro_3_2 = (ImageView) findViewById(R.id.intro_3_2);
ImageView intro_3_3 = (ImageView) findViewById(R.id.intro_3_3);
ImageView intro_3_4 = (ImageView) findViewById(R.id.intro_3_4);
Button intro3_btn = (Button) findViewById(R.id.intro3_btn);
ObjectAnimator anime1 = ObjectAnimator.ofFloat(intro_3_3, "translationY", -intro_3_2.getHeight())
.setDuration(300);
anime1.setStartDelay(100);
anime1.start();
startViewAnime(intro_3_4, 200, 0, 1);
startViewAnime(intro3_btn, 500, 0, 1);
startViewAnime(findViewById(R.id.intro3_btn_f), 500, 0, 1);
startPointAnime(intro3_btn, 800);
}
private void intro4Anime() {
ImageView intro_4_2 = (ImageView) findViewById(R.id.intro_4_2);
ImageView intro_4_3 = (ImageView) findViewById(R.id.intro_4_3);
ImageView intro_4_4 = (ImageView) findViewById(R.id.intro_4_4);
ImageView intro_4_5 = (ImageView) findViewById(R.id.intro_4_5);
ImageView intro_4_black = (ImageView) findViewById(R.id.intro_4_black);
Button intro4_btn = (Button) findViewById(R.id.intro4_btn);
startViewAnime(intro_4_black, 200, 0, 1);
startViewAnime(intro_4_2, 300, 0, 1);
startViewAnime(intro_4_3, 400, 0, 1);
startViewAnime(intro_4_2, 2000, 1, 0);
startViewAnime(intro_4_3, 2000, 1, 0);
startViewAnime(intro_4_4, 2200, 0, 1);
startViewAnime(intro_4_5, 2200, 0, 1);
startViewAnime(intro4_btn, 2500, 0, 1);
startViewAnime(findViewById(R.id.intro4_btn_f), 2500, 0, 1);
startPointAnime(intro4_btn, 2800);
}
private void intro5Anime() {
ImageView intro_5_2 = (ImageView) findViewById(R.id.intro_5_2);
ImageView intro_5_3 = (ImageView) findViewById(R.id.intro_5_3);
ImageView intro_5_black = (ImageView) findViewById(R.id.intro_5_black);
Button intro5_btn = (Button) findViewById(R.id.intro5_btn);
startViewAnime(intro_5_black, 200, 0, 1);
startViewAnime(intro_5_2, 300, 0, 1);
startViewAnime(intro_5_3, 400, 0, 1);
startViewAnime(intro5_btn, 700, 0, 1);
startViewAnime(findViewById(R.id.intro5_btn_f), 700, 0, 1);
startPointAnime(intro5_btn, 1000);
}
private void intro6Anime() {
ImageView intro_6_2 = (ImageView) findViewById(R.id.intro_6_2);
ImageView intro_6_3 = (ImageView) findViewById(R.id.intro_6_3);
Button intro6_btn = (Button) findViewById(R.id.intro6_btn);
startViewAnime(intro_6_2, 200, 0, 1);
startViewAnime(intro_6_3, 300, 0, 1);
startViewAnime(intro6_btn, 600, 0, 1);
startViewAnime(findViewById(R.id.intro6_btn_f), 600, 0, 1);
startPointAnime(intro6_btn, 900);
}
private void intro7Anime() {
ImageView intro_7_2 = (ImageView) findViewById(R.id.intro_7_2);
ImageView intro_7_3 = (ImageView) findViewById(R.id.intro_7_3);
ImageView intro_7_4 = (ImageView) findViewById(R.id.intro_7_4);
Button intro7_btn = (Button) findViewById(R.id.intro7_btn);
ImageView intro_7_black = (ImageView) findViewById(R.id.intro_7_black);
startViewAnime(intro_7_black, 200, 0, 1);
startViewAnime(intro_7_2, 300, 0, 1);
startViewAnime(intro_7_3, 400, 0, 1);
startViewAnime(intro_7_2, 2000, 1, 0);
startViewAnime(intro_7_3, 2000, 1, 0);
startViewAnime(intro_7_4, 2300, 0, 1);
startViewAnime(intro7_btn, 2300, 0, 1);
}
}
intro_view_detail.xml文件
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="@+id/view_intro_7"
layout="@layout/view_intro_7"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<include
android:id="@+id/view_intro_6"
layout="@layout/view_intro_6"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<include
android:id="@+id/view_intro_5"
layout="@layout/view_intro_5"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<include
android:id="@+id/view_intro_4"
layout="@layout/view_intro_4"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<include
android:id="@+id/view_intro_3"
layout="@layout/view_intro_3"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<include
android:id="@+id/view_intro_2"
layout="@layout/view_intro_2"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<include
android:id="@+id/view_intro_1"
layout="@layout/view_intro_1"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<include
android:id="@+id/view_intro_0"
layout="@layout/view_intro_0"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</merge>
每一個界面的顯示代碼,就不貼了,有興趣的可以去下載看看:http://download.csdn.net/detail/u012975370/94822909.簡單的回調
public class MainActivity extends Activity {
Button1 mButton1;
Button mButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton1 = new Button1();
mButton1.setOnClickListener1(new OnClickListener1() {
@Override
public void onClick() {
Log.i("niejianjian"," -> 1");
Toast.makeText(getApplicationContext(), "click", Toast.LENGTH_LONG).show();
}
});
mButton = (Button) findViewById(R.id.showBtn);
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i("niejianjian"," -> 2");
mButton1.click();
}
});
}
}
interface OnClickListener1 {
public void onClick();
}
class Button1 {
OnClickListener1 mListener1;
public void click() {
Log.i("niejianjian"," -> 3");
mListener1.onClick();
}
public void setOnClickListener1(OnClickListener1 listener1) {
Log.i("niejianjian"," -> 4");
this.mListener1 = listener1;
}
}
10.簡單的自定義進度條
效果圖
CircleProgressView類
package com.example.jian.myapplication;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
/**
* Created by jian on 2016/9/20.
*/
public class CircleProgressView extends View {
private int mMeasureHeight;
private int mMeasureWidth;
private Paint mCirclePaint;
private float mCircleXY;
private float mRadius;
private Paint mArcPaint;
private RectF mArcRectF;
private float mSweepAngle;
private float mSweepValue = 66;
private Paint mTextPaint;
private String mShowText;
private float mShowTextSize;
public CircleProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CircleProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mMeasureWidth = MeasureSpec.getSize(widthMeasureSpec);
mMeasureHeight = MeasureSpec.getSize(heightMeasureSpec);
// 設定測量出的大小
setMeasuredDimension(mMeasureWidth, mMeasureHeight);
initViews();
}
private void initViews() {
float length = 0;
if (mMeasureWidth > mMeasureHeight) {
length = mMeasureHeight;
} else {
length = mMeasureWidth;
}
mCircleXY = length / 2;
mRadius = (float) (length * 0.5 / 2);
mCirclePaint = new Paint();
// 抗鋸齒
mCirclePaint.setAntiAlias(true);
mCirclePaint.setColor(getResources().getColor(android.R.color.holo_blue_bright));
mArcRectF = new RectF(
(float) (length * 0.1),
(float) (length * 0.1),
(float) (length * 0.9),
(float) (length * 0.9)
);
// 獲取繪畫的角度值
mSweepAngle = (mSweepValue / 100f) * 360f;
mArcPaint = new Paint();
mArcPaint.setAntiAlias(true);
mArcPaint.setColor(getResources().getColor(android.R.color.holo_blue_bright));
// 實心寬度
mArcPaint.setStrokeWidth((float) (length * 0.1));
mArcPaint.setStyle(Paint.Style.STROKE);
mShowText = setShowText();
mShowTextSize = setShowTextSize();
mTextPaint = new Paint();
mTextPaint.setTextSize(mShowTextSize);
mTextPaint.setTextAlign(Paint.Align.CENTER);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 繪製圓
canvas.drawCircle(mCircleXY, mCircleXY, mRadius, mCirclePaint);
// 繪製弧線(扇形)
canvas.drawArc(mArcRectF, 270, mSweepAngle, false, mArcPaint);
// 繪製文字
canvas.drawText(mShowText, 0, mShowText.length(), mCircleXY, mCircleXY + (mShowTextSize / 4), mTextPaint);
}
private float setShowTextSize() {
this.invalidate();
return 100;
}
private String setShowText() {
this.invalidate();
return "Android Skill";
}
public void setSweepValue(float sweepValue) {
if (sweepValue != 0) {
mSweepValue = sweepValue;
} else {
mSweepValue = 25;
}
this.invalidate();
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.jian.myapplication.CircleProgressView
android:id="@+id/circle"
android:layout_width="match_parent"
android:layout_height="match_parent"/>/>
</RelativeLayout>
MainActivity
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CircleProgressView circleProgressView = (CircleProgressView) findViewById(R.id.circle);
circleProgressView.setSweepValue(66);
}
}
11.ListView的使用技巧
簡單的listview以及常用到的相關方法
MainActivity
package com.example.jian.myapplication;
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import com.example.jian.myapplication.listview.ViewHolderApdater;
import java.util.ArrayList;
import java.util.List;
/**
* Created by jian on 2016/9/19.
*/
public class MainActivity extends Activity {
ListView mListView;
private List<String> data = new ArrayList<String>();
private ViewHolderApdater mAdapter;
private int lastVisibleImtePosition;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = (ListView) findViewById(R.id.listview);
getData();
mAdapter = new ViewHolderApdater(this, data);
mListView.setAdapter(mAdapter);
// 設置第一個選中的item,其實類似於scrollTo
// mListView.setSelection(0);
// 設置滾動條在左邊
// mListView.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_LEFT);
// 設置空view
// mListView.setEmptyView(new View(this)); // 傳入一個view對象參數
mListView.setOnTouchListener(new MyOnTouchListener());
mListView.setOnItemClickListener(new MyOnItemClickListener());
mListView.setOnScrollListener(new MyOnScrollListener());
mListView.getFirstVisiblePosition();
mListView.getLastVisiblePosition();
}
/*遍歷listView的的子view*/
public void getListViewItem() {
for (int i = 0; i < mListView.getChildCount(); i++) {
View view = mListView.getChildAt(i);
}
}
private List<String> getData() {
for (int i = 0; i < 20; i++) {
data.add("第 " + i + " 個");
}
return data;
}
class MyOnScrollListener implements AbsListView.OnScrollListener {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:
// 滑動時停止
break;
case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
// 正在滾動
break;
case AbsListView.OnScrollListener.SCROLL_STATE_FLING:
// 手指拋動時,即用手指滑動
// 在離開後ListView由於慣性繼續滑動
break;
}
}
/**
* @param view
* @param firstVisibleItem // 當前顯示的第一個item的position
* @param visibleItemCount // 當前屏幕總共顯示的item的個數
* @param totalItemCount // listview的總數
*/
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
// 滾動時一直調用
if (firstVisibleItem + visibleItemCount == totalItemCount && totalItemCount > 0) {
// 說明滾動到了最後一行
}
if (firstVisibleItem > lastVisibleImtePosition) {
// 上滑
} else if (firstVisibleItem < lastVisibleImtePosition) {
// 下滑
}
lastVisibleImtePosition = firstVisibleItem;
}
}
class MyOnItemClickListener implements AdapterView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(MainActivity.this, " " + position, Toast.LENGTH_SHORT).show();
if (position == 5) {
data.add("第 " + (data.size()) + " 個");
mAdapter.notifyDataSetChanged();
}
if (position == 6) {
data.remove(data.size() - 1);
mAdapter.notifyDataSetChanged();
}
if (position == 7) {
// 移動的距離,offset = 2,就是向下移動兩個item的距離,如果offset = -2,那就是向上移動兩個item的距離
// mListView.smoothScrollByOffset(-2);
// 移動到固定的位置,和setSelection一樣
// mListView.smoothScrollToPosition(1);
// 雙擊 distance是移動的像素數,duration是動畫時間
// mListView.smoothScrollBy(500, 1000);
}
}
}
class MyOnTouchListener implements View.OnTouchListener {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 觸摸時操作
break;
case MotionEvent.ACTION_MOVE:
// 移動時操作
break;
case MotionEvent.ACTION_UP:
// 離開時操作
break;
}
return false;
}
}
}
ViewHolderAdapter
package com.example.jian.myapplication.listview;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.jian.myapplication.R;
import java.util.List;
/**
* Created by jian on 2016/9/21.
*/
public class ViewHolderApdater extends BaseAdapter {
private List<String> mData;
private LayoutInflater mLayoutInflater;
public ViewHolderApdater(Context context, List<String> data) {
this.mData = data;
mLayoutInflater = LayoutInflater.from(context);
// mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
return mData.size();
}
@Override
public Object getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = mLayoutInflater.inflate(R.layout.list_item, null);
holder.img = (ImageView) convertView.findViewById(R.id.imageView);
holder.title = (TextView) convertView.findViewById(R.id.textView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.img.setBackgroundResource(R.drawable.ic_launcher);
holder.title.setText(mData.get(position));
return convertView;
}
public final class ViewHolder {
public ImageView img;
public TextView title;
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:dividerHeight="10dp"
android:paddingLeft="20dp"/>
<!--android:divider="@null"--> <!--設置無滾動條-->
<!--android:divider="@android:color/darker_gray"--> <!--設置滾動條顏色-->
<!--android:listSelector="#00000000"
android:listSelector="@android:color/transparent"--> <!--取消點擊效果-->
</RelativeLayout>
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@+id/imageView"/>
</RelativeLayout>
具有彈性的ListView
CustomListView
package com.example.jian.myapplication.listview;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.widget.ListView;
/**
* Created by jian on 2016/9/22.
*/
public class CustomListView extends ListView {
Context mContext;
private static int mMaxOverDistance = 50;
public CustomListView(Context context) {
super(context);
this.mContext = context;
initView();
}
public CustomListView(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
initView();
}
public CustomListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.mContext = context;
initView();
}
private void initView() {
DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
float density = metrics.density;
mMaxOverDistance = (int) (density * mMaxOverDistance);
}
@Override
protected boolean overScrollBy(int deltaX, int deltaY,
int scrollX, int scrollY,
int scrollRangeX, int scrollRangeY,
int maxOverScrollX, int maxOverScrollY,
boolean isTouchEvent) {
return super.overScrollBy(deltaX, deltaY, scrollX, scrollY,
scrollRangeX, scrollRangeY, maxOverScrollX,
mMaxOverDistance, isTouchEvent);
}
}
MainActivity
package com.example.jian.myapplication;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import com.example.jian.myapplication.listview.CustomListView;
/**
* Created by jian on 2016/9/22.
*/
public class MainActivity extends Activity {
CustomListView mCustomListView;
private String[] data = new String[30];
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCustomListView = (CustomListView) findViewById(R.id.listview);
for (int i = 0; i < 30; i++) {
data[i] = "" + i;
}
mCustomListView.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, data));
}
}
帶顯示隱藏ToolBar的ListView
ScrollHideListView
package com.example.jian.myapplication.listview;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.AbsListView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.example.jian.myapplication.R;
/**
* Created by jian on 2016/9/22.
*/
public class ScrollHideListView extends Activity {
private Toolbar mToolbar;
private ListView mListView;
private String[] mStr = new String[20];
private int mTouchSlop;
private float mFirstY;
private float mCurrentY;
private int direction;
private ObjectAnimator mAnimator;
private boolean mShow = true;
View.OnTouchListener myTouchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mFirstY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
mCurrentY = event.getY();
if (mCurrentY - mFirstY > mTouchSlop) {
direction = 0;// down
} else if (mFirstY - mCurrentY > mTouchSlop) {
direction = 1;// up
}
if (direction == 1) {
if (mShow) {
toolbarAnim(1);//show
mShow = !mShow;
}
} else if (direction == 0) {
if (!mShow) {
toolbarAnim(0);//hide
mShow = !mShow;
}
}
break;
case MotionEvent.ACTION_UP:
break;
}
return false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.scroll_hide);
// 系統認爲的最低滑動距離
mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
mToolbar = (Toolbar) findViewById(R.id.toolbar);
mListView = (ListView) findViewById(R.id.listview);
for (int i = 0; i < mStr.length; i++) {
mStr[i] = "Item " + i;
}
View header = new View(this);
header.setLayoutParams(new AbsListView.LayoutParams(
AbsListView.LayoutParams.MATCH_PARENT,
(int) getResources().getDimension(
R.dimen.abc_action_bar_default_height_material)));
// 防止toolbar擋住listview,給listview添加一個header
mListView.addHeaderView(header);
mListView.setAdapter(new ArrayAdapter<String>(
ScrollHideListView.this,
android.R.layout.simple_expandable_list_item_1,
mStr));
mListView.setOnTouchListener(myTouchListener);
}
private void toolbarAnim(int flag) {
if (mAnimator != null && mAnimator.isRunning()) {
mAnimator.cancel();
}
if (flag == 0) {
mAnimator = ObjectAnimator.ofFloat(mToolbar,
"translationY", mToolbar.getTranslationY(), 0);
} else {
mAnimator = ObjectAnimator.ofFloat(mToolbar,
"translationY", mToolbar.getTranslationY(),
-mToolbar.getHeight());
}
mAnimator.start();
}
}
scroll_hdie.xml
<RelativeLayout 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=".listview.ScrollHideListView">
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:headerDividersEnabled="false"/>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@android:color/holo_blue_light"/>
</RelativeLayout>
聊天ListView
兩種佈局,聊天單條內容背景採用的是.9圖片,因爲拉伸不失真。
chat_item_itemout.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:gravity="center_vertical|right"
android:orientation="horizontal"
android:padding="10dp">
<TextView
android:id="@+id/text_out"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/chatitem_out_bg"
android:gravity="center"
android:textSize="20sp" />
<ImageView
android:id="@+id/icon_out"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" />
</LinearLayout>
chat_item_itemin.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:gravity="center_vertical"
android:orientation="horizontal"
android:padding="10dp">
<ImageView
android:id="@+id/icon_in"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" />
<TextView
android:id="@+id/text_in"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/chatitem_in_bg"
android:gravity="center"
android:textSize="20sp" />
</LinearLayout>
ChatItemAdapter.java
package com.example.jian.myapplication.listview;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.jian.myapplication.R;
import java.util.List;
/**
* Created by jian on 2016/9/23.
*/
public class ChatItemAdapter extends BaseAdapter {
private List<ChatItemBean> mData;
private LayoutInflater mInflater;
Context mContext;
public ChatItemAdapter(Context context, List<ChatItemBean> data) {
this.mData = data;
this.mContext = context;
mInflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return mData.size();
}
@Override
public Object getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
/**
* 返回第position個item是何種類型
*/
@Override
public int getItemViewType(int position) {
ChatItemBean bean = mData.get(position);
return bean.getType();
}
/**
* 返回不同佈局的總數,就是有幾種佈局
*/
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
if (getItemViewType(position) == 0) {
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.chat_item_itemin, null);
holder.text = (TextView) convertView.findViewById(R.id.text_in);
holder.icon = (ImageView) convertView.findViewById(R.id.icon_in);
} else {
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.chat_item_itemout, null);
holder.text = (TextView) convertView.findViewById(R.id.text_out);
holder.icon = (ImageView) convertView.findViewById(R.id.icon_out);
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.icon.setImageBitmap(BitmapFactory.decodeResource(
mContext.getResources(), (getItemViewType(position) == 0) ?
R.drawable.in_icon : R.drawable.ic_launcher));
holder.text.setText(mData.get(position).getText());
return convertView;
}
public final class ViewHolder {
public TextView text;
public ImageView icon;
}
}
ChatItemBean.java
package com.example.jian.myapplication.listview;
import android.graphics.Bitmap;
/**
* Created by jian on 2016/9/23.
*/
public class ChatItemBean {
private int type;
private String text;
private Bitmap icon;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Bitmap getIcon() {
return icon;
}
public void setIcon(Bitmap icon) {
this.icon = icon;
}
}
MainActivity.java
package com.example.jian.myapplication;
import android.app.Activity;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.widget.ListView;
import com.example.jian.myapplication.listview.ChatItemAdapter;
import com.example.jian.myapplication.listview.ChatItemBean;
import java.util.ArrayList;
import java.util.List;
/**
* Created by jian on 2016/9/22.
*/
public class MainActivity extends Activity {
private ListView mListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = (ListView) findViewById(R.id.listview);
mListView.setAdapter(new ChatItemAdapter(this, getData()));
}
private List<ChatItemBean> getData() {
ChatItemBean bean1 = new ChatItemBean();
bean1.setType(0);
bean1.setText("Hello, How are you?");
bean1.setIcon(BitmapFactory.decodeResource(getResources(), R.drawable.in_icon));
ChatItemBean bean2 = new ChatItemBean();
bean2.setType(0);
bean2.setText("Fine thank you,and you?");
bean2.setIcon(BitmapFactory.decodeResource(getResources(), R.drawable.in_icon));
ChatItemBean bean3 = new ChatItemBean();
bean3.setType(1);
bean3.setText("I'm fine too");
bean3.setIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher));
ChatItemBean bean4 = new ChatItemBean();
bean4.setType(0);
bean4.setText("bye");
bean4.setIcon(BitmapFactory.decodeResource(getResources(), R.drawable.in_icon));
ChatItemBean bean5 = new ChatItemBean();
bean5.setType(1);
bean5.setText("now,I will go back");
bean5.setIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher));
ChatItemBean bean6 = new ChatItemBean();
bean6.setType(1);
bean6.setText("ok, bye");
bean6.setIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher));
ChatItemBean bean7 = new ChatItemBean();
bean7.setType(0);
bean7.setText("bye bye");
bean7.setIcon(BitmapFactory.decodeResource(getResources(), R.drawable.in_icon));
List<ChatItemBean> data = new ArrayList<>();
data.add(bean1);
data.add(bean2);
data.add(bean3);
data.add(bean4);
data.add(bean5);
data.add(bean6);
data.add(bean7);
return data;
}
}
activity_main.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="vertical">
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@null"
android:listSelector="@android:color/transparent"/>
</LinearLayout>
12.自定義屬性的複合控件
自定義屬性attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TopBar">
<attr name="title" format="string"/>
<attr name="titleTextSize" format="dimension"/>
<attr name="titleTextColor" format="color"/>
<attr name="leftTextColor" format="color"/>
<attr name="leftBackground" format="reference|color"/>
<attr name="leftText" format="string"/>
<attr name="rightTextColor" format="color"/>
<attr name="rightBackground" format="reference|color"/>
<attr name="rightText" format="string"/>
</declare-styleable>
</resources>
自定義View:TopBar.java
package com.example.jian.myapplication.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.example.jian.myapplication.R;
/**
* Created by jian on 2016/10/12.
*/
public class TopBar extends RelativeLayout {
private Button mLeftBtn, mRightBtn;
private TextView mTitleTv;
// 左按鈕的屬性值
private int mLeftTextColor;
private Drawable mLeftBackground;
private String mLeftText;
// 右按鈕的屬性值
private int mRightTextColor;
private Drawable mRightBackground;
private String mRightText;
// 標題的屬性值
private int mTitleTextColor;
private float mTitleTextSize;
private String mTitleText;
// 佈局屬性,用來控制組件元素在ViewGroup中的位置
private LayoutParams mLeftParams, mTitlepParams, mRightParams;
// 映射傳入的接口對象
private TopBarClickListener mListener;
public TopBar(Context context) {
super(context);
}
public TopBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public TopBar(Context context, AttributeSet attrs) {
super(context, attrs);
// 通過這個方法,將你在attrs.xml中定義的declare-styleable的所以屬性的值存儲到TypedArray中
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TopBar);
getAttrs(ta);
setAttrs(context);
setLayout();
setBtnClickListener();
}
/**
* 從TypedArray中取出對應的值,爲要設置的屬性賦值
*/
private void getAttrs(TypedArray ta) {
mLeftTextColor = ta.getColor(R.styleable.TopBar_leftTextColor, 0);
mLeftBackground = ta.getDrawable(R.styleable.TopBar_leftBackground);
mLeftText = ta.getString(R.styleable.TopBar_leftText);
mRightTextColor = ta.getColor(R.styleable.TopBar_rightTextColor, 0);
mRightBackground = ta.getDrawable(R.styleable.TopBar_rightBackground);
mRightText = ta.getString(R.styleable.TopBar_rightText);
mTitleTextColor = ta.getColor(R.styleable.TopBar_titleTextColor, 0);
mTitleTextSize = ta.getDimension(R.styleable.TopBar_titleTextSize, 10);
mTitleText = ta.getString(R.styleable.TopBar_title);
// 獲取完TypedArray的值後,一般要調用recyle方法來避免重新創建的時候的錯誤(資源回收)
ta.recycle();
}
/**
* 爲創建的組件元素賦值
*/
private void setAttrs(Context context) {
mLeftBtn = new Button(context);
mRightBtn = new Button(context);
mTitleTv = new TextView(context);
mLeftBtn.setText(mLeftText);
mLeftBtn.setBackground(mLeftBackground);
mLeftBtn.setTextColor(mLeftTextColor);
mRightBtn.setText(mRightText);
mRightBtn.setBackground(mRightBackground);
mRightBtn.setTextColor(mRightTextColor);
mTitleTv.setText(mTitleText);
mTitleTv.setTextSize(mTitleTextSize);
mTitleTv.setTextColor(mTitleTextColor);
}
/**
* 爲組件元素設置相應的佈局元素
*/
private void setLayout() {
mLeftParams = new LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.MATCH_PARENT);
mLeftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, TRUE);
// 添加到ViewGroup
addView(mLeftBtn, mLeftParams);
mRightParams = new LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.MATCH_PARENT);
mRightParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, TRUE);
// 添加到ViewGroup
addView(mRightBtn, mRightParams);
mTitlepParams = new LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.MATCH_PARENT);
mTitlepParams.addRule(RelativeLayout.CENTER_IN_PARENT, TRUE);
addView(mTitleTv, mTitlepParams);
}
/**
* 按鈕的點擊實現,不需要具體的實現,
* 只需要嗲用接口的方法,回調的時候,會有具體的實現
*/
private void setBtnClickListener() {
mRightBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mListener.rightClick();
}
});
mLeftBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mListener.leftClick();
}
});
}
/**
* 設置按鈕的顯示與否 通過id區分按鈕,flag區分是否顯示
*
* @param id id
* @param flag 是否顯示
*/
public void setButtonVisable(int id, boolean flag) {
if (flag) {
if (id == 0) {
mLeftBtn.setVisibility(View.VISIBLE);
} else {
mRightBtn.setVisibility(View.VISIBLE);
}
} else {
if (id == 0) {
mLeftBtn.setVisibility(View.GONE);
} else {
mRightBtn.setVisibility(View.GONE);
}
}
}
/**
* 接口對象,實現回調機制,在回調方法中,通過映射的接口對象調用接口中的方法,
* 而不用去考慮如何實現,具體的實現由調用者去創建
*/
public interface TopBarClickListener {
void leftClick();
void rightClick();
}
/**
* 暴露一個方法給調用者來註冊接口回調,通過接口來獲得回調這對接口方法的實現
*
* @param listener
*/
public void setOnTopBarClickListener(TopBarClickListener listener) {
this.mListener = listener;
}
}
MainActivity.java
package com.example.jian.myapplication;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;
import com.example.jian.myapplication.view.TopBar;
/**
* Created by jian on 2016/9/26.
*/
public class MainActivity extends Activity {
TopBar mTopBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_topbar);
mTopBar = (TopBar) findViewById(R.id.topbar);
mTopBar.setOnTopBarClickListener(new TopBar.TopBarClickListener() {
@Override
public void leftClick() {
Toast.makeText(MainActivity.this, "left", Toast.LENGTH_SHORT).show();
}
@Override
public void rightClick() {
Toast.makeText(MainActivity.this, "right", Toast.LENGTH_SHORT).show();
}
});
mTopBar.setButtonVisable(0,true);
mTopBar.setButtonVisable(1,true);
}
}
activity_topbar.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:topbar="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp">
<com.example.jian.myapplication.view.TopBar
android:id="@+id/topbar"
android:layout_width="match_parent"
android:layout_height="40dp"
topbar:leftBackground="@drawable/blue_button"
topbar:leftText="Back"
topbar:leftTextColor="#FFFFFF"
topbar:rightBackground="@drawable/blue_button"
topbar:rightText="More"
topbar:rightTextColor="#FFFFFF"
topbar:title="自定義標題"
topbar:titleTextColor="#123412"
topbar:titleTextSize="10sp"/>
</RelativeLayout>
blue_button.xml
<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="rectangle">
<!-- 填充的顏色 -->
<solid android:color="#33444444" />
</shape>
</item>
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<!-- 填充的顏色 -->
<solid android:color="#3EC5FF" />
</shape>
</item>
</selector>
13.TextSwitcher實現上下滾動廣告效果
xml文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextSwitcher
android:id="@+id/textSwitcher"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="50dp"
android:background="#e4e4e4"
android:inAnimation="@anim/push_up_in"
android:minHeight="48dp"
android:outAnimation="@anim/push_up_out"/>
</RelativeLayout>
MainActivity.java
package com.example.jian.myapplication;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextSwitcher;
import android.widget.TextView;
import android.widget.ViewSwitcher;
/**
* Created by jian on 2016/9/26.
*/
public class MainActivity extends Activity {
private TextSwitcher mTextSwitcher;
private BitHandler bitHandler;
private String[] strings = {"text00001", "text00002"};
private int index = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_textswitcher);
mTextSwitcher = (TextSwitcher) findViewById(R.id.textSwitcher);
mTextSwitcher.setFactory(new ViewSwitcher.ViewFactory() {
@Override
public View makeView() {
TextView textView = new TextView(MainActivity.this);
textView.setSingleLine();
textView.setTextSize(15);
textView.setTextColor(Color.parseColor("#ff0000"));
textView.setEllipsize(TextUtils.TruncateAt.END);
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT
);
lp.gravity = Gravity.CENTER;
textView.setLayoutParams(lp);
return textView;
}
});
bitHandler = new BitHandler();
bitHandler.sendEmptyMessage(0);
// new myThread().start();
}
class BitHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mTextSwitcher.setText(strings[index]);
index++;
if (index == strings.length) {
index = 0;
}
bitHandler.sendEmptyMessageDelayed(0, 2000);
}
}
private class myThread extends Thread {
@Override
public void run() {
super.run();
while (index < strings.length) {
try {
synchronized (this) {
bitHandler.sendEmptyMessage(0);
this.sleep(2000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
push_up_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false"
android:zAdjustment="top">
<translate
android:duration="400"
android:fromYDelta="100%"
android:toYDelta="0"/>
<alpha
android:duration="400"
android:fromAlpha="0.0"
android:toAlpha="1.0"/>
</set>
push_up_out.xml<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false"
android:zAdjustment="top">
<translate
android:duration="400"
android:fromYDelta="0"
android:toYDelta="-100%"/>
<alpha
android:duration="400"
android:fromAlpha="1.0"
android:toAlpha="0.0"/>
</set>
14.工廠模式模版
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AudiFactory factory = new AudiCarFactory();
AudiCar q5car = factory.createAudiCar(AudiQ5.class);
q5car.drive();
q5car.selfNavigation();
AudiQ7 q7car = factory.createAudiCar(AudiQ7.class);
q7car.drive();
q7car.selfNavigation();
}
}
public abstract class AudiFactory {
public abstract <T extends AudiCar> T createAudiCar(Class<T> clz);
}
public class AudiCarFactory extends AudiFactory {
@Override
public <T extends AudiCar> T createAudiCar(Class<T> clz) {
AudiCar car = null;
try {
car = (AudiCar) Class.forName(clz.getName()).newInstance();
// car = (AudiCar) clz.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (T) car;
}
}
public abstract class AudiCar {
public abstract void drive();
public abstract void selfNavigation();
}
public class AudiQ5 extends AudiCar {
@Override
public void drive() {
Log.i("niejianjian", " -> AudiQ5 -> drive");
}
@Override
public void selfNavigation() {
Log.i("niejianjian", " -> AudiQ5 -> selfNavigation");
}
}
public class AudiQ7 extends AudiCar {
@Override
public void drive() {
Log.i("niejianjian", " -> AudiQ7 -> drive");
}
@Override
public void selfNavigation() {
Log.i("niejianjian", " -> AudiQ7 -> selfNavigation");
}
}
15.小圓點ViewPager指示器
/**
* 小圓點 ViewPager 指示器
* Created by WangWei on 2015/10/14.
*/
public class CircleViewPagerIndicator extends LinearLayout implements ViewPager.OnPageChangeListener {
protected static final int NORMAL_INDICATOR = R.drawable.indicator_slide_show;
protected static final int HIGHLIGHT_INDICATOR = R.drawable.indicator_slideshow_checked;
protected ViewPager mViewPager;
public CircleViewPagerIndicator(Context context) {
this(context, null);
}
public CircleViewPagerIndicator(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CircleViewPagerIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
if (isInEditMode()) return;
setOrientation(HORIZONTAL);
setBackgroundColor(getResources().getColor(android.R.color.transparent));
setPadding(20, 20, 20, 20);
setGravity(Gravity.CENTER);
}
public final void setViewPager(final ViewPager slideShow) {
// Preconditions.checkNotNull(slideShow);
// Verify.verify(slideShow.getAdapter() != null, "viewPager adapter == null");
mViewPager = slideShow;
onSetViewPager(slideShow);
slideShow.addOnPageChangeListener(this);
}
protected void onSetViewPager(final ViewPager slideShow) {
removeAllViews();
/*只有一個就不顯示了*/
final int count = slideShow.getAdapter().getCount();
if (count == 1) return;
for (int index = 0; index < count; index++) {
addIndicator(index == slideShow.getCurrentItem());
}
}
protected final void addIndicator(boolean highlight) {
ImageView imageView = new ImageView(getContext());
imageView.setImageResource(highlight ? HIGHLIGHT_INDICATOR : NORMAL_INDICATOR);
LayoutParams params = new LayoutParams(16, 16);
params.rightMargin = 24;
addView(imageView, params);
}
@Override
public void onPageScrolled(int i, float v, int i2) {
}
@Override
public void onPageSelected(final int i) {
if (mViewPager == null) return;
final int count = getChildCount();
for (int index = 0; index < count; index++) {
final int indicator = index == i ? HIGHLIGHT_INDICATOR : NORMAL_INDICATOR;
final ImageView imageView = (ImageView) getChildAt(index);
imageView.setImageResource(indicator);
}
}
@Override
public void onPageScrollStateChanged(int i) {
}
}
indicator_slide_show和indicator_slideshow_checked 可以是兩個圓點圖片,也可以自己shape繪製兩個圓形的drawable。
使用的時候,將CircleViewPagerIndicator添加到佈局xml需要的位置,然後,在代碼中初始化後,只需要調用
mIndicator.setViewPager(mViewPager);
就可以和相關的viewpager綁定了。16.動態佈局切換
fragment切換,以及view切換兩種方式
package com.example.niejianjian.myapplication;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import com.example.niejianjian.myapplication.fragment.Fragment1;
import com.example.niejianjian.myapplication.fragment.Fragment2;
import com.example.niejianjian.myapplication.fragment.Fragment3;
/**
* Created by niejianjian on 2017/10/11.
*/
public class MyFragmentActicity extends FragmentActivity implements View.OnClickListener {
private Button mButton1, mButton2, mButton3;
private FragmentManager mFragmentManager;
private Fragment mFragment1, mFragment2, mFragment3;
private View mView1, mView2, mView3;
private FrameLayout mFrameLayout;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment);
mFrameLayout = (FrameLayout) findViewById(R.id.framelayout);
mButton1 = (Button) findViewById(R.id.btn1);
mButton2 = (Button) findViewById(R.id.btn2);
mButton3 = (Button) findViewById(R.id.btn3);
mButton1.setOnClickListener(this);
mButton2.setOnClickListener(this);
mButton3.setOnClickListener(this);
mFragment1 = new Fragment1();
mFragment2 = new Fragment2();
mFragment3 = new Fragment3();
mView1 = View.inflate(this, R.layout.fragment1, null);
mView2 = View.inflate(this, R.layout.fragment2, null);
mView3 = View.inflate(this, R.layout.fragment3, null);
mFragmentManager = getSupportFragmentManager();
// replaceFragment(mFragment1);
replaceView(mView1);
}
private void replaceFragment(Fragment fragment) {
FragmentTransaction transaction = mFragmentManager.beginTransaction();
transaction.replace(R.id.framelayout, fragment);
// transaction.addToBackStack(null);
transaction.commit();
}
private void replaceView(View view) {
mFrameLayout.removeAllViews();
mFrameLayout.addView(view);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn1:
// replaceFragment(mFragment1);
replaceView(mView1);
break;
case R.id.btn2:
// replaceFragment(mFragment2);
replaceView(mView2);
break;
case R.id.btn3:
// replaceFragment(mFragment3);
replaceView(mView3);
break;
}
}
}
<?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">
<LinearLayout
android:layout_width="120dp"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="fragment1"/>
<Button
android:id="@+id/btn2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="fragment2"/>
<Button
android:id="@+id/btn3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="fragment3"/>
</LinearLayout>
<FrameLayout
android:id="@+id/framelayout"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
Fragment1就是一個簡單的Fragment,將其複製,分別命名爲Fragment2,Fragment3.
public class Fragment1 extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment1, container, false);
}
}
<?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="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF0000"
android:gravity="center"
android:text="這是第一個fragment"/>
</LinearLayout>