안 드 로 이 드 모방 물결 무늬 트 래 픽 볼 진도 바 컨트롤 러

모방 물결 무늬 흐름 구 진도 조 컨트롤 러,안 드 로 이 드 는 고급 대기의 주류 효 과 를 실현 하여 여러분 께 참고 하 시기 바 랍 니 다.구체 적 인 내용 은 다음 과 같 습 니 다.
효과 그림:

CircleView
여 기 는 주로 중심 원 과 물결 효 과 를 실현 합 니 다.

package com.lgl.circleview;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ProgressBar;

/**
 *    
 * 
 * @author lgl
 * 
 */
public class CircleView extends View {

 private Context mContext;

 private int mScreenWidth;
 private int mScreenHeight;

 private Paint mRingPaint;
 private Paint mCirclePaint;
 private Paint mWavePaint;
 private Paint linePaint;
 private Paint flowPaint;
 private Paint leftPaint;

 private int mRingSTROKEWidth = 15;
 private int mCircleSTROKEWidth = 2;
 private int mLineSTROKEWidth = 1;

 private int mCircleColor = Color.WHITE;
 private int mRingColor = Color.WHITE;
 private int mWaveColor = Color.WHITE;

 private Handler mHandler;
 private long c = 0L;
 private boolean mStarted = false;
 private final float f = 0.033F;
 private int mAlpha = 50;//    
 private float mAmplitude = 10.0F; //   
 private float mWaterLevel = 0.5F;//   (0~1)
 private Path mPath;

 //            ,       ,            
 private String flowNum = "";
 private String flowLeft = "   ";

 /**
  * @param context
  */
 public CircleView(Context context) {
  super(context);
  // TODO Auto-generated constructor stub
  mContext = context;
  init(mContext);
 }

 /**
  * @param context
  * @param attrs
  */
 public CircleView(Context context, AttributeSet attrs) {
  super(context, attrs);
  // TODO Auto-generated constructor stub
  mContext = context;
  init(mContext);
 }

 /**
  * @param context
  * @param attrs
  * @param defStyleAttr
  */
 public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  // TODO Auto-generated constructor stub
  mContext = context;
  init(mContext);
 }

 public void setmWaterLevel(float mWaterLevel) {
  this.mWaterLevel = mWaterLevel;
 }

 private void init(Context context) {
  mRingPaint = new Paint();
  mRingPaint.setColor(mRingColor);
  mRingPaint.setAlpha(50);
  mRingPaint.setStyle(Paint.Style.STROKE);
  mRingPaint.setAntiAlias(true);
  mRingPaint.setStrokeWidth(mRingSTROKEWidth);

  mCirclePaint = new Paint();
  mCirclePaint.setColor(mCircleColor);
  mCirclePaint.setStyle(Paint.Style.STROKE);
  mCirclePaint.setAntiAlias(true);
  mCirclePaint.setStrokeWidth(mCircleSTROKEWidth);

  linePaint = new Paint();
  linePaint.setColor(mCircleColor);
  linePaint.setStyle(Paint.Style.STROKE);
  linePaint.setAntiAlias(true);
  linePaint.setStrokeWidth(mLineSTROKEWidth);

  flowPaint = new Paint();
  flowPaint.setColor(mCircleColor);
  flowPaint.setStyle(Paint.Style.FILL);
  flowPaint.setAntiAlias(true);
  flowPaint.setTextSize(36);

  leftPaint = new Paint();
  leftPaint.setColor(mCircleColor);
  leftPaint.setStyle(Paint.Style.FILL);
  leftPaint.setAntiAlias(true);
  leftPaint.setTextSize(36);

  mWavePaint = new Paint();
  mWavePaint.setStrokeWidth(1.0F);
  mWavePaint.setColor(mWaveColor);
  mWavePaint.setAlpha(mAlpha);
  mPath = new Path();

  mHandler = new Handler() {
   @Override
   public void handleMessage(android.os.Message msg) {
    if (msg.what == 0) {
     invalidate();
     if (mStarted) {
      //         ,        
      mHandler.sendEmptyMessageDelayed(0, 60L);
     }
    }
   }
  };
 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  int width = measure(widthMeasureSpec, true);
  int height = measure(heightMeasureSpec, false);
  if (width < height) {
   setMeasuredDimension(width, width);
  } else {
   setMeasuredDimension(height, height);
  }

 }

 /**
  * @category   
  * @param measureSpec
  * @param isWidth
  * @return
  */
 private int measure(int measureSpec, boolean isWidth) {
  int result;
  int mode = MeasureSpec.getMode(measureSpec);
  int size = MeasureSpec.getSize(measureSpec);
  int padding = isWidth ? getPaddingLeft() + getPaddingRight()
    : getPaddingTop() + getPaddingBottom();
  if (mode == MeasureSpec.EXACTLY) {
   result = size;
  } else {
   result = isWidth ? getSuggestedMinimumWidth()
     : getSuggestedMinimumHeight();
   result += padding;
   if (mode == MeasureSpec.AT_MOST) {
    if (isWidth) {
     result = Math.max(result, size);
    } else {
     result = Math.min(result, size);
    }
   }
  }
  return result;
 }

 @Override
 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  // TODO Auto-generated method stub
  super.onSizeChanged(w, h, oldw, oldh);
  mScreenWidth = w;
  mScreenHeight = h;
 }

 @Override
 protected void onDraw(Canvas canvas) {
  // TODO Auto-generated method stub
  super.onDraw(canvas);
  //        
  int width = getWidth();
  int height = getHeight();
  setBackgroundColor(mContext.getResources().getColor(R.color.main_bg));
  //                
  float centerOffset = Math.abs(mScreenWidth / 2 * mWaterLevel
    - mScreenWidth / 4);
  //               
  float horiAngle = (float) (Math.asin(centerOffset / (mScreenWidth / 4)) * 180 / Math.PI);
  //             
  float startAngle, sweepAngle;
  if (mWaterLevel > 0.5F) {
   startAngle = 360F - horiAngle;
   sweepAngle = 180F + 2 * horiAngle;
  } else {
   startAngle = horiAngle;
   sweepAngle = 180F - 2 * horiAngle;
  }

  canvas.drawLine(mScreenWidth * 3 / 8, mScreenHeight * 5 / 8,
    mScreenWidth * 5 / 8, mScreenHeight * 5 / 8, linePaint);

  float num = flowPaint.measureText(flowNum);
  canvas.drawText(flowNum, mScreenWidth * 4 / 8 - num / 2,
    mScreenHeight * 4 / 8, flowPaint);
  float left = leftPaint.measureText(flowLeft);
  canvas.drawText(flowLeft, mScreenWidth * 4 / 8 - left / 2,
    mScreenHeight * 3 / 8, leftPaint);

  //      (   startWave  ),      
  if ((!mStarted) || (mScreenWidth == 0) || (mScreenHeight == 0)) {
   //   ,         
   RectF oval = new RectF(mScreenWidth / 4, mScreenHeight / 4,
     mScreenWidth * 3 / 4, mScreenHeight * 3 / 4);
   canvas.drawArc(oval, startAngle, sweepAngle, false, mWavePaint);
   return;
  }
  //   ,         
  //   ,         
  RectF oval = new RectF(mScreenWidth / 4, mScreenHeight / 4,
    mScreenWidth * 3 / 4, mScreenHeight * 3 / 4);
  canvas.drawArc(oval, startAngle, sweepAngle, false, mWavePaint);

  if (this.c >= 8388607L) {
   this.c = 0L;
  }
  //   onDraw c    
  c = (1L + c);
  float f1 = mScreenHeight * (1.0F - (0.25F + mWaterLevel / 2))
    - mAmplitude;
  //         
  float waveWidth = (float) Math.sqrt(mScreenWidth * mScreenWidth / 16
    - centerOffset * centerOffset);
  //         
  float offsetWidth = mScreenWidth / 4 - waveWidth;

  int top = (int) (f1 + mAmplitude);
  mPath.reset();
  //     X  ,    X  
  int startX, endX;
  if (mWaterLevel > 0.50F) {
   startX = (int) (mScreenWidth / 4 + offsetWidth);
   endX = (int) (mScreenWidth / 2 + mScreenWidth / 4 - offsetWidth);
  } else {
   startX = (int) (mScreenWidth / 4 + offsetWidth - mAmplitude);
   endX = (int) (mScreenWidth / 2 + mScreenWidth / 4 - offsetWidth + mAmplitude);
  }
  //     
  while (startX < endX) {
   int startY = (int) (f1 - mAmplitude
     * Math.sin(Math.PI
       * (2.0F * (startX + this.c * width * this.f))
       / width));
   canvas.drawLine(startX, startY, startX, top, mWavePaint);
   startX++;
  }
  canvas.drawCircle(mScreenWidth / 2, mScreenHeight / 2, mScreenWidth / 4
    + mRingSTROKEWidth / 2, mRingPaint);

  canvas.drawCircle(mScreenWidth / 2, mScreenHeight / 2,
    mScreenWidth / 4, mCirclePaint);
  canvas.restore();
 }

 @Override
 public Parcelable onSaveInstanceState() {
  Parcelable superState = super.onSaveInstanceState();
  SavedState ss = new SavedState(superState);
  ss.progress = (int) c;
  return ss;
 }

 @Override
 public void onRestoreInstanceState(Parcelable state) {
  SavedState ss = (SavedState) state;
  super.onRestoreInstanceState(ss.getSuperState());
  c = ss.progress;
 }

 @Override
 protected void onAttachedToWindow() {
  super.onAttachedToWindow();
  //       ,    unsupported operation exception
  this.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
 }

 @Override
 protected void onDetachedFromWindow() {
  super.onDetachedFromWindow();
 }

 /**
  * @category     
  */
 public void startWave() {
  if (!mStarted) {
   this.c = 0L;
   mStarted = true;
   this.mHandler.sendEmptyMessage(0);
  }
 }

 /**
  * @category     
  */
 public void stopWave() {
  if (mStarted) {
   this.c = 0L;
   mStarted = false;
   this.mHandler.removeMessages(0);
  }
 }

 /**
  * @category     
  */
 static class SavedState extends BaseSavedState {
  int progress;

  /**
   * Constructor called from {@link ProgressBar#onSaveInstanceState()}
   */
  SavedState(Parcelable superState) {
   super(superState);
  }

  /**
   * Constructor called from {@link #CREATOR}
   */
  private SavedState(Parcel in) {
   super(in);
   progress = in.readInt();
  }

  @Override
  public void writeToParcel(Parcel out, int flags) {
   super.writeToParcel(out, flags);
   out.writeInt(progress);
  }

  public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
   public SavedState createFromParcel(Parcel in) {
    return new SavedState(in);
   }

   public SavedState[] newArray(int size) {
    return new SavedState[size];
   }
  };
 }

}

저희 가 운행 을 해 보도 록 하 겠 습 니 다.

사실 그 는 매우 넓 기 때문에 우리 가 맞 춤 형 제작 을 할 가치 가 있다.우 리 는 중간 에 데이터 디 스 플레이 를 추가 하고 진도 표를 추가 할 가치 가 있다.
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="@color/main_bg" >

 <TextView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_alignParentTop="true"
  android:layout_centerHorizontal="true"
  android:layout_marginTop="10dp"
  android:text="  "
  android:textColor="@android:color/white"
  android:textSize="18sp" />

 <com.lgl.circleview.CircleView
  android:id="@+id/wave_view"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:layout_centerInParent="true" />

 <TextView
  android:id="@+id/power"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_centerInParent="true"
  android:textColor="@android:color/white" />

 <SeekBar
  android:id="@+id/seekBar"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_alignParentBottom="true"
  android:layout_marginBottom="150dp" />

</RelativeLayout>

이것 을 실현 하려 면 초기 화 및 start 방법 을 사용 해 야 합 니 다.

 mCircleView = (CircleView) findViewById(R.id.wave_view);
  //     ,float,0.1-1F
  mCircleView.setmWaterLevel(0.1F);
  //     
  mCircleView.startWave();

   activity          
@Override
 protected void onDestroy() {
  // TODO Auto-generated method stub
  mCircleView.stopWave();
  mCircleView = null;
  super.onDestroy();
 }
저희 가 다시 한 번 운행 을 해 보도 록 하 겠 습 니 다.

하지만 우 리 는 어떻게 물결 을 진도 에 따라 함께 올 라 가게 해 야 합 니까?여기 서 우 리 는 우리 가 방금 쓴 SeekBar 를 사용 해 야 한다.우 리 는 그것 을 실현 할 것 이다.

setOnSeekBarChangeListener   ,              ,          
public void onProgressChanged(SeekBar seekBar, int progress,
     boolean fromUser) {
    //       
    mCircleView.setmWaterLevel((float) progress / 100);
    }
여기 서 우 리 는 이렇게 계산 해 야 한다.우리 가 설정 한 높이 의 단 위 는 float 이다.즉,0-1F 이다.우리 의 진 도 는 int progress 이다.0-100 에서 우 리 는(float)progress/100)을 사용 하고 단 위 를 강하 게 전환 해 야 한다.자,우 리 는 지금 물결 무늬 의 높이 가 우리 의 진도 항목 과 함께 변화 하고 있다.우 리 는 다시 운행 해 보 자.

좋 습 니 다.그러면 우 리 는 하나 밖 에 남지 않 았 습 니 다.바로 크기 를 우리 의 진도 에 따라 변화 시 키 는 것 입 니 다.여기 서 우 리 는 UI 를 업데이트 하기 때문에 메 인 스 레 드 에서 조작 할 수 없 기 때문에 우 리 는 우리 의 오 랜 친구 인 Handler 를 사용 해 야 합 니 다.그러나 handler 를 사용 하 는 것 이 부족 합 니 다.우리 의 진도 항목 수치 도 내부 클래스 에 있 기 때문에 여기 서 우 리 는 Handler 를 사용 하여 값 을 전달 해 야 합 니 다.여기 서 우리 가 사용 하 는 것 은 Bundle 입 니 다.우 리 는 여전히 onProgressChanged 방법 에서 조작 하 였 습 니 다.

 //      
    Message message = new Message();
    Bundle bundle = new Bundle();
    //put  int 
    bundle.putInt("progress", progress);
    //  
    message.setData(bundle);
    //    
    handler.sendMessage(message);
    //    
    message.what = 1;
메 시 지 를 보 냈 으 니 앞에서 Handler 를 써 서 받 으 면 됩 니 다.

 private Handler handler = new Handler() {
  public void handleMessage(android.os.Message msg) {
   if (msg.what == 1) {
    int num = msg.getData().getInt("progress");
    Log.i("num", num + "");
    power.setText((float) num / 100 * max + "M/" + max + "M");
   }
  }
 };
이곳 의 계산 공식 니 는 현재 의 수치/100 을 백분율 로 얻 은 다음*최대 치 입 니 다.우 리 는 이제 완전 하 게 운행 할 수 있 게 되 었 다.사실은 맨 위 에서 운행 하 는 그림 과 같다.

MainActivity

package com.lgl.circleview;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.SeekBar;
import android.widget.TextView;

public class MainActivity extends Activity {

 private CircleView mCircleView;
 private SeekBar mSeekBar;
 private TextView power;
 private int max = 1024;
 private int min = 102;

 private Handler handler = new Handler() {
 public void handleMessage(android.os.Message msg) {
  if (msg.what == 1) {
  int num = msg.getData().getInt("progress");
  Log.i("num", num + "");
  power.setText((float) num / 100 * max + "M/" + max + "M");
  }
 }
 };

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 getActionBar().hide();
 setContentView(R.layout.activity_main);

 power = (TextView) findViewById(R.id.power);
 power.setText(min + "M/" + max + "M");

 mCircleView = (CircleView) findViewById(R.id.wave_view);
 //     ,float,0.1-1F
 mCircleView.setmWaterLevel(0.1F);
 //     
 mCircleView.startWave();

 mSeekBar = (SeekBar) findViewById(R.id.seekBar);
 mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
  @Override
  public void onProgressChanged(SeekBar seekBar, int progress,
   boolean fromUser) {
  mCircleView.setmWaterLevel((float) progress / 100);
  //       
  Message message = new Message();
  Bundle bundle = new Bundle();
  // put  int 
  bundle.putInt("progress", progress);
  //   
  message.setData(bundle);
  //     
  handler.sendMessage(message);
  //     
  message.what = 1;
  }

  @Override
  public void onStartTrackingTouch(SeekBar seekBar) {

  }

  @Override
  public void onStopTrackingTouch(SeekBar seekBar) {

  }
 });
 }

 @Override
 protected void onDestroy() {
 // TODO Auto-generated method stub
 mCircleView.stopWave();
 mCircleView = null;
 super.onDestroy();
 }
}
코드 다운로드:안 드 로 이 드 모방 물결 무늬 트 래 픽 볼 진도 바
이상 은 본 고의 모든 내용 입 니 다.여러분 이 안 드 로 이 드 소프트웨어 프로 그래 밍 을 배 우 는 데 도움 이 되 기 를 바 랍 니 다.

좋은 웹페이지 즐겨찾기