暑期大学生博客分享大赛 - 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更简单的自定义各种控件,希望大家继续支持
来源:oschina
链接:https://my.oschina.net/u/126188/blog/28990