星辰小队针对于软件“星遇”的10天冲刺——第7天
日期:2019.5.11
博客期:077
星期六
这都已经第七天了,我好像还没有把这个雷达搞定好!嗯~~~怎么它就是不出来呢?
我把昨天代码里的LogUntils和DisplayUntils当作一个新的Java类,进行了详细的琢磨,我发现这个LogUntil就是一个消息传递的表现手法,而另一个则是长度转换的工具!
明天要去西柏坡社会实践,所以应该是不会有太大的进度的,今天做的也不是很多!
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package basic; 2 3 import android.content.Context; 4 import android.graphics.Bitmap; 5 import android.graphics.BitmapFactory; 6 import android.graphics.Canvas; 7 import android.graphics.Paint; 8 import android.graphics.Rect; 9 import android.util.AttributeSet; 10 import android.view.View; 11 12 import com.example.radar.R; 13 14 public class CircleView extends View { 15 private Paint mPaint; 16 private Bitmap mBitmap; 17 private float radius = DisplayUtils.dp2px(getContext(),9);//半径 18 private float disX;//位置X 19 private float disY;//位置Y 20 private float angle;//旋转的角度 21 private float proportion;//根据远近距离的不同计算得到的应该占的半径比例 22 23 public float getProportion() { 24 return proportion; 25 } 26 27 public void setProportion(float proportion) { 28 this.proportion = proportion; 29 } 30 31 public float getAngle() { 32 return angle; 33 } 34 35 public void setAngle(float angle) { 36 this.angle = angle; 37 } 38 39 public float getDisX() { 40 return disX; 41 } 42 43 public void setDisX(float disX) { 44 this.disX = disX; 45 } 46 47 public float getDisY() { 48 return disY; 49 } 50 51 public void setDisY(float disY) { 52 this.disY = disY; 53 } 54 55 public CircleView(Context context) { 56 this(context, null); 57 } 58 59 public CircleView(Context context, AttributeSet attrs) { 60 this(context, attrs, 0); 61 } 62 63 public CircleView(Context context, AttributeSet attrs, int defStyleAttr) { 64 super(context, attrs, defStyleAttr); 65 init(); 66 } 67 68 private void init() { 69 mPaint = new Paint(); 70 mPaint.setColor(getResources().getColor(R.color.bg_color_pink)); 71 mPaint.setAntiAlias(true); 72 } 73 74 @Override 75 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 76 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 77 setMeasuredDimension(measureSize(widthMeasureSpec), measureSize(heightMeasureSpec)); 78 } 79 80 private int measureSize(int measureSpec) { 81 int result = 0; 82 int specMode = MeasureSpec.getMode(measureSpec); 83 int specSize = MeasureSpec.getSize(measureSpec); 84 if (specMode == MeasureSpec.EXACTLY) { 85 result = specSize; 86 } else { 87 result = (int)DisplayUtils.dp2px(getContext(),18); 88 if (specMode == MeasureSpec.AT_MOST) { 89 result = Math.min(result, specSize); 90 } 91 } 92 return result; 93 } 94 95 96 @Override 97 protected void onDraw(Canvas canvas) { 98 canvas.drawCircle(radius, radius, radius, mPaint); 99 if (mBitmap != null) { 100 canvas.drawBitmap(mBitmap, null, new Rect(0, 0, 2 * (int) radius, 2 * (int) radius), mPaint); 101 } 102 } 103 104 public void setPaintColor(int resId) { 105 mPaint.setColor(resId); 106 invalidate(); 107 } 108 109 public void setPortraitIcon(int resId) { 110 mBitmap = BitmapFactory.decodeResource(getResources(), resId); 111 invalidate(); 112 } 113 public void clearPortaitIcon(){ 114 mBitmap = null; 115 invalidate(); 116 } 117 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package basic; 2 3 import android.content.Context; 4 import android.support.v4.view.ViewPager; 5 import android.util.AttributeSet; 6 import android.view.MotionEvent; 7 8 public class CustomViewPager extends ViewPager { 9 private long downTime; 10 private float LastX; 11 private float mSpeed; 12 13 public CustomViewPager(Context context) { 14 super(context); 15 } 16 17 public CustomViewPager(Context context, AttributeSet attrs) { 18 super(context, attrs); 19 } 20 21 @Override 22 public boolean dispatchTouchEvent(MotionEvent ev) { 23 float x = ev.getX(); 24 switch (ev.getAction()) { 25 case MotionEvent.ACTION_DOWN: 26 downTime = System.currentTimeMillis(); 27 LastX = x; 28 break; 29 case MotionEvent.ACTION_MOVE: 30 x = ev.getX(); 31 break; 32 case MotionEvent.ACTION_UP: 33 //计算得到手指从按下到离开的滑动速度 34 mSpeed = (x - LastX) * 1000 / (System.currentTimeMillis() - downTime); 35 break; 36 } 37 return super.dispatchTouchEvent(ev); 38 } 39 40 public float getSpeed() { 41 return mSpeed; 42 } 43 44 public void setSpeed(float mSpeed) { 45 this.mSpeed = mSpeed; 46 } 47 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package basic; 2 3 import android.app.Activity; 4 import android.content.Context; 5 import android.util.DisplayMetrics; 6 7 /** * dp、sp 转换为 px 的工具类 * * Created by sunfusheng on 16/5/31. */ 8 public class DisplayUtils { 9 // 将px值转换为dip或dp值,保证尺寸大小不变 10 public static int px2dip(Context context, float pxValue) { 11 final float scale = context.getResources().getDisplayMetrics().density; 12 return (int) (pxValue / scale + 0.5f); 13 } 14 // 将dip或dp值转换为px值,保证尺寸大小不变 15 public static int dip2px(Context context, float dipValue) { 16 final float scale = context.getResources().getDisplayMetrics().density; 17 return (int) (dipValue * scale + 0.5f); 18 } 19 // 将px值转换为sp值,保证文字大小不变 20 public static int px2sp(Context context, float pxValue) { 21 final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 22 return (int) (pxValue / fontScale + 0.5f); 23 } 24 // 将sp值转换为px值,保证文字大小不变 25 public static int sp2px(Context context, float spValue) { 26 final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 27 return (int) (spValue * fontScale + 0.5f); 28 } 29 // 屏幕宽度(像素) 30 public static int getWindowWidth(Activity context) { 31 DisplayMetrics metric = new DisplayMetrics(); 32 context.getWindowManager().getDefaultDisplay().getMetrics(metric); 33 return metric.widthPixels; 34 } 35 // 屏幕高度(像素) 36 public static int getWindowHeight(Activity context) { 37 DisplayMetrics metric = new DisplayMetrics(); 38 context.getWindowManager().getDefaultDisplay().getMetrics(metric); 39 return metric.heightPixels; 40 } 41 42 public static float dp2px(Context context, int i) { 43 return dip2px(context,i); 44 } 45 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package basic; 2 3 import android.content.Context; 4 5 import android.view.animation.Interpolator; 6 import android.widget.Scroller; 7 8 public class FixedSpeedScroller extends Scroller { 9 private int mDuration = 0; 10 public FixedSpeedScroller(Context context) { 11 super(context); 12 } 13 public FixedSpeedScroller(Context context, Interpolator interpolator) { 14 super(context, interpolator); 15 } 16 public FixedSpeedScroller(Context context, Interpolator interpolator, boolean flywheel) { 17 super(context, interpolator, flywheel); 18 } 19 @Override 20 public void startScroll(int startX, int startY, int dx, int dy, int duration) { 21 super.startScroll(startX, startY, dx, dy, mDuration); 22 } 23 @Override 24 public void startScroll(int startX, int startY, int dx, int dy) { 25 super.startScroll(startX, startY, dx, dy, mDuration); 26 } 27 28 public void setmDuration(int duration) { 29 mDuration = duration; 30 } 31 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package basic; 2 3 public class Info { 4 private int portraitId;//头像id 5 private String name;//名字 6 private String age;//年龄 7 private boolean sex;//false为男,true为女 8 private float distance;//距离 9 private String password;//密码 10 11 public int getPortraitId() { 12 return portraitId; 13 } 14 15 public void setPortraitId(int portraitId) { 16 this.portraitId = portraitId; 17 } 18 public void setPassword(String password){ 19 this.password = password; 20 } 21 public String getPassword() { 22 return password; 23 } 24 25 public String getAge() { 26 return age; 27 } 28 29 public void setAge(String age) { 30 this.age = age; 31 } 32 33 public float getDistance() { 34 return distance; 35 } 36 37 public void setDistance(float distance) { 38 this.distance = distance; 39 } 40 41 public String getName() { 42 return name; 43 } 44 45 public void setName(String name) { 46 this.name = name; 47 } 48 49 public boolean getSex() { 50 return sex; 51 } 52 53 public void setSex(boolean sex) { 54 this.sex = sex; 55 } 56 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package basic; 2 3 import android.util.Log; 4 5 /** 6 * Used 实现自由的控制日志的打印--《第一行代码》 郭霖 7 * 只有当LEVEL常量的值大于或等于对应日志级别值的时候,才会打印日志。 8 * 开发阶段,将LEVEL赋值为VERBOSE,上线阶段将LEVEL赋值为NOTHING 9 */ 10 public class LogUtil { 11 public static final int VERBOSE = 1; 12 public static final int DEBUG = 2; 13 public static final int INFO = 3; 14 public static final int WARN = 4; 15 public static final int ERROR = 5; 16 public static final int NOTHING = 6; 17 /**控制想要打印的日志级别 18 * 等于VERBOSE,则就会打印所有级别的日志 19 * 等于WARN,则只会打印警告级别以上的日志 20 * 等于NOTHING,则会屏蔽掉所有日志*/ 21 public static final int LEVEL = VERBOSE; 22 23 24 public static void v(String tag, String msg){ 25 if(LEVEL <= VERBOSE){ 26 Log.v(tag, msg); 27 } 28 } 29 30 public static void d(String tag, String msg){ 31 if(LEVEL <= DEBUG){ 32 Log.d(tag, msg); 33 } 34 } 35 36 public static void i(String tag, String msg){ 37 if(LEVEL <= INFO){ 38 Log.i(tag, msg); 39 } 40 } 41 42 public static void w(String tag, String msg){ 43 if(LEVEL <= WARN){ 44 Log.w(tag, msg); 45 } 46 } 47 48 public static void e(String tag, String msg){ 49 if(LEVEL <= ERROR){ 50 Log.e(tag, msg); 51 } 52 } 53 54 public static void m(String tag) { 55 if(LEVEL <= NOTHING) 56 Log.i(tag,""); 57 } 58 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package basic; 2 3 import android.content.Context; 4 import android.graphics.Bitmap; 5 import android.graphics.BitmapFactory; 6 import android.graphics.Canvas; 7 import android.graphics.Color; 8 import android.graphics.Matrix; 9 import android.graphics.Paint; 10 import android.graphics.Rect; 11 import android.graphics.Shader; 12 import android.graphics.SweepGradient; 13 import android.util.AttributeSet; 14 import android.view.View; 15 16 import com.example.radar.R; 17 18 public class RadarView extends View { 19 private Paint mPaintLine;//画圆线需要用到的paint 20 private Paint mPaintCircle;//画圆需要用到的paint 21 private Paint mPaintScan;//画扫描需要用到的paint 22 23 private int mWidth, mHeight;//整个图形的长度和宽度 24 25 private Matrix matrix = new Matrix();//旋转需要的矩阵 26 private int scanAngle;//扫描旋转的角度 27 private Shader scanShader;//扫描渲染shader 28 private Bitmap centerBitmap;//最中间icon 29 30 //每个圆圈所占的比例 31 private static float[] circleProportion = {1 / 13f, 2 / 13f, 3 / 13f, 4 / 13f, 5 / 13f, 6 / 13f}; 32 private int scanSpeed = 5; 33 34 private int currentScanningCount;//当前扫描的次数 35 private int currentScanningItem;//当前扫描显示的item 36 private int maxScanItemCount;//最大扫描次数 37 private boolean startScan = false;//只有设置了数据后才会开始扫描 38 private IScanningListener iScanningListener;//扫描时监听回调接口 39 40 public void setScanningListener(IScanningListener iScanningListener) { 41 this.iScanningListener = iScanningListener; 42 } 43 44 private Runnable run = new Runnable() { 45 @Override 46 public void run() { 47 scanAngle = (scanAngle + scanSpeed) % 360; 48 matrix.postRotate(scanSpeed, mWidth / 2, mHeight / 2); 49 invalidate(); 50 postDelayed(run, 130); 51 //开始扫描显示标志为true 且 只扫描一圈 52 if (startScan && currentScanningCount <= (360 / scanSpeed)) { 53 if (iScanningListener != null && currentScanningCount % scanSpeed == 0 54 && currentScanningItem < maxScanItemCount) { 55 56 iScanningListener.onScanning(currentScanningItem, scanAngle); 57 currentScanningItem++; 58 } else if (iScanningListener != null && currentScanningItem == maxScanItemCount) { 59 iScanningListener.onScanSuccess(); 60 } 61 currentScanningCount++; 62 } 63 } 64 }; 65 66 public RadarView(Context context) { 67 this(context, null); 68 } 69 70 public RadarView(Context context, AttributeSet attrs) { 71 this(context, attrs, 0); 72 } 73 74 public RadarView(Context context, AttributeSet attrs, int defStyleAttr) { 75 super(context, attrs, defStyleAttr); 76 init(); 77 post(run); 78 } 79 80 81 private void init() { 82 mPaintLine = new Paint(); 83 mPaintLine.setColor(getResources().getColor(R.color.line_color_blue)); 84 mPaintLine.setAntiAlias(true); 85 mPaintLine.setStrokeWidth(1); 86 mPaintLine.setStyle(Paint.Style.STROKE); 87 88 mPaintCircle = new Paint(); 89 mPaintCircle.setColor(Color.WHITE); 90 mPaintCircle.setAntiAlias(true); 91 92 mPaintScan = new Paint(); 93 mPaintScan.setStyle(Paint.Style.FILL_AND_STROKE); 94 } 95 96 @Override 97 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 98 setMeasuredDimension(measureSize(widthMeasureSpec), measureSize(widthMeasureSpec)); 99 mWidth = getMeasuredWidth(); 100 mHeight = getMeasuredHeight(); 101 mWidth = mHeight = Math.min(mWidth, mHeight); 102 centerBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.circle_photo); 103 //设置扫描渲染的shader 104 scanShader = new SweepGradient(mWidth / 2, mHeight / 2, 105 new int[]{Color.TRANSPARENT, Color.parseColor("#84B5CA")}, null); 106 } 107 108 private int measureSize(int measureSpec) { 109 int result = 0; 110 int specMode = MeasureSpec.getMode(measureSpec); 111 int specSize = MeasureSpec.getSize(measureSpec); 112 if (specMode == MeasureSpec.EXACTLY) { 113 result = specSize; 114 } else { 115 result = 300; 116 if (specMode == MeasureSpec.AT_MOST) { 117 result = Math.min(result, specSize); 118 } 119 } 120 return result; 121 } 122 123 @Override 124 protected void onDraw(Canvas canvas) { 125 drawCircle(canvas); 126 drawScan(canvas); 127 drawCenterIcon(canvas); 128 } 129 130 /** 131 * 绘制圆线圈 132 * 133 * @param canvas 134 */ 135 private void drawCircle(Canvas canvas) { 136 canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth * circleProportion[1], mPaintLine); // 绘制小圆 137 canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth * circleProportion[2], mPaintLine); // 绘制中圆 138 canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth * circleProportion[3], mPaintLine); // 绘制中大圆 139 canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth * circleProportion[4], mPaintLine); // 绘制大圆 140 canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth * circleProportion[5], mPaintLine); // 绘制大大圆 141 } 142 143 /** 144 * 绘制扫描 145 * 146 * @param canvas 147 */ 148 private void drawScan(Canvas canvas) { 149 canvas.save(); 150 mPaintScan.setShader(scanShader); 151 canvas.concat(matrix); 152 canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth * circleProportion[4], mPaintScan); 153 canvas.restore(); 154 } 155 156 /** 157 * 绘制最中间的图标 158 * 159 * @param canvas 160 */ 161 private void drawCenterIcon(Canvas canvas) { 162 canvas.drawBitmap(centerBitmap, null, 163 new Rect((int) (mWidth / 2 - mWidth * circleProportion[0]), (int) (mHeight / 2 - mWidth * circleProportion[0]), 164 (int) (mWidth / 2 + mWidth * circleProportion[0]), (int) (mHeight / 2 + mWidth * circleProportion[0])), mPaintCircle); 165 } 166 167 168 public interface IScanningListener { 169 //正在扫描(此时还没有扫描完毕)时回调 170 void onScanning(int position, float scanAngle); 171 172 //扫描成功时回调 173 void onScanSuccess(); 174 } 175 176 public void setMaxScanItemCount(int maxScanItemCount) { 177 this.maxScanItemCount = maxScanItemCount; 178 } 179 180 /** 181 * 开始扫描 182 */ 183 public void startScan() { 184 this.startScan = true; 185 } 186 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package basic; 2 3 import android.animation.ObjectAnimator; 4 import android.content.Context; 5 import android.util.AttributeSet; 6 import android.util.SparseArray; 7 import android.view.View; 8 import android.view.ViewGroup; 9 10 import com.example.radar.R; 11 12 public class RadarViewGroup extends ViewGroup implements RadarView.IScanningListener { 13 private int mWidth, mHeight;//viewgroup的宽高 14 private SparseArray<Float> scanAngleList = new SparseArray<>();//记录展示的item所在的扫描位置角度 15 private SparseArray<Info> mDatas;//数据源 16 private int dataLength;//数据源长度 17 private int minItemPosition;//最小距离的item所在数据源中的位置 18 private CircleView currentShowChild;//当前展示的item 19 private CircleView minShowChild;//最小距离的item 20 private IRadarClickListener iRadarClickListener;//雷达图中点击监听CircleView小圆点回调接口 21 22 public void setiRadarClickListener(IRadarClickListener iRadarClickListener) { 23 this.iRadarClickListener = iRadarClickListener; 24 } 25 26 public RadarViewGroup(Context context) { 27 this(context, null); 28 } 29 30 public RadarViewGroup(Context context, AttributeSet attrs) { 31 this(context, attrs, 0); 32 } 33 34 public RadarViewGroup(Context context, AttributeSet attrs, int defStyleAttr) { 35 super(context, attrs, defStyleAttr); 36 } 37 38 39 @Override 40 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 41 setMeasuredDimension(measureSize(widthMeasureSpec), measureSize(heightMeasureSpec)); 42 mWidth = getMeasuredWidth(); 43 mHeight = getMeasuredHeight(); 44 mWidth = mHeight = Math.min(mWidth, mHeight); 45 //测量每个children 46 measureChildren(widthMeasureSpec, heightMeasureSpec); 47 for (int i = 0; i < getChildCount(); i++) { 48 View child = getChildAt(i); 49 if (child.getId() == R.id.id_scan_circle) { 50 //为雷达扫描图设置需要的属性 51 ((RadarView) child).setScanningListener(this); 52 //考虑到数据没有添加前扫描图在扫描,但是不会开始为CircleView布局 53 if (mDatas != null && mDatas.size() > 0) { 54 ((RadarView) child).setMaxScanItemCount(mDatas.size()); 55 ((RadarView) child).startScan(); 56 } 57 continue; 58 } 59 } 60 } 61 62 @Override 63 protected void onLayout(boolean changed, int l, int t, int r, int b) { 64 int childCount = getChildCount(); 65 //首先放置雷达扫描图 66 View view = findViewById(R.id.id_scan_circle); 67 if (view != null) { 68 view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); 69 } 70 //放置雷达图中需要展示的item圆点 71 for (int i = 0; i < childCount; i++) { 72 final int j = i; 73 final View child = getChildAt(i); 74 if (child.getId() == R.id.id_scan_circle) { 75 //如果不是Circleview跳过 76 continue; 77 } 78 //设置CircleView小圆点的坐标信息 79 //坐标 = 旋转角度 * 半径 * 根据远近距离的不同计算得到的应该占的半径比例 80 ((CircleView) child).setDisX((float) Math.cos(Math.toRadians(scanAngleList.get(i - 1) - 5)) 81 * ((CircleView) child).getProportion() * mWidth / 2); 82 ((CircleView) child).setDisY((float) Math.sin(Math.toRadians(scanAngleList.get(i - 1) - 5)) 83 * ((CircleView) child).getProportion() * mWidth / 2); 84 //如果扫描角度记录SparseArray中的对应的item的值为0, 85 // 说明还没有扫描到该item,跳过对该item的layout 86 //(scanAngleList设置数据时全部设置的value=0, 87 // 当onScanning时,value设置的值始终不会0,具体可以看onScanning中的实现) 88 if (scanAngleList.get(i - 1) == 0) { 89 continue; 90 } 91 //放置Circle小圆点 92 child.layout((int) ((CircleView) child).getDisX() + mWidth / 2, (int) ((CircleView) child).getDisY() + mHeight / 2, 93 (int) ((CircleView) child).getDisX() + child.getMeasuredWidth() + mWidth / 2, 94 (int) ((CircleView) child).getDisY() + child.getMeasuredHeight() + mHeight / 2); 95 //设置点击事件 96 child.setOnClickListener(new OnClickListener() { 97 @Override 98 public void onClick(View v) { 99 resetAnim(currentShowChild); 100 currentShowChild = (CircleView) child; 101 //因为雷达图是childAt(0),所以这里需要作-1才是正确的Circle 102 startAnim(currentShowChild, j - 1); 103 if (iRadarClickListener != null) { 104 iRadarClickListener.onRadarItemClick(j - 1); 105 106 } 107 } 108 }); 109 } 110 111 112 } 113 114 private int measureSize(int measureSpec) { 115 int result = 0; 116 int specMode = MeasureSpec.getMode(measureSpec); 117 int specSize = MeasureSpec.getSize(measureSpec); 118 if (specMode == MeasureSpec.EXACTLY) { 119 result = specSize; 120 } else { 121 result = 300; 122 if (specMode == MeasureSpec.AT_MOST) { 123 result = Math.min(result, specSize); 124 } 125 } 126 return result; 127 128 } 129 130 /** 131 * 设置数据 132 * 133 * @param mDatas 134 */ 135 public void setDatas(SparseArray<Info> mDatas) { 136 this.mDatas = mDatas; 137 dataLength = mDatas.size(); 138 float min = Float.MAX_VALUE; 139 float max = Float.MIN_VALUE; 140 //找到距离的最大值,最小值对应的minItemPosition 141 for (int j = 0; j < dataLength; j++) { 142 Info item = mDatas.get(j); 143 if (item.getDistance() < min) { 144 min = item.getDistance(); 145 minItemPosition = j; 146 } 147 if (item.getDistance() > max) { 148 max = item.getDistance(); 149 } 150 scanAngleList.put(j, 0f); 151 } 152 //根据数据源信息动态添加CircleView 153 for (int i = 0; i < dataLength; i++) { 154 CircleView circleView = new CircleView(getContext()); 155 if (mDatas.get(i).getSex()) { 156 circleView.setPaintColor(getResources().getColor(R.color.bg_color_pink)); 157 } else { 158 circleView.setPaintColor(getResources().getColor(R.color.bg_color_blue)); 159 } 160 //根据远近距离的不同计算得到的应该占的半径比例 0.312-0.832 161 circleView.setProportion((mDatas.get(i).getDistance() / max + 0.6f) * 0.52f); 162 if (minItemPosition == i) { 163 minShowChild = circleView; 164 } 165 addView(circleView); 166 } 167 } 168 169 /** 170 * 雷达图没有扫描完毕时回调 171 * 172 * @param position 173 * @param scanAngle 174 */ 175 @Override 176 public void onScanning(int position, float scanAngle) { 177 if (scanAngle == 0) { 178 scanAngleList.put(position, 1f); 179 } else { 180 scanAngleList.put(position, scanAngle); 181 } 182 requestLayout(); 183 } 184 185 /** 186 * 雷达图扫描完毕时回调 187 */ 188 @Override 189 public void onScanSuccess() { 190 LogUtil.m("完成回调"); 191 resetAnim(currentShowChild); 192 currentShowChild = minShowChild; 193 startAnim(currentShowChild, minItemPosition); 194 } 195 196 /** 197 * 恢复CircleView小圆点原大小 198 * 199 * @param object 200 */ 201 private void resetAnim(CircleView object) { 202 if (object != null) { 203 object.clearPortaitIcon(); 204 ObjectAnimator.ofFloat(object, "scaleX", 1f).setDuration(300).start(); 205 ObjectAnimator.ofFloat(object, "scaleY", 1f).setDuration(300).start(); 206 } 207 208 } 209 210 /** 211 * 放大CircleView小圆点大小 212 * 213 * @param object 214 * @param position 215 */ 216 private void startAnim(CircleView object, int position) { 217 if (object != null) { 218 object.setPortraitIcon(mDatas.get(position).getPortraitId()); 219 ObjectAnimator.ofFloat(object, "scaleX", 2f).setDuration(300).start(); 220 ObjectAnimator.ofFloat(object, "scaleY", 2f).setDuration(300).start(); 221 } 222 } 223 224 /** 225 * 雷达图中点击监听CircleView小圆点回调接口 226 */ 227 public interface IRadarClickListener { 228 void onRadarItemClick(int position); 229 } 230 231 /** 232 * 根据position,放大指定的CircleView小圆点 233 * 234 * @param position 235 */ 236 public void setCurrentShowItem(int position) { 237 CircleView child = (CircleView) getChildAt(position + 1); 238 resetAnim(currentShowChild); 239 currentShowChild = child; 240 startAnim(currentShowChild, position); 241 } 242 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package basic; 2 3 import android.support.v4.view.PagerAdapter; 4 import android.view.LayoutInflater; 5 import android.view.View; 6 import android.view.ViewGroup; 7 import android.widget.ImageView; 8 import android.widget.TextView; 9 import android.widget.Toast; 10 11 import com.example.radar.R; 12 13 import java.util.List; 14 15 public class ViewpagerAdapter extends PagerAdapter { 16 private List<Info> mDatas; 17 //private Object mImgs; 18 19 @Override 20 public Object instantiateItem(final ViewGroup container, final int position) { 21 22 final Info info = mDatas.get(position); 23 //设置一大堆演示用的数据,麻里麻烦~~ 24 View view = LayoutInflater.from(container.getContext()).inflate(R.layout.viewpager_layout, null); 25 ImageView ivPortrait = (ImageView) view.findViewById(R.id.iv); 26 ImageView ivSex = (ImageView) view.findViewById(R.id.iv_sex); 27 TextView tvName = (TextView) view.findViewById(R.id.tv_name); 28 TextView tvDistance = (TextView) view.findViewById(R.id.tv_distance); 29 tvName.setText(info.getName()); 30 tvDistance.setText(info.getDistance() + "km"); 31 ivPortrait.setImageResource(info.getPortraitId()); 32 if (info.getSex()) { 33 ivSex.setImageResource(R.drawable.girl); 34 } else { 35 ivSex.setImageResource(R.drawable.boy); 36 } 37 ivPortrait.setOnClickListener(new View.OnClickListener() { 38 @Override 39 public void onClick(View v) { 40 Toast.makeText(container.getContext() , "这是 " + info.getName() + " >.<", Toast.LENGTH_SHORT).show(); 41 } 42 }); 43 container.addView(view); 44 return view; 45 } 46 47 @Override 48 public int getCount() { 49 return mDatas.size();//mImgs.length; 50 } 51 52 @Override 53 public boolean isViewFromObject(View view, Object object) { 54 return view == object; 55 } 56 57 @Override 58 public void destroyItem(ViewGroup container, int position, Object object) { 59 View view = (View) object; 60 container.removeView(view); 61 } 62 63 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package basic; 2 3 import android.support.v4.view.ViewPager; 4 import android.view.View; 5 6 public class ZoomOutPageTransformer implements ViewPager.PageTransformer { 7 private static final float MIN_SCALE = 0.70f; 8 private static final float MIN_ALPHA = 0.5f; 9 10 public void transformPage(View view, float position) { 11 int pageWidth = view.getWidth(); 12 int pageHeight = view.getHeight(); 13 if (position < -1) { // [-Infinity,-1) 14 // This page is way off-screen to the left. 15 view.setAlpha(MIN_ALPHA); 16 view.setScaleX(MIN_SCALE); 17 view.setScaleY(MIN_SCALE); 18 } else if (position <= 1) { // [-1,1] 19 // Modify the default slide transition to shrink the page as well 20 float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position)); 21 float vertMargin = pageHeight * (1 - scaleFactor) / 2; 22 float horzMargin = pageWidth * (1 - scaleFactor) / 2; 23 if (position < 0) { 24 view.setTranslationX(horzMargin - vertMargin / 2); 25 view.setScaleX(1 + 0.3f * position); 26 view.setScaleY(1 + 0.3f * position); 27 } else { 28 view.setTranslationX(-horzMargin + vertMargin / 2); 29 30 view.setScaleX(1 - 0.3f * position); 31 view.setScaleY(1 - 0.3f * position); 32 } 33 34 // Scale the page down (between MIN_SCALE and 1) 35 36 // Fade the page relative to its size. 37 view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA)); 38 39 } else { // (1,+Infinity] 40 // This page is way off-screen to the right. 41 view.setScaleX(MIN_SCALE); 42 view.setScaleY(MIN_SCALE); 43 view.setAlpha(MIN_ALPHA); 44 } 45 } 46 }