安卓自定义控件(图像循环切换)

来源:互联网 发布:matlab化工优化 编辑:程序博客网 时间:2024/05/10 12:47



源码下载:http://download.csdn.net/detail/scimence/9027447


package com.sci.circularviewswitching;import android.app.Activity;import android.os.Bundle;/** * MainActivity * ----- * 2015-8-18 下午4:48:07  * wangzhongyuan */public class MainActivity extends Activity{int[] PicId = { R.drawable.pic1, R.drawable.pic2, R.drawable.pic3, R.drawable.pic4, R.drawable.pic5, R.drawable.pic6, R.drawable.pic7, R.drawable.pic8 };@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);CircularImageView main = new CircularImageView(this, PicId); // 创建主视图setContentView(main);// 设置为游戏视图// setContentView(R.layout.activity_main);}}

/** * 2015-8-19上午9:48:34 * wangzhongyuan */package com.shjc.jsbc.view2d.util;import android.annotation.SuppressLint;import android.content.Context;import android.graphics.Color;import android.os.Handler;import android.os.Message;import android.view.MotionEvent;import android.view.View;import android.view.View.OnTouchListener;import android.view.animation.Animation;import android.view.animation.AnimationSet;import android.view.animation.ScaleAnimation;import android.widget.ImageView;import android.widget.ImageView.ScaleType;import android.widget.RelativeLayout;import android.widget.Toast;/** * CircularImageView 此类用于实现多张ImageView的层叠展示循环切换,中间图像最前端显示,向两边图像尺寸依次递减 * selected()获取当前最前端显示的控件id * ----- * 2015-8-19 上午9:48:34  * wangzhongyuan */public class CircularImageView extends RelativeLayout implements OnTouchListener, android.view.View.OnClickListener{private Context context;// 控件所处的上下文环境private int[] PicId;// 控件所要展示的子图像private int len;// 子图像总数private ImageView2[] pics;// 子图像数组private int offSet = 0;// 图像显示偏移值,控制图像的显示位置private float x1 = -1, y1 = -1, x2 = -1, y2 = -1;// 标志触摸按下和触摸释放时的坐标/** * 获取当前选中的子控件id = [0, len) */public int selected(){// 选中图像idint id = len / 2 + offSet;if (id >= len)id -= len;else if (id < 0) id += len;return id;}/** * 选中子控件变动时调用该函数,子类可重写该函数,执行子控件选项变动逻辑 */public void selecteChanged(){// if(selected() == 0) ...;// else if(selected() == 1) ...;}/** *  创建控件, PicId = { R.drawable.pic1, R.drawable.pic2, R.drawable.pic3, R.drawable.pic4, R.drawable.pic5}; */public CircularImageView(Context context, int[] PicId){super(context);this.context = context;this.PicId = PicId;len = PicId.length;offSet = -len / 2;// 初始时,显示第一项到最中间creatMainView();}// 创建CircularImageView的子控件,以代码布局的方式显示PicId对应的图像private void creatMainView(){int w = 480, h = 300;// CircularImageView整体大小int w2 = 264, h2 = 165;// CircularImageView最中间位置的ImageView展示大小// 控件主体部分RelativeLayout body = new RelativeLayout(context);// 创建一个相对布局的视图body.setBackgroundColor(Color.GRAY); // 为其设置背景色body.setOnTouchListener(this);// 为CircularImageView添加触屏响应// 添加游戏主体部分到主界面RelativeLayout.LayoutParams paramsBody = new RelativeLayout.LayoutParams(w, h);paramsBody.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);this.addView(body, paramsBody);pics = new ImageView2[len];for (int i = 0; i < len; i++){// 修改控件的显示顺序int j = i, half = len / 2;if (i >= half) j = len - 1 - (i - half);// 向body中添加子控件ImageView2 pic = new ImageView2(context, j - half);RelativeLayout.LayoutParams params = getLayoutParams(w / 2, h / 2, w2, h2, j);body.addView(pic, params);// 将表示方格的文本框添加到窗体pic.setScaleType(ScaleType.CENTER_CROP);pic.setBackgroundResource(getPicId(PicId, j));pics[j] = pic;pic.setOnClickListener(this);// 添加事件监听}pics[len / 2].setOnTouchListener(this);// 为中间位置的子控件添加触屏响应}// 根据偏移值,循环获取图像资源对应的索引private int getPicId(int[] PicId, int i){i += offSet;if (i >= len)i -= len;else if (i < 0) i += len;return PicId[i];}// 获取第index项的布局参数,界面从0-len项依次布局,最中间的那项居中显示,从中间向两边尺寸依次递减private RelativeLayout.LayoutParams getLayoutParams(int CenterX, int CenterY, int w, int h, int index){int len = this.len, half = len / 2;if (len % 2 == 0) len++;index %= len;int Sign = index >= half ? 1 : -1;int W = getHalfWH(w, index - half);int H = getHalfWH(h, index - half);int sumW = getHalfWH_sum(w, index - half) * Sign;// int sumH = getHalfWH_sum(h, index - half);RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(W, H);int left = CenterX + sumW - W / 2, top = CenterY - H / 2, right = left + W + 1, bottom = top + H + 1;params.setMargins(left, top, right, bottom);// 设置index对应的View的布局位置return params;}// 长宽值WH经过n次折半private int getHalfWH(int WH, int n){n = Math.abs(n);while (n-- > 0)WH /= 2;return WH;}// 长宽值WH经过n次折半,偏移量累积值private int getHalfWH_sum(int WH, int n){n = Math.abs(n);int sum = 0;while (n-- > 0){WH /= 2;sum += WH;}return sum;}/* 点击界面中的View,切换显示至最前端 */@SuppressLint("HandlerLeak")@Overridepublic void onClick(View arg0){if (arg0 instanceof ImageView2){int half = len / 2;ImageView2 view = (ImageView2) arg0;if (view.offSet == 0) return;// 根据点击的ImageView位置,为所有子控件添加简单的动画切换效果for (int i = 0; i < len; i++){if (i < half)aniScale(pics[i], view.offSet < 0);else if (i > half)aniScale(pics[i], view.offSet > 0);elseaniScale(pics[i], false);}// 根据点击控件位置,设置图像偏移值offSet += view.offSet;if (offSet >= len)offSet -= len;else if (offSet < 0) offSet += len;// 延时执行切换显示动作new Handler(){public void handleMessage(Message msg){for (int i = 0; i < len; i++){pics[i].setBackgroundResource(getPicId(PicId, i));}}}.sendEmptyMessageDelayed(1, 55L);// 执行选中子控件变动逻辑selecteChanged();// 选中图像提示信息Toast.makeText(context, "选中图像" + selected(), Toast.LENGTH_SHORT).show();}}// 为视图v添加动画效果,尺寸变化private void aniScale(View v, boolean amplify){// v.bringToFront(); //前端显示AnimationSet aniSet = new AnimationSet(true);// 设置尺寸从1倍变化到1.7倍ScaleAnimation scaleAni;if (amplify)scaleAni = new ScaleAnimation(1f, 1.75f, 1f, 1.75f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);elsescaleAni = new ScaleAnimation(1f, 0.45f, 1f, 0.45f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);scaleAni.setDuration(50);// 设置动画效果时间aniSet.addAnimation(scaleAni);// 将动画效果添加到动画集中v.startAnimation(aniSet);// 视图v开始动画效果}// 为每个ImageView添加offSet属性值,记录相对于中间ImageView的偏移量class ImageView2 extends ImageView{int offSet = -1;ImageView2(Context context, int offSet){super(context);this.offSet = offSet;}}/* 触屏响应 */public boolean onTouch(View v, MotionEvent event){// 获取触摸拖动起点和终点的坐标,以便于判断触摸移动方向switch (event.getAction()){case MotionEvent.ACTION_DOWN:// 触摸屏幕后记录坐标x1 = event.getX();// 按下点坐标y1 = event.getY();break;case MotionEvent.ACTION_MOVE:// 触摸移动break;case MotionEvent.ACTION_UP:x2 = event.getX();// 移动点坐标y2 = event.getY();if (x2 - x1 > 6) onClick(pics[len / 2 - 1]);// 向右滑动else if (x2 - x1 < -6) onClick(pics[len / 2 + 1]);// 向左滑动break;case MotionEvent.ACTION_CANCEL:}return true;}}


0 0