今日林北心血來潮要來寫一個簡單的相簿軟體,功能包括
1. 小圖預覽
2. 大圖檢視
利用 HorizontalScrollView 實現小圖預覽
很久以前記得有個 Gallery 的元件可以用,但 Android 4.1 之後好像不再支援了,改用 HorizontalScrollView 這個元件
Class Overview: http://developer.android.com/reference/android/widget/HorizontalScrollView.html
HorizontalScrollView 是一個 view containter,讓 user 可以用滑動方式存取到肉眼看得到的更多元件,至少要放一個 child 到 HorizontalScrollView 中,通常為 LinearLayout,並自行管理內部的原件。
本文中在 HorizontalScrollView 中實作一個客製化的 LinearLayout,利用 Adapter 與 ImageSwitcher 進行互動。
利用 ImageSwitcher 實現大圖檢視
ImageSwitcher 是一個有動畫效果的圖片切換器
Class Overview: https://developer.android.com/reference/android/widget/ImageSwitcher.html
實作 ImageSwitcher 時,Activity 必須繼承 ViewFactory,並 override makeView() 方法,通過其創建 View,再將 View 添加到 ImageSwitcher 上
實作方式如下
首先在 main.xml 中宣告 HorizontalScrollView & ImageSwitcher :
<HorizontalScrollView android:id="@+id/hsview"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_weight="0"
android:scrollbars="none" >
<com.lotusgallery.lotus.lotusgallery.HSVLayout
android:id="@+id/movieLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</HorizontalScrollView>
<ImageSwitcher android:id="@+id/image_switcher"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginTop="20dp" />
再定義預覽圖片顯示的 Layout 如下: (hsv.xml)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<ImageView android:id="@+id/movie_image"
android:layout_width="wrap_content"
android:layout_height="400dp"
android:layout_alignParentBottom="true" />
</RelativeLayout>
可以發現在 HorizontalScrollView 中放了一個自定義的 HSLayout 元件,這是一個客製化的 LinearLayout,可想見之後會放很多預覽圖片進去讓使用者可快速瀏覽,因此實作了一個 setAdapter() 方法,以便動態餵圖片給這個 Layout 元件。當把 Adapter 指定給 HSLayout 元件之後,HSLayout 便可取得 Adapter 中儲存的所有小圖,將其加到自己的顯示介面中,並對每一張圖片實作 onClick(),當圖片被點下後就會發出 intent 給對應的人處理,此例中就是 ImageSwitcher 。
其實作方法如下:
public class HSVLayout extends LinearLayout {
private Context mContext;
public HSVLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
}
public void setAdapter(HSVAdapter adapter) {
for (int i = 0; i < adapter.getCount(); i++) {
final Map<String, Object> map = adapter.getItem(i);
View view = adapter.getView(i, null, null);
view.setPadding(10, 0, 10, 0);
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(AppConstant.UPDATE_IMAGE_ACTION);
intent.putExtra("index", (Integer) map.get("index"));
mContext.sendBroadcast(intent);
}
});
this.setOrientation(HORIZONTAL);
this.addView(view, new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
}
}
HSVAdapter 繼承自 BaseAdapter,管理一個 List 來保存所有的預覽圖,利用 addObject() 方法加入到其中,透過 HSVAdapter 可抓取到所有預覽圖的 View 元件。
實作如下:
public class HSVAdapter extends BaseAdapter {
private List<Map<String, Object>> mList;
private Context mContext;
public HSVAdapter(Context context) {
mContext = context;
mList = new ArrayList<Map<String, Object>>();
}
@Override
public int getCount() {
return mList.size();
}
@Override
public Map<String, Object> getItem(int location) {
return mList.get(location);
}
@Override
public long getItemId(int arg0) {
return arg0;
}
public void addObject(Map<String, Object> map) {
mList.add(map);
notifyDataSetChanged();
}
@Override
public View getView(int location, View arg1, ViewGroup arg2) {
View view = LayoutInflater.from(mContext).inflate(R.layout.hsv, null);
ImageView image = (ImageView) view.findViewById(R.id.movie_image);
Map<String, Object> map = getItem(location);
image.setBackgroundResource((Integer) map.get("image"));
return view;
}
}
幹你娘打好多字喔,休息一下
最後在 MainActivity 的部分,為了實作 ImageSwitcher,必須去繼承 ViewFactory 並複寫 makeView 方法:
public class MainActivity extends ActionBarActivity implements ViewSwitcher.ViewFactory {
.....
@Override
public View makeView() {
ImageView imageView = new ImageView(getApplicationContext());
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
imageView.setLayoutParams(new ImageSwitcher.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
return imageView;
}
宣告所需的變數:
private ImageSwitcher mImgSwicher;
private HSVLayout mGalleryLayout;
private HSVAdapter mImgAdapter;
private IntentFilter mIntentFilter;
private BroadcastReceiver mReceiver;
private int mCount = 0;
宣告原始圖片與預覽圖片:
// 宣告原始圖片
private Integer[] imgArr = {
R.drawable.img01, R.drawable.img02, R.drawable.img03,
R.drawable.img04, R.drawable.img05, R.drawable.img06,
R.drawable.img07, R.drawable.img08};
// 宣告預覽圖片
private Integer[] thumbImgArr = {
R.drawable.img01th, R.drawable.img02th, R.drawable.img03th,
R.drawable.img04th, R.drawable.img05th, R.drawable.img06th,
R.drawable.img07th, R.drawable.img08th};
初始化 ImageSwitcher 並指定圖片切換動畫效果
mImgSwicher = (ImageSwitcher) findViewById(R.id.image_switcher);
mImgSwicher.setFactory(this);
mImgSwicher.setInAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_in));
mImgSwicher.setOutAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out));
初始化 HSVLayout 與 HSVAdapter:
mGalleryLayout = (HSVLayout) findViewById(R.id.movieLayout);
mImgAdapter = new HSVAdapter(this);
將預覽圖餵給 HSVAdapter:
for (int i = 0; i < thumbImgArr.length; i++) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("image", thumbImgArr[i]);
map.put("index", (i+1));
mImgAdapter.addObject(map);
}
將 HSVAdapter 指定給 HSVLayout:
mGalleryLayout.setAdapter(mImgAdapter);
為 ImageSwitcher 設定 default 圖片:
mImgSwicher.setImageResource(imgArr[mCount]);
動態宣告 Internt filter:
private IntentFilter getIntentFilter() {
if (mIntentFilter == null) {
mIntentFilter = new IntentFilter();
mIntentFilter.addAction(AppConstant.UPDATE_IMAGE_ACTION);
}
return mIntentFilter;
}
在 onResume() 時註冊 Receiver 去監聽 HSVLayout 有沒有預覽圖被點擊,若有則通知 ImageSwitcher 切換到指定的原始圖片
@Override
protected void onResume() {
super.onResume();
if (mReceiver == null) {
mReceiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(AppConstant.UPDATE_IMAGE_ACTION)) {
int index = intent.getIntExtra("index", Integer.MAX_VALUE);
mImgSwicher.setImageResource(imgArr[index-1]);
}
}
};
}
registerReceiver(mReceiver, getIntentFilter());
}
在 onPause() 時記得去做反註冊:
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mReceiver);
}
以上~
參考文件:
http://www.it165.net/pro/html/201310/7469.html