안 드 로 이 드 모방 물결 무늬 트 래 픽 볼 진도 바 컨트롤 러
효과 그림:
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();
}
}
코드 다운로드:안 드 로 이 드 모방 물결 무늬 트 래 픽 볼 진도 바이상 은 본 고의 모든 내용 입 니 다.여러분 이 안 드 로 이 드 소프트웨어 프로 그래 밍 을 배 우 는 데 도움 이 되 기 를 바 랍 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.