Canvas的实际使用
来源:互联网 发布:ubuntu syslog函数 编辑:程序博客网 时间:2024/05/21 14:03
这个就是一个大致的实现效果,左右滑动用的是一个自定义的HorizontalScrollView,图片渐变用的是一个自定义Drawable;
1、自定义HorizontalScrollView实现实现左右滑动
1.1、extends HorizontalScrollView 并进行相应的初始化
public class GallaryHorizonalScrollView extends HorizontalScrollView implements View.OnTouchListener { private LinearLayout container; private int iconWidth; private int centerX; public GallaryHorizonalScrollView(Context context) { this(context, null); } public GallaryHorizonalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public GallaryHorizonalScrollView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { //在ScrollView里面放置一个水平线性布局,再往里面放置很多的ImageView LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT ); container = new LinearLayout(getContext()); container.setLayoutParams(params); setOnTouchListener(this); }}
1.2、重写onLayout方法进行摆放
@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); //得到某一张图片的宽度 View v = container.getChildAt(0); iconWidth = v.getWidth(); //得到中间x坐标 centerX = getWidth() / 2; //处理中心坐标改成中心图片的左边界 centerX = centerX - iconWidth / 2; //给LinearLayout和HorizontalScrollView之间设置边框距离 container.setPadding(centerX, 0, centerX, 0);}
1.3、设置setOnTouchListener进行事件处理
@Overridepublic boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_MOVE) { //处理移动 //渐变图片 reveal(); } return false;}private void reveal() { //渐变效果 //得到HorizontalScrollView滑出去的距离 int scrollX = getScrollX(); //找到两张渐变的图片的下标--左 右 int indexLeft = scrollX / iconWidth; int indexRight = indexLeft + 1; //设置图片的level for (int i = 0; i < container.getChildCount(); i++) { if (i == indexLeft || i == indexRight) { //变化 //比例 float ratio = 5000f / iconWidth; ImageView ivLeft = (ImageView) container.getChildAt(indexLeft); //scrollX%icon_width:代表滑出去的距离 //滑出去了icon_width/2 icon_width/2%icon_width ivLeft.setImageLevel((int) (5000 - scrollX % iconWidth * ratio)); //右边 if (indexRight < container.getChildCount()) { ImageView ivRight = (ImageView) container.getChildAt(indexRight); //scrollX%icon_width:代表滑出去的距离 //滑出去了icon_width/2 icon_width/2%icon_width ivRight.setImageLevel( (int) (10000 - scrollX % iconWidth * ratio) ); } } else { //灰色 ImageView iv = (ImageView) container.getChildAt(i); iv.setImageLevel(0); } }}
这里只需要对ACTION_MOVE进行处理,对应的提供了一个添加图片数据源的方法;
/** * 添加图片 * * @param revealDrawables 传入的Drawable数组资源 */public void addImageViews(Drawable[] revealDrawables) { for (int i = 0; i < revealDrawables.length; i++) { ImageView img = new ImageView(getContext()); img.setImageDrawable(revealDrawables[i]); container.addView(img); if (i == 0) { img.setImageLevel(5000); } } addView(container);}
2、自定义Drawable对图片进行处理
图片的渐变效果其实利用了Canvas的裁剪,将画布裁剪成两个区域,左边为未选状态,右边为已选状态,根据滑动的距离去做相应的显示;
public class RevealDrawable extends Drawable { //未被选 private Drawable mUnselectedDrawable; //被选 private Drawable mSelectedDrawable; //显示方向 private int mOrientation; //横向 public static final int HORIZONTAL = 1; //纵向 public static final int VERTICAL = 2; //绘制和裁剪的矩形区域 private final Rect mTmpRect = new Rect(); public RevealDrawable(Drawable unselected, Drawable selected, int orientation) { mUnselectedDrawable = unselected; mSelectedDrawable = selected; mOrientation = orientation; } @Override public void draw(Canvas canvas) { //绘制 int level = getLevel();//from 0 (minimum) to 10000 //右边区域和左边区域--设置成灰色 if (level == 10000 || level == 0) { mUnselectedDrawable.draw(canvas); } else if (level == 5000) { //全部选中 设置成彩色 mSelectedDrawable.draw(canvas); } else { //混合效果的Drawable /** * 将画板切割成两块--左边和右边 */ Rect r = mTmpRect; //得到当前自身Drawable的矩形区域 Rect bounds = getBounds(); { //先绘制灰色部分 level 0--5000--10000 //比例 float ratio = (level / 5000f) - 1f; int w = bounds.width(); if (mOrientation == HORIZONTAL) { w = (int) (w * Math.abs(ratio)); } int h = bounds.height(); if (mOrientation == VERTICAL) { h = (int) (h * Math.abs(ratio)); } int gravity = ratio < 0 ? Gravity.LEFT : Gravity.RIGHT; //从一个已有的bounds矩形边界范围中抠出一个矩形r Gravity.apply( gravity,//从左边还是从右边开始抠 w,//目标矩形的宽度 h,//目标矩形的高度 bounds,//被抠出来的rect r//目标rect ); //保存当前画布 canvas.save(); //进行切割 canvas.clipRect(r); //进行绘制 mUnselectedDrawable.draw(canvas); //恢复之前的画布 canvas.restore(); } { //绘制彩色部分 level 0--5000--10000 //比例 float ratio = (level / 5000f) - 1f; int w = bounds.width(); if (mOrientation == HORIZONTAL) { w -= (int) (w * Math.abs(ratio)); } int h = bounds.height(); if (mOrientation == VERTICAL) { h -= (int) (h * Math.abs(ratio)); } int gravity = ratio < 0 ? Gravity.RIGHT : Gravity.LEFT; //从一个已有的bounds矩形边界范围中抠出一个矩形r Gravity.apply( gravity,//从左边还是从右边开始抠 w,//目标矩形的宽度 h,//目标矩形的高度 bounds,//被抠出来的rect r//目标rect ); //保存当前画布 canvas.save(); //进行切割 canvas.clipRect(r); //进行绘制 mSelectedDrawable.draw(canvas); //恢复之前的画布 canvas.restore(); } } } @Override protected void onBoundsChange(Rect bounds) { //定义好两个Drawable图片的宽高--边界bounds mUnselectedDrawable.setBounds(bounds); mSelectedDrawable.setBounds(bounds); } @Override public int getIntrinsicWidth() { //得到Drawable的实际宽度 return Math.max(mSelectedDrawable.getIntrinsicWidth(), mUnselectedDrawable.getIntrinsicWidth()); } @Override public int getIntrinsicHeight() { //得到Drawable的实际高度 return Math.max(mSelectedDrawable.getIntrinsicHeight(), mUnselectedDrawable.getIntrinsicHeight()); } @Override protected boolean onLevelChange(int level) { //当设置level的时候就会回调该方法 //进行重新绘制 invalidateSelf(); return true; } @Override public void setAlpha(int alpha) { } @Override public void setColorFilter(ColorFilter colorFilter) { } @Override public int getOpacity() { return PixelFormat.UNKNOWN; }}
3、使用
public class MainActivity extends AppCompatActivity { private int[] mImgIds = new int[] { //7个 R.mipmap.avft, R.mipmap.box_stack, R.mipmap.bubble_frame, R.mipmap.bubbles, R.mipmap.bullseye, R.mipmap.circle_filled, R.mipmap.circle_outline, R.mipmap.avft, R.mipmap.box_stack, R.mipmap.bubble_frame, R.mipmap.bubbles, R.mipmap.bullseye, R.mipmap.circle_filled, R.mipmap.circle_outline }; private int[] mImgIds_active = new int[] { R.mipmap.avft_active, R.mipmap.box_stack_active, R.mipmap.bubble_frame_active, R.mipmap.bubbles_active, R.mipmap.bullseye_active, R.mipmap.circle_filled_active, R.mipmap.circle_outline_active, R.mipmap.avft_active, R.mipmap.box_stack_active, R.mipmap.bubble_frame_active, R.mipmap.bubbles_active, R.mipmap.bullseye_active, R.mipmap.circle_filled_active, R.mipmap.circle_outline_active }; public Drawable[] revealDrawables; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initData(); initView(); } private void initView() { for (int i = 0; i < mImgIds.length; i++) { RevealDrawable rd=new RevealDrawable( getResources().getDrawable(mImgIds[i]), getResources().getDrawable(mImgIds_active[i]), RevealDrawable.HORIZONTAL ); revealDrawables[i]=rd; } GallaryHorizonalScrollView hsv = (GallaryHorizonalScrollView) findViewById(R.id.hsv); hsv.addImageViews(revealDrawables); } private void initData() { revealDrawables=new Drawable[mImgIds.length]; }}
源码地址:
http://download.csdn.net/download/wangwo1991/9971873
阅读全文
0 0
- Canvas的实际使用
- Canvas的实际使用--自定义搜索效果
- Android PorterDuff.Mode与Canvas实际使用
- 使用 Canvas 的Xfermode 实现 ImageView 圆形图片的实际步骤
- xmlhttp的实际使用
- Binder的实际使用
- popupWindow的实际使用
- android canvas的使用
- canvas的使用:
- canvas的使用
- Canvas类的使用
- canvas的基本使用
- Canvas(画布)的使用
- canvas的使用
- Html5 的Canvas使用
- Canvas类的使用
- canvas 的使用1
- Canvas的使用
- 练习二(第二周)
- android datebinding学习
- 欢迎使用CSDN-markdown编辑器
- BOW
- 欢迎使用CSDN-markdown编辑器
- Canvas的实际使用
- PHP执行外部程序
- 基数排序
- 【京东2017年秋招笔试题】统计移除括号对的方案数
- JSTL标签用法,很重要!!!
- python运算符的优先级
- 最长线段(几何证明题)
- 2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛 A,C,F , H
- 大数据分析中的 数据,大数据