玩轉Android 之 絢麗的自定義Gallery

暑期大學生博客分享大賽 - 2011 Android 成長篇

         本文參加第二屆Google大學生暑期博客分享大賽 
         相信你們對Gallery這個控件是再喜好不過了,用它能夠作出很炫的效果,這得意於Android優良的架構和MVC設計模式的
便利。下面我會介紹一個比較炫的自定義的Gallery效果。先上效果圖:

         如圖,主要效果包括,中央文字變大,變亮,出現倒影,未選中項變小,變暗,gallery減慢滑動速度,循環gallery展
示。
         因爲涉及公司項目,這裏只貼關鍵代碼和xml文檔。
         首先默認的Gallery滑動時,滾動速度很快,會致使某些項一閃而過看不清楚,解決的辦法是繼承Gallery,自定義一個

CustomGallery類,覆蓋Gallery的onFling()方法,讓它返回false就好了,代碼以下
package com.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.Gallery;

public class CustomGallery extends Gallery {

	public CustomGallery(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}
	public boolean onFling (MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
		return false;
	}

}


         接下來就是在xml文件中如何調用這個自定義的控件類的問題,解決方法很簡單
<LinearLayout android:id="@+id/gallerylayout"
			android:layout_width="fill_parent" android:layout_height="fill_parent">
			<com.widget.CustomGallery
				android:layout_width="fill_parent" android:layout_height="wrap_content"
				android:spacing="10dip" android:unselectedAlpha="0.5" android:id="@+id/gallery"
				android:layout_marginTop="36dip" />
		</LinearLayout>


須要注意的是,Android支持的自定義控件類的構造函數,須要有Context和AttributeSet兩個參數,不然會報異常!
另外
 android:unselectedAlpha="0.5"
這個屬性能夠設置未選中項的半透明度,設置爲0.5,這樣有突顯選中項的效果。
         此時運行程序並不能顯示咱們自定義的Gallery,緣由是,咱們尚未向Gallery中添加數據,而向Gallery中添加數據需

要使用
Gallery的setAdapter方法,經過適配器來進行添加顯示項,這裏咱們把大學的名稱做爲顯示數據加入到適配器中,因爲須要處理選

中項的倒影效果和變大效果,因而咱們自定義一個Adapter來進行處理,代碼以下
根據MVC,先是數據模型類University
public class University{
	private String name;  // 學校名稱

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

而後是自定義的Adapter

public import java.util.ArrayList;
import com.model.Channel;
import com.util.BitmapUtil;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;


public class UniversityAdapter extends BaseAdapter {

	private Context context;
	private ArrayList<University> universityList;

	public UniversityAdapter(Context context, ArrayList<University> universityList) {
		this.context = context;
		this.universityList = universityList;
	}
        //這裏返回一個較大整數是爲了實現Gallery的循環播放
	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return Integer.MAX_VALUE;
	}

	@Override
	public Object getItem(int position) {
		// TODO Auto-generated method stub
		return position;
	}

	@Override
	public long getItemId(int position) {
		// TODO Auto-generated method stub
		return position;
	}

	private int select = 0;

	public void notifyDataSetChanged(int albumId) {
		select = albumId;
		super.notifyDataSetChanged();
	}
	public View getView(int position, View convertView, ViewGroup parent) {
		// TODO Auto-generated method stub
		ImageView imageView = new ImageView(context);//初始化ImageView,用來顯示各項
		if (select == position) {//當此項是選中項時,對起進行特殊處理
			University pro = universityList.get(position % universityList.size());//要實現循環播放,這

裏須要對數據大小進行求餘
			imageView.setImageBitmap(BitmapUtil.createReflectedImage(BitmapUtil
					.createTxtImage(pro.getName(), 28)));//這裏經過自定義的BitmapUtil類中的兩個

方法,實現了倒影效果
		} else {
			University pro = universityList.get(position % universityList.size());
			imageView.setImageBitmap(BitmapUtil.createTxtImage(pro.getName(),
					22));//這設置文字大小爲22。實現了未選中項的變小效果
		}
		return imageView;
	}

上面代碼中的BitmapUtil是封裝好的Bitmap處理工具類,包括了傳入文字和字體大小,返回繪製好的Bitmap 和傳入Bitmap返回下方

加入了倒影效果的Bitmap的函數。代碼以下
package com.util;

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader.TileMode;

public class BitmapUtil {

	public static Bitmap createTxtImage(String txt, int txtSize) {
		Bitmap mbmpTest = Bitmap.createBitmap(txt.length() * txtSize + 4,
				txtSize + 4, Config.ARGB_8888);
		Canvas canvasTemp = new Canvas(mbmpTest);
		Paint p = new Paint();
		p.setAntiAlias(true);
		p.setColor(Color.WHITE);
		p.setTextSize(txtSize);
		canvasTemp.drawText(txt, 2, txtSize - 2, p);
		return mbmpTest;
	}
	
	public static Bitmap createReflectedImage(Bitmap originalImage) {
		// The gap we want between the reflection and the original image
		final int reflectionGap = 0;

		int width = originalImage.getWidth();
		int height = originalImage.getHeight();

		// This will not scale but will flip on the Y axis
		Matrix matrix = new Matrix();
		matrix.preScale(1, -1);

		// Create a Bitmap with the flip matrix applied to it.
		// We only want the bottom half of the image
		Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0,
				height / 2, width, height / 2, matrix, false);

		// Create a new bitmap with same width but taller to fit reflection
		Bitmap bitmapWithReflection = Bitmap.createBitmap(width,
				(height + height / 2), Config.ARGB_8888);

		// Create a new Canvas with the bitmap that's big enough for
		// the image plus gap plus reflection
		Canvas canvas = new Canvas(bitmapWithReflection);
		// Draw in the original image
		canvas.drawBitmap(originalImage, 0, 0, null);
		// Draw in the gap
		Paint defaultPaint = new Paint();
		canvas.drawRect(0, height, width, height + reflectionGap, defaultPaint);
		// Draw in the reflection
		canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);

		// Create a shader that is a linear gradient that covers the reflection
		Paint paint = new Paint();
		LinearGradient shader = new LinearGradient(0,
				originalImage.getHeight(), 0, bitmapWithReflection.getHeight()
						+ reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP);
		// Set the paint to use this shader (linear gradient)
		paint.setShader(shader);
		// Set the Transfer mode to be porter duff and destination in
		paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
		// Draw a rectangle using the paint with our linear gradient
		canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()
				+ reflectionGap, paint);

		return bitmapWithReflection;
	}
}


最後就是主界面代碼中對Gallery的調用了,關鍵代碼以下
private CustomGallery gallery;
	private UniversityAdapter pAdapter;
	private ArrayList<University> universityList = new ArrayList<University>();
        private void init(){
		pAdapter = new UniversityAdapter(MainActivity.this, universityList);//初始化咱們自定義的Adapter
		University p = new University();
		p.setName("電子科技大學");
		universityList .add(p);
		University p1 = new University();
		p1.setName("清華大學");
		universityList .add(p1);
		University p2 = new University();
		p2.setName("北京大學");
		universityList .add(p2);
		gallery.setAdapter(pAdapter);//設置Gallery顯示的內容
		gallery.setSelection(Integer.MAX_VALUE / 2);//經過setSelection() 能夠設置當前選中的元素,這裏咱們將

其設置在中間
		gallery.setOnItemSelectedListener(this);//這裏對Item項進行監聽,以實現刷新顯示的效果
       }

@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,
			long arg3) {
	// TODO Auto-generated method stub
	pAdapter.notifyDataSetChanged(arg2);//arg2會返回當前選中項的位置,調用此方法,通知更新
}


@Override
public void onNothingSelected(AdapterView<?> arg0) {
		// TODO Auto-generated method stub
}

代碼貼完了,有疑問的能夠發我郵件,郵箱是uestccokey@gmail.com
但願你們最後都能把程序跑起來,作出更好更實用的效果。

各位路過的哥們兒們,幫小弟投個票吧,http://www.google.com/intl/zh-CN/daxue/blog/vote.html#tab2
下面選李可,電子科技大學,謝謝了,哈哈
下一期咱們將會講解如何經過xml更簡單的自定義各類控件,但願你們繼續支持 
相關文章
相關標籤/搜索