玩转Android 之 绚丽的自定义Gallery

来源:互联网 发布:嗟乎大丈夫当如此也 编辑:程序博客网 时间:2024/06/08 00:22

http://my.oschina.net/u/126188/blog/28990

暑期大学生博客分享大赛 - 2011 Android 成长篇

         本文参加第二届Google大学生暑期博客分享大赛  
         相信大家对Gallery这个控件是再喜爱不过了,用它可以做出很炫的效果,这得意于Android优良的架构和MVC设计模式的
便利。下面我会介绍一个比较炫的自定义的Gallery效果。先上效果图:
  
如图,主要效果包括,中央文字变大,变亮,出现倒影,未选中项变小,变暗,gallery减慢滑动速度,循环gallery展
示。
         由于涉及公司项目,这里只贴关键代码和xml文档。
         首先默认的Gallery滑动时,滚动速度很快,会导致某些项一闪而过看不清楚,解决的办法是继承Gallery,自定义一个

CustomGallery类,覆盖Gallery的onFling()方法,让它返回false就行了,代码如下
01package com.widget;
02import android.content.Context;
03import android.util.AttributeSet;
04import android.view.MotionEvent;
05import android.widget.Gallery;
06 
07public class CustomGallery extends Gallery {
08 
09    public CustomGallery(Context context, AttributeSet attrs) {
10        super(context, attrs);
11        // TODO Auto-generated constructor stub
12    }
13    public boolean onFling (MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
14        return false;
15    }
16 
17}


         接下来就是在xml文件中如何调用这个自定义的控件类的问题,解决方法很简单
1<LinearLayout android:id="@+id/gallerylayout"
2    android:layout_width="fill_parent" android:layout_height="fill_parent">
3    <com.widget.CustomGallery
4        android:layout_width="fill_parent" android:layout_height="wrap_content"
5        android:spacing="10dip" android:unselectedAlpha="0.5" android:id="@+id/gallery"
6        android:layout_marginTop="36dip" />
7</LinearLayout>


需要注意的是,Android支持的自定义控件类的构造函数,需要有Context和AttributeSet两个参数,否则会报异常!
另外
 android:unselectedAlpha="0.5"
这个属性可以设置未选中项的半透明度,设置为0.5,这样有突显选中项的效果。
         此时运行程序并不能显示我们自定义的Gallery,原因是,我们还没有向Gallery中添加数据,而向Gallery中添加数据需

要使用
Gallery的setAdapter方法,通过适配器来进行添加显示项,这里我们把大学的名称作为显示数据加入到适配器中,由于需要处理选

中项的倒影效果和变大效果,于是我们自定义一个Adapter来进行处理,代码如下
根据MVC,先是数据模型类University
01public class University{
02    private String name;  // 学校名称
03 
04    public String getName() {
05        return name;
06    }
07 
08    public void setName(String name) {
09        this.name = name;
10    }
11}

然后是自定义的Adapter

01public import java.util.ArrayList;
02import com.model.Channel;
03import com.util.BitmapUtil;
04import android.content.Context;
05import android.view.View;
06import android.view.ViewGroup;
07import android.widget.BaseAdapter;
08import android.widget.ImageView;
09 
10 
11public class UniversityAdapter extends BaseAdapter {
12 
13    private Context context;
14    private ArrayList<University> universityList;
15 
16    public UniversityAdapter(Context context, ArrayList<University> universityList) {
17        this.context = context;
18        this.universityList = universityList;
19    }
20        //这里返回一个较大整数是为了实现Gallery的循环播放
21    @Override
22    public int getCount() {
23        // TODO Auto-generated method stub
24        return Integer.MAX_VALUE;
25    }
26 
27    @Override
28    public Object getItem(int position) {
29        // TODO Auto-generated method stub
30        return position;
31    }
32 
33    @Override
34    public long getItemId(int position) {
35        // TODO Auto-generated method stub
36        return position;
37    }
38 
39    private int select = 0;
40 
41    public void notifyDataSetChanged(int albumId) {
42        select = albumId;
43        super.notifyDataSetChanged();
44    }
45    public View getView(int position, View convertView, ViewGroup parent) {
46        // TODO Auto-generated method stub
47        ImageView imageView = new ImageView(context);//初始化ImageView,用来显示各项
48        if (select == position) {//当此项是选中项时,对起进行特殊处理
49            University pro = universityList.get(position % universityList.size());//要实现循环播放,这
50 
51里需要对数据大小进行求余
52            imageView.setImageBitmap(BitmapUtil.createReflectedImage(BitmapUtil
53                    .createTxtImage(pro.getName(), 28)));//这里通过自定义的BitmapUtil类中的两个
54 
55方法,实现了倒影效果
56        else {
57            University pro = universityList.get(position % universityList.size());
58            imageView.setImageBitmap(BitmapUtil.createTxtImage(pro.getName(),
59                    22));//这设置文字大小为22。实现了未选中项的变小效果
60        }
61        return imageView;
62    }

上面代码中的BitmapUtil是封装好的Bitmap处理工具类,包括了传入文字和字体大小,返回绘制好的Bitmap 和传入Bitmap返回下方

加入了倒影效果的Bitmap的函数。代码如下
01package com.util;
02 
03import android.graphics.Bitmap;
04import android.graphics.Bitmap.Config;
05import android.graphics.Canvas;
06import android.graphics.Color;
07import android.graphics.LinearGradient;
08import android.graphics.Matrix;
09import android.graphics.Paint;
10import android.graphics.PorterDuff.Mode;
11import android.graphics.PorterDuffXfermode;
12import android.graphics.Shader.TileMode;
13 
14public class BitmapUtil {
15 
16    public static Bitmap createTxtImage(String txt, int txtSize) {
17        Bitmap mbmpTest = Bitmap.createBitmap(txt.length() * txtSize + 4,
18                txtSize + 4, Config.ARGB_8888);
19        Canvas canvasTemp = new Canvas(mbmpTest);
20        Paint p = new Paint();
21        p.setAntiAlias(true);
22        p.setColor(Color.WHITE);
23        p.setTextSize(txtSize);
24        canvasTemp.drawText(txt, 2, txtSize - 2, p);
25        return mbmpTest;
26    }
27     
28    public static Bitmap createReflectedImage(Bitmap originalImage) {
29        // The gap we want between the reflection and the original image
30        final int reflectionGap = 0;
31 
32        int width = originalImage.getWidth();
33        int height = originalImage.getHeight();
34 
35        // This will not scale but will flip on the Y axis
36        Matrix matrix = new Matrix();
37        matrix.preScale(1, -1);
38 
39        // Create a Bitmap with the flip matrix applied to it.
40        // We only want the bottom half of the image
41        Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0,
42                height / 2, width, height / 2, matrix, false);
43 
44        // Create a new bitmap with same width but taller to fit reflection
45        Bitmap bitmapWithReflection = Bitmap.createBitmap(width,
46                (height + height / 2), Config.ARGB_8888);
47 
48        // Create a new Canvas with the bitmap that's big enough for
49        // the image plus gap plus reflection
50        Canvas canvas = new Canvas(bitmapWithReflection);
51        // Draw in the original image
52        canvas.drawBitmap(originalImage, 00null);
53        // Draw in the gap
54        Paint defaultPaint = new Paint();
55        canvas.drawRect(0, height, width, height + reflectionGap, defaultPaint);
56        // Draw in the reflection
57        canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
58 
59        // Create a shader that is a linear gradient that covers the reflection
60        Paint paint = new Paint();
61        LinearGradient shader = new LinearGradient(0,
62                originalImage.getHeight(), 0, bitmapWithReflection.getHeight()
63                        + reflectionGap, 0x70ffffff0x00ffffff, TileMode.CLAMP);
64        // Set the paint to use this shader (linear gradient)
65        paint.setShader(shader);
66        // Set the Transfer mode to be porter duff and destination in
67        paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
68        // Draw a rectangle using the paint with our linear gradient
69        canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()
70                + reflectionGap, paint);
71 
72        return bitmapWithReflection;
73    }
74}


最后就是主界面代码中对Gallery的调用了,关键代码如下
view source
print?
01    private CustomGallery gallery;
02    private UniversityAdapter pAdapter;
03    private ArrayList<University> universityList = new ArrayList<University>();
04        private void init(){
05        pAdapter = new UniversityAdapter(MainActivity.this, universityList);//初始化我们自定义的Adapter
06        University p = new University();
07        p.setName("电子科技大学");
08        universityList .add(p);
09        University p1 = new University();
10        p1.setName("清华大学");
11        universityList .add(p1);
12        University p2 = new University();
13        p2.setName("北京大学");
14        universityList .add(p2);
15        gallery.setAdapter(pAdapter);//设置Gallery显示的内容
16        gallery.setSelection(Integer.MAX_VALUE / 2);//通过setSelection() 可以设置当前选中的元素,这里我们将
17 
18其设置在中间
19        gallery.setOnItemSelectedListener(this);//这里对Item项进行监听,以实现刷新显示的效果
20       }
21 
22@Override
23public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,
24            long arg3) {
25    // TODO Auto-generated method stub
26    pAdapter.notifyDataSetChanged(arg2);//arg2会返回当前选中项的位置,调用此方法,通知更新
27}
28 
29 
30@Override
31public void onNothingSelected(AdapterView<?> arg0) {
32        // TODO Auto-generated method stub
33}

代码贴完了,有疑问的可以发我邮件,邮箱是uestccokey@gmail.com 
希望大家最后都能把程序跑起来,做出更好更实用的效果。 


0 0
原创粉丝点击