最近要做一個抽獎活動因為比較空閑所以花時間看了一下,哈哈,下面記錄一下
繪制文字:主要求出圓弧長度,再計算出文字長度,(圓弧長-文字長)/2=文字離兩邊的距離(文字居中處理)
還用到了在線圖片的下載和保存以及展示
支持滑動到指定的位置
上傳gif老是失敗,先看看圖片
上代碼
package cn.wangxiao.crm.myprizedemo;import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewCompat;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.assist.ImageSize;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.UUID;/*** Created by ytt on 2018/3/2.*/public class MyPrizeView extends View {private static final String IN_PATH = "/Android/pic/";private List<MyPrizeBean> myPrizeList;/*** 當前控件的寬高*/private int minWidthAndHeight;/*** 當前控件的半徑*/private int radius;/*** 寫字和畫圓弧的畫筆*/Paint mTextPaint;Paint mBgPaint;/*** 當前角度*/int initAngle = 0;/*** 每一個獎品占的角度,例如 六個獎品,sweepAngle=360/6*/int sweepAngle;private Canvas mCanvas;public MyPrizeView(Context context) {this(context, null);}public MyPrizeView(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public MyPrizeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initView();}private void initView() {mTextPaint = new Paint();mTextPaint.setAntiAlias(true);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);Log.i("ytt", "MyPrizeView: onSizeChanged");//獲取寬高minWidthAndHeight = Math.min(w, h);radius = minWidthAndHeight / 2;}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);mCanvas = canvas;if (myPrizeList != null && myPrizeList.size() > 0) {mTextPaint.setTextSize(radius / 10);//每一個獎品占有的角度sweepAngle = 360 / myPrizeList.size();for (int i = 0; i < myPrizeList.size(); i++) {RectF rectF = new RectF(0, 0, minWidthAndHeight, minWidthAndHeight);if (i % 2 == 0) {mTextPaint.setColor(Color.rgb(255, 133, 132));} else {mTextPaint.setColor(Color.rgb(254, 104, 105));}//繪制圓弧canvas.drawArc(rectF, initAngle, sweepAngle, true, mTextPaint);//繪制文字mTextPaint.setColor(Color.WHITE);drawCurrentText(rectF, initAngle, sweepAngle, myPrizeList.get(i).text, canvas);//繪制圖片if (!TextUtils.isEmpty(myPrizeList.get(i).address)) {if (myPrizeList.get(i).myBitmap != null) {drawCurrentPicture(initAngle, myPrizeList.get(i).myBitmap);} else {myPrizeList.get(i).myBitmap = BitmapFactory.decodeFile(myPrizeList.get(i).address);drawCurrentPicture(initAngle, myPrizeList.get(i).myBitmap);Log.i("ytt", "地址:" + myPrizeList.get(i).address);}} else {//加載網絡圖片loadingPicture(i, myPrizeList.get(i).icon);}initAngle += sweepAngle;}}initAngle = initAngle % 360;}/*** 繪制文字*/private void drawCurrentText(RectF rectF, int angle, int sweepAngle, String text, Canvas canvas) {Path path = new Path();path.addArc(rectF, angle, sweepAngle);float textWidth = mTextPaint.measureText(text);Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();//圓弧的水平偏移 先計算出弧長 減去文字長度/2的長度就是距離兩邊的距離float hOffset = (float) (2*Math.PI*radius * sweepAngle/360-textWidth)/2;//圓弧的垂直偏移,文字的高度float vOffset = Math.abs(fontMetrics.top - fontMetrics.bottom);canvas.drawTextOnPath(text, path, hOffset, vOffset, mTextPaint);}/*** 繪制圖片*/private void drawCurrentPicture(int startAngle, Bitmap myBitmap) {// 設置圖片的寬度int imgWidth = minWidthAndHeight / (myPrizeList.size() <= 3 ? myPrizeList.size() + 2 : myPrizeList.size());float angle = (float) ((360 / myPrizeList.size() / 2 + startAngle) * (Math.PI / 180));int x = (int) (radius + minWidthAndHeight / 2 / 2 * Math.cos(angle));int y = (int) (radius + minWidthAndHeight / 2 / 2 * Math.sin(angle));int addInt = imgWidth / 2;RectF rect = new RectF(x - addInt, y - addInt, x + addInt, y + addInt);if (myBitmap != null && !myBitmap.isRecycled()) {mCanvas.drawBitmap(myBitmap, null, rect, null);}}/**** 加載網絡圖片* */private void loadingPicture(final int position, final String address) {if (TextUtils.isEmpty(address)) {return;}/*** 設置ImageSize和DisplayImageOptions避免圖片太大,占用內存太多* */ImageLoader.getInstance().loadImage(address, new ImageSize(50, 50), DisplayImageOptions.createSimple(), new SimpleImageLoadingListener() {@Overridepublic void onLoadingCancelled(String imageUri, View view) {super.onLoadingCancelled(imageUri, view);Log.i("ytt", "圖片加載onLoadingCancelled " + position);}@Overridepublic void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {super.onLoadingComplete(imageUri, view, loadedImage);Log.i("ytt", "圖片加載完成onLoadingComplete " + position);if (myPrizeList != null && myPrizeList.size() > position) {myPrizeList.get(position).address = saveBitmap(loadedImage);ViewCompat.postInvalidateOnAnimation(MyPrizeView.this);}}@Overridepublic void onLoadingFailed(String imageUri, View view, FailReason failReason) {super.onLoadingFailed(imageUri, view, failReason);Log.i("ytt", "圖片加載onLoadingFailed " + position);}});}/*** 隨機生產文件名** @return*/private static String generateFileName() {return UUID.randomUUID().toString();}/*** 保存bitmap到本地** @param* @param mBitmap* @return*/public String saveBitmap(Bitmap mBitmap) {String savePath;File filePic;savePath = getContext().getApplicationContext().getFilesDir().getAbsolutePath() + IN_PATH;try {filePic = new File(savePath + generateFileName() + ".jpg");if (!filePic.exists()) {filePic.getParentFile().mkdirs();filePic.createNewFile();}FileOutputStream fos = new FileOutputStream(filePic);mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);fos.flush();fos.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();return null;}return filePic.getAbsolutePath();}public void setListData(List<MyPrizeBean> myPrizeList) {this.myPrizeList = myPrizeList;invalidate();}/*** 開始轉動*/public void startRotate(int position) {//算出未轉動時的角度int currentAngle = 360 - (position - 1) * sweepAngle + 270 - sweepAngle / 2 + 360 * 2;ValueAnimator animtor = ValueAnimator.ofInt(initAngle % 360, currentAngle + initAngle / 360 * 360);animtor.setInterpolator(new AccelerateDecelerateInterpolator());animtor.setDuration(2500);animtor.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {int updateValue = (int) animation.getAnimatedValue();initAngle = (updateValue % 360 + 360) % 360;ViewCompat.postInvalidateOnAnimation(MyPrizeView.this);}});animtor.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {super.onAnimationEnd(animation);}});animtor.start();}}
主要的實現類
xml中的寫法
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="cn.wangxiao.crm.myprizedemo.MainActivity"><cn.wangxiao.crm.myprizedemo.MyPrizeViewandroid:id="@+id/myPrizeView"android:layout_width="match_parent"android:layout_marginTop="20dp"android:layout_height="match_parent"android:text="Hello World!"tools:layout_editor_absoluteX="8dp"tools:layout_editor_absoluteY="8dp" /><EditTextandroid:id="@+id/edittext"android:layout_width="match_parent"android:layout_alignParentBottom="true"android:layout_height="wrap_content" /><Buttonandroid:id="@+id/xixi"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="30dp"android:text="開始" /></RelativeLayout>
主要調用類
package cn.wangxiao.crm.myprizedemo;import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;import java.util.ArrayList;
import java.util.List;public class MainActivity extends AppCompatActivity {private MyPrizeView myPrizeView;private String[] string = new String[]{"https://cdn.duitang.com/uploads/item/201506/29/20150629091228_aF2WC.jpeg", "http://pic13.nipic.com/20110421/7074946_131907700142_2.jpg","http://pic.58pic.com/58pic/15/39/80/91k58PICXEU_1024.jpg", "http://scimg.jb51.net/allimg/160706/103-160F6095531355.jpg", "http://pic23.photophoto.cn/20120624/0010023982061468_b.jpg"};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ImageLoader imageLoader = ImageLoader.getInstance();imageLoader.init(ImageLoaderConfiguration.createDefault(this));myPrizeView = (MyPrizeView) findViewById(R.id.myPrizeView);final EditText editText = (EditText) findViewById(R.id.edittext);findViewById(R.id.xixi).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// myPrizeView.startRotate(1);setNumber(Integer.parseInt(editText.getText().toString().trim()) );}});}public void setNumber(int number) {List<MyPrizeBean> myPrizeBeanList = new ArrayList<>();for (int i = 0; i < number; i++) {MyPrizeBean bean = new MyPrizeBean();bean.text = "" + (i + 1);bean.icon = string[i % string.length];myPrizeBeanList.add(bean);}myPrizeView.setListData(myPrizeBeanList);myPrizeView.startRotate(number);}
}
好了好了,不玩了,就是這樣的,三個類就可以跑
有用到imageLoade
在app/build.gradle中添加
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
需要在項目入口初始化
ImageLoader imageLoader = ImageLoader.getInstance();imageLoader.init(ImageLoaderConfiguration.createDefault(this));
就可以跑啦
項目地址: https://github.com/ytttp/MyPrizeDemo
總結
以上是生活随笔為你收集整理的绘制圆形抽奖转盘的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。