实现支付宝咻一咻的几种思路
2016-02-05 21:14
627 查看
对于现在最火的无外乎集五福了,而五福除了加十个好友获得外,最直接的途径就是支付宝的咻一咻了。那么咻一咻具体有哪些实现方式呢?下面我们将一一介绍这几种思路的实现过程。
用该种方式实现的优点有:
㈠这种是最复杂的实现方法,但其兼容性最高,其支持android的所有设备。
㈡其对内存要求不大,几乎不占用任何内存。
下面我们来看看是怎样实现其效果的:
看看其效果图:
这里实现的效果没有支付宝好看自然有两个原因:
①.支付宝的背景图片是淡红色,衬托了红色的波纹。当然了你也可以将画布设置为透明淡红色。
②.其为填充圆圈渲染,不是我的边框渲染效果,你可以将circlePaint.setStyle(Paint.Style.STROKE);换成Paint.Style.FILL.然后,微调shader的mPositions实现环形填充渐变。
下面我们看看其实现步骤:
㈠自定义View实现一个圆即可,代码如下:
代码与上面差不多,就不注释了。
㈡实现Activity即可
㈢布局文件代码如下:
当然上面两个实现方法,我都只设置圆边框,没有填充,你可以设置为填充后,在微调渐变值。
其效果图如下:
我们都知道5.0中提供如下两个属性:
android:background="?android:attr/selectableItemBackground"波纹有边界
android:background="?android:attr/selectableItemBackgroundBorderless"波纹超出边界
设置下面这个就会绘制一个圆形的波纹(不管你的控件是不是圆形)。
通过android:colorControlHighlight设置波纹颜色。
那么好了就,介绍这么多了,时间匆促,要过年了。
1.自定义View实现咻一咻
那么这种实现方法需要掌握Canvas以及Paint几乎所有的方法。其对程序员的专业知识要求极高。用该种方式实现的优点有:
㈠这种是最复杂的实现方法,但其兼容性最高,其支持android的所有设备。
㈡其对内存要求不大,几乎不占用任何内存。
下面我们来看看是怎样实现其效果的:
public class XiuYiXiuView extends View { /*** * 中心图片画笔 */ private Paint paint; /*** * 水波圆圈画笔 */ private Paint circlePaint; /*** * 用bitmap创建画布 */ private Bitmap bitmap; /*** * 中心图片 */ private Bitmap imageBit; /*** * 画布 */ private Canvas canvas; /*** * 屏幕的宽 */ private int screenWidth; /*** * 屏幕的高 */ private int screenHeight; /*** * 图片右上角坐标 */ private Point pointLeftTop; /*** * 图片右下角坐标 */ private Point pointRightBottom; /*** * 记录圆圈 */ private List<LYJCircle> lyjCircleList; /*** * 标记是否按下按钮,并且源泉是否扩散消失 */ private boolean isSpread=false; /*** * 默认没有按动时候的圆圈 */ private LYJCircle defaultCircle; public XiuYiXiuView(Context context, AttributeSet attrs) { super(context, attrs); this.lyjCircleList=new ArrayList<>(); screenWidth=LYJUtils.getScreenWidth((Activity) context); screenHeight=LYJUtils.getScreenHeight((Activity) context); bitmap = Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.ARGB_8888); // 设置位图的宽高 canvas = new Canvas(); canvas.setBitmap(bitmap); paint=new Paint(Paint.DITHER_FLAG); paint.setAntiAlias(true); circlePaint=new Paint(Paint.DITHER_FLAG); circlePaint.setAntiAlias(true); imageBit= BitmapFactory.decodeResource(getResources(), R.drawable.bwa_homepage_yuyin); pointLeftTop=new Point((screenWidth/2)-(imageBit.getWidth()/2),(screenHeight/2)-(imageBit.getHeight()/2)); pointRightBottom=new Point(pointLeftTop.x+imageBit.getWidth(),pointLeftTop.y+imageBit.getHeight()); canvas.drawBitmap(imageBit,pointLeftTop.x,pointLeftTop.y,paint); //取图片上的颜色 Palette.generateAsync(imageBit, new Palette.PaletteAsyncListener() { @Override public void onGenerated(Palette palette) { Palette.Swatch swatch1 = palette.getVibrantSwatch(); //充满活力的色板 circlePaint.setColor(swatch1.getRgb()); circlePaint.setStyle(Paint.Style.STROKE); circlePaint.setStrokeWidth(10); circlePaint.setAlpha(100); paint.setShadowLayer(15, 0, 0, swatch1.getRgb());//设置阴影效果 int[] mColors = new int[] {//渲染颜色 Color.TRANSPARENT,swatch1.getRgb() }; //范围,这里可以微调,实现你想要的渐变 float[] mPositions = new float[] { 0f, 0.1f }; Shader shader=new RadialGradient(screenWidth / 2,screenHeight / 2,imageBit.getWidth() / 2 + 10,mColors, mPositions, Shader.TileMode.MIRROR); circlePaint.setShader(shader); defaultCircle=new LYJCircle(screenWidth / 2, screenHeight / 2, imageBit.getWidth() / 2 + 10); clearScreenAndDrawList(); Message message = handler.obtainMessage(1); handler.sendMessageDelayed(message, 1000); //发送message } }); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: break; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: isSpread=true;//是否按下图片 lyjCircleList.add(new LYJCircle(screenWidth / 2, screenHeight / 2, imageBit.getWidth() / 2 + 10)); clearScreenAndDrawList(); invalidate(); break; default: break; } return true; } private Handler handler = new Handler(){ public void handleMessage(Message msg){ switch (msg.what) { case 1: //定时更新界面 clearScreenAndDrawList(); invalidate(); Message message = handler.obtainMessage(1); handler.sendMessageDelayed(message, 200); } super.handleMessage(msg); } }; /** * 清掉屏幕上所有的线,然后画出集合里面的线 */ private void clearScreenAndDrawList() { canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); //判断是否按下图片,并且外圈执行完成没有。 if(!isSpread){ circlePaint.setMaskFilter(null); canvas.drawCircle(defaultCircle.getRoundX(), defaultCircle.getRoundY(),defaultCircle.getRadiuLoop(), circlePaint);// 画线 }else{ for (LYJCircle lyjCircle : lyjCircleList) { if(lyjCircle.getSpreadRadiu()==0){ }else if(lyjCircle.getSpreadRadiu()>(lyjCircle.getRadiu()+99)){ //如果圆圈扩散半径大于图片半径+99,那么设置边缘模糊,也就是淡出的效果 circlePaint.setMaskFilter(new BlurMaskFilter(5, BlurMaskFilter.Blur.OUTER)); canvas.drawCircle(lyjCircle.getRoundX(), lyjCircle.getRoundY(),lyjCircle.getSpreadRadiu(), circlePaint);// 画线 }else{ //不是则按正常的环形渲染来 circlePaint.setMaskFilter(null); canvas.drawCircle(lyjCircle.getRoundX(), lyjCircle.getRoundY(),lyjCircle.getSpreadRadiu(), circlePaint);// 画线 } } } canvas.drawBitmap(imageBit,pointLeftTop.x,pointLeftTop.y,paint); //释放小时了的圆圈 for(int i=0;i<lyjCircleList.size();i++){ if(lyjCircleList.get(i).getSpreadRadiu()==0){ lyjCircleList.remove(i); } } //如果没有点击图片发射出去的圆圈,那么就恢复默认缩放。 if(lyjCircleList.size()<=0){ isSpread=false; } } @Override protected void onDraw(Canvas canvas) { canvas.drawBitmap(bitmap, 0, 0, null); } }
看看其效果图:
这里实现的效果没有支付宝好看自然有两个原因:
①.支付宝的背景图片是淡红色,衬托了红色的波纹。当然了你也可以将画布设置为透明淡红色。
②.其为填充圆圈渲染,不是我的边框渲染效果,你可以将circlePaint.setStyle(Paint.Style.STROKE);换成Paint.Style.FILL.然后,微调shader的mPositions实现环形填充渐变。
2.属性动画实现咻一咻
其要掌握的只是基本只需要属性动画,在加一点线程方面有关的知识而已。下面我们看看其实现步骤:
㈠自定义View实现一个圆即可,代码如下:
public class LYJCircleView extends View { private Bitmap bitmap; private Paint paint; private Canvas canvas; private int screenWidth; private int screenHeight; private boolean isSpreadFlag=false;//标记是否发射完成 public boolean isSpreadFlag() { return isSpreadFlag; } public void setIsSpreadFlag(boolean isSpreadFlag) { this.isSpreadFlag = isSpreadFlag; } public LYJCircleView(Context context,int width,int height,int statusHeight) { super(context); screenWidth= LYJUtils.getScreenWidth((Activity) context); screenHeight=LYJUtils.getScreenHeight((Activity) context); bitmap = Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.ARGB_8888); // 设置位图的宽高 canvas = new Canvas(); canvas.setBitmap(bitmap); paint=new Paint(Paint.DITHER_FLAG); paint.setAntiAlias(true); paint.setColor(Color.RED); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(5); paint.setAlpha(100); paint.setShadowLayer(10, 0, 0, Color.RED); int[] mColors = new int[] { Color.TRANSPARENT,Color.RED }; float[] mPositions = new float[] { 0f, 0.1f }; Shader shader=new RadialGradient(screenWidth / 2,screenHeight / 2,width / 2 + 10,mColors, mPositions, Shader.TileMode.MIRROR); paint.setShader(shader); canvas.drawCircle(screenWidth / 2, (screenHeight - statusHeight) / 2, width / 2 + 10, paint); invalidate(); } @Override protected void onDraw(Canvas canvas) { canvas.drawBitmap(bitmap,0,0,null); } }
代码与上面差不多,就不注释了。
㈡实现Activity即可
public class XiuYiXiuActivity extends AppCompatActivity { private ImageButton mImageButton; private LYJCircleView lyjCircleView; private RelativeLayout relativeLayout; private List<LYJCircleView> lyjCircleViewList; private int statusBarHeight; private Animator anim; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.xiuyixiu_activity_main); this.mImageButton=(ImageButton)findViewById(R.id.xiuyixiu_imagebutton); this.relativeLayout=(RelativeLayout)findViewById(R.id.xiuyixiu_relativelayout); this.lyjCircleViewList=new ArrayList<>(); this.mImageButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { lyjCircleView.setVisibility(View.GONE);//发射圆圈,即将循环动画View隐藏 final LYJCircleView item=new LYJCircleView(XiuYiXiuActivity.this, mImageButton.getWidth(), mImageButton.getHeight(), statusBarHeight); Animator spreadAnim = AnimatorInflater.loadAnimator(XiuYiXiuActivity.this, R.animator.circle_spread_animator); spreadAnim.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { item.setIsSpreadFlag(true);//动画执行完成,标记一下 } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); spreadAnim.setTarget(item); spreadAnim.start(); lyjCircleViewList.add(item); relativeLayout.addView(item); relativeLayout.invalidate(); Message message = handler.obtainMessage(1); handler.sendMessageDelayed(message, 10); //发送message,定时释放LYJCircleView } }); } private Handler handler = new Handler(){ public void handleMessage(Message msg){ switch (msg.what) { case 1: for(int i=0;i<lyjCircleViewList.size();i++){ if(lyjCircleViewList.get(i).isSpreadFlag()){ relativeLayout.removeView(lyjCircleViewList.get(i)); lyjCircleViewList.remove(i); relativeLayout.invalidate(); } } if(lyjCircleViewList.size()<=0){ lyjCircleView.setVisibility(View.VISIBLE); } Message message = handler.obtainMessage(1); handler.sendMessageDelayed(message, 10); } super.handleMessage(msg); } }; @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); //获取状态栏高度 Rect frame = new Rect(); getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); statusBarHeight = frame.top; this.mImageButton.post(new Runnable() { @Override public void run() { lyjCircleView = new LYJCircleView(XiuYiXiuActivity.this, mImageButton.getWidth(), mImageButton.getHeight(), statusBarHeight); relativeLayout.addView(lyjCircleView); relativeLayout.postInvalidate(); // 加载动画 anim = AnimatorInflater.loadAnimator(XiuYiXiuActivity.this, R.animator.circle_scale_animator); anim.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { anim.start();//循环执行动画 } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); anim.setTarget(lyjCircleView); anim.start(); } }); } }
㈢布局文件代码如下:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/xiuyixiu_relativelayout" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageButton android:id="@+id/xiuyixiu_imagebutton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:background="@drawable/bwa_homepage_yuyin"/> </RelativeLayout>
当然上面两个实现方法,我都只设置圆边框,没有填充,你可以设置为填充后,在微调渐变值。
其效果图如下:
3.Android 5.0逆天实现咻一咻
这个仅标记出来,不做讲解,不过有几个知识提示一下,你就明白了,不过此种方式实现只兼容5.0以上设备,不兼容5.0以下设备。我们都知道5.0中提供如下两个属性:
android:background="?android:attr/selectableItemBackground"波纹有边界
android:background="?android:attr/selectableItemBackgroundBorderless"波纹超出边界
设置下面这个就会绘制一个圆形的波纹(不管你的控件是不是圆形)。
通过android:colorControlHighlight设置波纹颜色。
那么好了就,介绍这么多了,时间匆促,要过年了。
相关文章推荐
- JavaWeb将数据包装成JSON以及JSP通过ajax对JSON的获取与解析(代码实例)
- 阿里云虚拟主机下载AKP失败解决办法
- zoj1025 dp(呃。。)
- 【Java】java使用反射访问对象方法和成员变量
- poj 1696 Space Ant(模拟+叉积)
- 数据结构实验之排序四:寻找大富翁
- nyoj 1237 最大岛屿(dfs)
- 单片机片内存储器烧写
- 第7讲项目3——发工资
- 使用DataGridView进行增删改查 并同步到数据库
- C语言 gets()和scanf()函数的区别
- [Leetcode]201. Bitwise AND of Numbers Range @python
- Java [Leetcode 223]Rectangle Area
- c++自制Redis数据库(三)初步基础框架设计
- 最简单的python命令解析器
- 数据结构实验之排序六:希尔排序
- 四大组件的工作过程
- Html表格<table>还是须要加入一些标签进行优化,能够加入标题<caption>和摘要<table summary>
- 118. Pascal's Triangle && 119. Pascal's Triangle II
- 数据结构实验之排序五:归并求逆序数