Android 사용자 정의 view 물결 무늬 애니메이션 효과 구현
이런 중요 한 때 에 몸 이 굳 어야 하 는데 절대 안 된다 고 말 하지 마 세 요.남자 가 어떻게 안 된다 고 할 수 있 습 니까?
자,모두 가 여동생 들 이 원 하 는 것 을 줄 수 있 도록 나중에 비교적 좋 은 효 과 를 점차적으로 공유 할 것 입 니 다.목적 은 하나 입 니 다.사용자 정의 view 를 통 해 우리 가 실현 할 수 있 는 동 효 를 실현 하 는 것 입 니 다.
오늘 은 주로 물결 무늬 효과 공유:
1.표준 코사인 물결 무늬;
2.비 표준 원형 액체 기둥 물결 무늬;
비록 모두 물결 무늬 라 고 하지만 이들 은 실현 에 있어 차이 가 비교적 크다.하 나 는 정 코사인 함 수 를 통 해 물결 무늬 효 과 를 모 의 하고 다른 하 나 는 이미지 의 혼합 모델(Porter Duff Xfermode)에 활용 된다.
먼저 효과 보기:
사용자 정의 View 는 실제 상황 에 따라 View,TextView,ImageView 또는 다른 것 을 계승 할 수 있 습 니 다.우 리 는 먼저 안 드 로 이 드 를 이용 하여 우리 에 게 좋 은 칼날 을 제공 하여 UI 여동생 종 이 를 만족 시 키 는 방법 만 알 아야 합 니 다.
이번 실현 은 모두 계승 view 를 선택 합 니 다.실현 하 는 과정 에서 우 리 는 다음 과 같은 몇 가지 방법 에 관심 을 가 져 야 합 니 다.
1.onMeasure():컨트롤 의 측정 에 가장 먼저 리 셋 합 니 다.
2.onSizeChanged():onMeasure 뒤에서 리 셋 하면 view 의 넓 은 고등 데 이 터 를 얻 을 수 있 고 가로 세로 화면 전환 시 리 셋 할 수 있 습 니 다.
3.onDraw():진짜 그리 기 부분 은 그 려 진 코드 를 모두 여기에 씁 니 다.
그렇다면 우 리 는 먼저 이 세 가지 방법 을 복사 한 후에 상기 두 가지 효 과 를 실현 한다.
표준 코사인 물결 무늬
이런 물결 무늬 는 구체 적 인 함수 로 구체 적 인 궤적 을 모 의 할 수 있 기 때문에 사고방식 은 기본적으로 다음 과 같다.
1.물결 함수 방정식 확정
2.함수 방정식 에 따라 모든 파문 상의 좌 표를 얻어 낸다.
3.물결 을 평평 하 게 이동 시 켜 물결 위의 점 이 끊임없이 이동 할 것 이다.
4.끊임없이 다시 그리 기,동적 물결 무늬 생 성;
위의 생각 이 있 으 면 우 리 는 한 걸음 한 걸음 실현 한다.
정 여현 함수 방정식 은 다음 과 같다.
y=Asin(wx+b)+h,이 공식 에서 w 는 주기 에 영향 을 주 고 A 는 진폭 에 영향 을 주 며 h 는 y 위치 에 영향 을 주 고 b 는 초상 이다.
위의 방정식 에 따라 자신 이 마음 에 드 는 파문 효 과 를 선택 하고 해당 하 는 매개 변수의 수 치 를 확인한다.
그 다음 에 확 정 된 방정식 에 따라 모든 방정식 의 y 수 치 를 얻 고 모든 y 수 치 를 배열 에 저장 합 니 다.
// view
mCycleFactorW = (float) (2 * Math.PI / mTotalWidth);
// view y
for (int i = 0; i < mTotalWidth; i++) {
mYPositions[i] = (float) (STRETCH_FACTOR_A * Math.sin(mCycleFactorW * i) + OFFSET_Y);
}
모든 y 값 에 따라 onDraw 에서 다음 코드 를 통 해 두 개의 정적 파문 을 그 릴 수 있 습 니 다.
for (int i = 0; i < mTotalWidth; i++) {
// 400 y , , ,
//
canvas.drawLine(i, mTotalHeight - mResetOneYPositions[i] - 400, i,
mTotalHeight,
mWavePaint);
//
canvas.drawLine(i, mTotalHeight - mResetTwoYPositions[i] - 400, i,
mTotalHeight,
mWavePaint);
}
이런 방식 은 수학 안의 세분 법,하나의 파문 과 유사 하 다.만약 에 가로로 하나의 화소 점 단위 로 세분 하면 view 총 너비 의 직선 을 형성 하고 모든 직선의 출발점 과 종점 을 우 리 는 알 수 있다.이 를 바탕 으로 우 리 는 모든 세분 화 된 직선(직선 은 세로)을 순환 적 으로 그 려 야 정태 적 인 물결 무늬 를 형성 할 수 있다.그 다음 에 우 리 는 물결 무늬 를 움 직 이게 했다.그 전에 한 배열 로 모든 y 값 점 을 저장 했다.두 개의 물결 무늬 가 있 고 두 개의 똑 같은 크기 의 배열 을 이용 하여 두 개의 물결 무늬 의 y 값 데 이 터 를 저장 하고 이 두 배열 의 데 이 터 를 계속 바 꾸 었 다.
private void resetPositonY() {
// mXOneOffset
int yOneInterval = mYPositions.length - mXOneOffset;
// System.arraycopy
System.arraycopy(mYPositions, mXOneOffset, mResetOneYPositions, 0, yOneInterval);
System.arraycopy(mYPositions, 0, mResetOneYPositions, yOneInterval, mXOneOffset);
int yTwoInterval = mYPositions.length - mXTwoOffset;
System.arraycopy(mYPositions, mXTwoOffset, mResetTwoYPositions, 0,
yTwoInterval);
System.arraycopy(mYPositions, 0, mResetTwoYPositions, yTwoInterval, mXTwoOffset);
}
이렇게 되면 이 두 배열 의 데 이 터 를 계속 바 꾸 고 계속 갱신 하면 동적 물결 무늬 를 생 성 할 수 있다.새로 고침 은 invalidate()또는 post Invaidate()를 호출 할 수 있 습 니 다.후자 가 하위 스 레 드 에서 UI 를 업데이트 할 수 있 는 것 과 차이 가 있 습 니 다.
전체 코드 는 다음 과 같 습 니 다.
public class DynamicWave extends View {
//
private static final int WAVE_PAINT_COLOR = 0x880000aa;
// y = Asin(wx+b)+h
private static final float STRETCH_FACTOR_A = 20;
private static final int OFFSET_Y = 0;
//
private static final int TRANSLATE_X_SPEED_ONE = 7;
//
private static final int TRANSLATE_X_SPEED_TWO = 5;
private float mCycleFactorW;
private int mTotalWidth, mTotalHeight;
private float[] mYPositions;
private float[] mResetOneYPositions;
private float[] mResetTwoYPositions;
private int mXOffsetSpeedOne;
private int mXOffsetSpeedTwo;
private int mXOneOffset;
private int mXTwoOffset;
private Paint mWavePaint;
private DrawFilter mDrawFilter;
public DynamicWave(Context context, AttributeSet attrs) {
super(context, attrs);
// dp px,
mXOffsetSpeedOne = UIUtils.dipToPx(context, TRANSLATE_X_SPEED_ONE);
mXOffsetSpeedTwo = UIUtils.dipToPx(context, TRANSLATE_X_SPEED_TWO);
//
mWavePaint = new Paint();
//
mWavePaint.setAntiAlias(true);
//
mWavePaint.setStyle(Style.FILL);
//
mWavePaint.setColor(WAVE_PAINT_COLOR);
mDrawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// canvas
canvas.setDrawFilter(mDrawFilter);
resetPositonY();
for (int i = 0; i < mTotalWidth; i++) {
// 400 y , , ,
//
canvas.drawLine(i, mTotalHeight - mResetOneYPositions[i] - 400, i,
mTotalHeight,
mWavePaint);
//
canvas.drawLine(i, mTotalHeight - mResetTwoYPositions[i] - 400, i,
mTotalHeight,
mWavePaint);
}
//
mXOneOffset += mXOffsetSpeedOne;
mXTwoOffset += mXOffsetSpeedTwo;
// ,
if (mXOneOffset >= mTotalWidth) {
mXOneOffset = 0;
}
if (mXTwoOffset > mTotalWidth) {
mXTwoOffset = 0;
}
// view , 20-30ms ,
postInvalidate();
}
private void resetPositonY() {
// mXOneOffset
int yOneInterval = mYPositions.length - mXOneOffset;
// System.arraycopy
System.arraycopy(mYPositions, mXOneOffset, mResetOneYPositions, 0, yOneInterval);
System.arraycopy(mYPositions, 0, mResetOneYPositions, yOneInterval, mXOneOffset);
int yTwoInterval = mYPositions.length - mXTwoOffset;
System.arraycopy(mYPositions, mXTwoOffset, mResetTwoYPositions, 0,
yTwoInterval);
System.arraycopy(mYPositions, 0, mResetTwoYPositions, yTwoInterval, mXTwoOffset);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// view
mTotalWidth = w;
mTotalHeight = h;
// y
mYPositions = new float[mTotalWidth];
// y
mResetOneYPositions = new float[mTotalWidth];
// y
mResetTwoYPositions = new float[mTotalWidth];
// view
mCycleFactorW = (float) (2 * Math.PI / mTotalWidth);
// view y
for (int i = 0; i < mTotalWidth; i++) {
mYPositions[i] = (float) (STRETCH_FACTOR_A * Math.sin(mCycleFactorW * i) + OFFSET_Y);
}
}
2.비 표준 원형 액체 기둥 물결 무늬앞의 파형 은 함수 시 뮬 레이 션 을 사용 합 니 다.이것 은 우리 가 다른 방식 으로 그림 으로 실현 하고 먼저 PS 로 파문 이 아 닌 파문 도 를 사용 합 니 다.
연결 이 긴밀 하기 위해 서 는 머리 와 꼬리 가 비교적 평평 하고 높이 가 일치 합 니 다.
생각:
1.원형 그림 을 마스크 로 파형 도 를 걸 러 내기;
2.물결 무늬 그림,즉 그 려 진 물결 무늬 그림 의 영역,즉 srcRect 를 계속 바 꾸 는 것 입 니 다.
3.주기 가 끝나 면 파문 도의 맨 앞에서 다시 계산한다.
우선 비트 맵 초기 화:
private void initBitmap() {
mSrcBitmap = ((BitmapDrawable) getResources().getDrawable(R.drawable.wave_2000))
.getBitmap();
mMaskBitmap = ((BitmapDrawable) getResources().getDrawable(
R.drawable.circle_500))
.getBitmap();
}
drawable 로 가 져 오 는 방식 을 사용 하면 전역 에 한 장 만 생 성 되 고 시스템 이 관리 되 며 BitmapFactory.decode()에서 나 오 는 것 은 decode 가 몇 번 에 몇 장 을 생 성 하 는 지 스스로 재 활용 해 야 합 니 다.그리고 파도 와 마스크 그림 을 그립 니 다.그 릴 때 해당 하 는 혼합 모드 를 설정 합 니 다.
/*
*
*/
int sc = canvas.saveLayer(0, 0, mTotalWidth, mTotalHeight, null, Canvas.ALL_SAVE_FLAG);
//
mSrcRect.set(mCurrentPosition, 0, mCurrentPosition + mCenterX, mTotalHeight);
//
canvas.drawBitmap(mSrcBitmap, mSrcRect, mDestRect, mBitmapPaint);
//
mBitmapPaint.setXfermode(mPorterDuffXfermode);
//
canvas.drawBitmap(mMaskBitmap, mMaskSrcRect, mMaskDestRect,
mBitmapPaint);
mBitmapPaint.setXfermode(null);
canvas.restoreToCount(sc);
동적 파도 효 과 를 형성 하기 위해 서 는 스 레 드 동적 으로 그 릴 파도 의 위 치 를 업데이트 합 니 다.
new Thread() {
public void run() {
while (true) {
//
mCurrentPosition += mSpeed;
if (mCurrentPosition >= mSrcBitmap.getWidth()) {
mCurrentPosition = 0;
}
try {
// , cpu ,
Thread.sleep(30);
} catch (InterruptedException e) {
}
postInvalidate();
}
};
}.start();
주요 과정 은 상기 와 같 습 니 다.모든 코드 는 다음 과 같 습 니 다.
public class PorterDuffXfermodeView extends View {
private static final int WAVE_TRANS_SPEED = 4;
private Paint mBitmapPaint, mPicPaint;
private int mTotalWidth, mTotalHeight;
private int mCenterX, mCenterY;
private int mSpeed;
private Bitmap mSrcBitmap;
private Rect mSrcRect, mDestRect;
private PorterDuffXfermode mPorterDuffXfermode;
private Bitmap mMaskBitmap;
private Rect mMaskSrcRect, mMaskDestRect;
private PaintFlagsDrawFilter mDrawFilter;
private int mCurrentPosition;
public PorterDuffXfermodeView(Context context, AttributeSet attrs) {
super(context, attrs);
initPaint();
initBitmap();
mPorterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
mSpeed = UIUtils.dipToPx(mContext, WAVE_TRANS_SPEED);
mDrawFilter = new PaintFlagsDrawFilter(Paint.ANTI_ALIAS_FLAG, Paint.DITHER_FLAG);
new Thread() {
public void run() {
while (true) {
//
mCurrentPosition += mSpeed;
if (mCurrentPosition >= mSrcBitmap.getWidth()) {
mCurrentPosition = 0;
}
try {
// , cpu ,
Thread.sleep(30);
} catch (InterruptedException e) {
}
postInvalidate();
}
};
}.start();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// canvas
canvas.setDrawFilter(mDrawFilter);
canvas.drawColor(Color.TRANSPARENT);
/*
*
*/
int sc = canvas.saveLayer(0, 0, mTotalWidth, mTotalHeight, null, Canvas.ALL_SAVE_FLAG);
//
mSrcRect.set(mCurrentPosition, 0, mCurrentPosition + mCenterX, mTotalHeight);
//
canvas.drawBitmap(mSrcBitmap, mSrcRect, mDestRect, mBitmapPaint);
//
mBitmapPaint.setXfermode(mPorterDuffXfermode);
//
canvas.drawBitmap(mMaskBitmap, mMaskSrcRect, mMaskDestRect,
mBitmapPaint);
mBitmapPaint.setXfermode(null);
canvas.restoreToCount(sc);
}
// bitmap
private void initBitmap() {
mSrcBitmap = ((BitmapDrawable) getResources().getDrawable(R.drawable.wave_2000))
.getBitmap();
mMaskBitmap = ((BitmapDrawable) getResources().getDrawable(
R.drawable.circle_500))
.getBitmap();
}
// paint
private void initPaint() {
mBitmapPaint = new Paint();
//
mBitmapPaint.setDither(true);
//
mBitmapPaint.setFilterBitmap(true);
mPicPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPicPaint.setDither(true);
mPicPaint.setColor(Color.RED);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mTotalWidth = w;
mTotalHeight = h;
mCenterX = mTotalWidth / 2;
mCenterY = mTotalHeight / 2;
mSrcRect = new Rect();
mDestRect = new Rect(0, 0, mTotalWidth, mTotalHeight);
int maskWidth = mMaskBitmap.getWidth();
int maskHeight = mMaskBitmap.getHeight();
mMaskSrcRect = new Rect(0, 0, maskWidth, maskHeight);
mMaskDestRect = new Rect(0, 0, mTotalWidth, mTotalHeight);
}
}
원본 다운로드 주소:http://xiazai.jb51.net/201701/yuanma/androidsbw(jb51.net)위 에서 말 한 것 은 소 편 이 소개 한 안 드 로 이 드 사용자 정의 view 가 물결 무늬 애니메이션 효 과 를 실현 하 는 것 입 니 다.여러분 에 게 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 면 메 시 지 를 남 겨 주세요.소 편 은 신속하게 답 해 드 리 겠 습 니 다.여기 서도 저희 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.