Android 는 Surface View 를 이용 하여 비 오 는 날씨 애니메이션 효 과 를 실현 합 니 다.
9083 단어 androidsurfaceview비가 오다
먼저 빗방울 의 실현 을 분석 해 보 자.
canvas.drawLine()
을 통 해 그립 니 다onDraw()
한 번 에 다시 그 려 야 한 다 는 것 을 의미 합 니 다.만약 당신 의 onDraw()방법 에 있 는 렌 더 링 코드 가 조금 걸 리 면 ViewonDraw()
방법 이 UI 스 레 드 에 호출 된다 면 그리 기 효과 가 원활 하지 않 고 UI 스 레 드 를 막 을 수도 있 습 니 다.그래서 더욱 원활 한 효 과 를 내 고 UI 스 레 드 를 막 지 않 기 위해 서 는 Surface View 를 사용 합 니 다.초 면 Surface View
SurfaceView 는 View 에서 직접 계승 합 니 다.View 는 UI 스 레 드 에서 그 려 야 합 니 다.SurfaceView 는 View 와 다 릅 니 다.비 UI 스 레 드 에서 그 려 서 인터페이스 에 표시 할 수 있 습 니 다.이것 은 새로 스 레 드 를 열 고 렌 더 링 코드 를 이 스 레 드 에 놓 을 수 있다 는 것 을 의미 합 니 다.
Surface 는 Z 축 으로 정렬 되 어 있 습 니 다.Surface View 의 Z 축 위 치 는 숙주 Window 보다 작 습 니 다.이것 은 항상 자신 이 있 는 Window 뒤에 있다 는 것 을 의미 합 니 다.뒤에 있 는 이상 어떻게 표시 합 니까?Surface View 는 Window 에'구멍'을 쳤 습 니 다.(사실은 숙주 Window 에 투명 한 영역 을 설정 하여 표시 할 수 있 도록 하 는 것 입 니 다)그의 형제 노드 의 View 가 그것 을 덮어 쓰 는 것 을 의미 합 니 다.예 를 들 어 Surface View 위 에 단추,텍스트 등 컨트롤 을 설치 할 수 있 습 니 다.
아래 Surface 에 접근 하려 면 Android 를 통 해 Surface Holder 인 터 페 이 스 를 제공 할 수 있 습 니 다.Surface View
onDraw()
를 호출 하여 얻 을 수 있 습 니 다.Surface View 는 라 이 프 사이클 이 있 습 니 다.라 이 프 사이클 동안 그리 기 코드 를 실행 해 야 하기 때문에 Surface View 의 상태(예 를 들 어 생 성 및 소각)를 감청 해 야 합 니 다.여기 Android 는 우리 에 게
getHolder()
이 인 터 페 이 스 를 제공 하여 Surface View 의 상 태 를 편리 하 게 감청 할 수 있 습 니 다.그럼 아래
SurfaceHolder.Callback
인 터 페 이 스 를 보 겠 습 니 다.
public interface Callback {
// SurfaceView (SurfaceView )
public void surfaceCreated(SurfaceHolder holder);
// SurfaceView
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height);
// SurfaceView (SurfaceView )
public void surfaceDestroyed(SurfaceHolder holder);
}
우리 의 그리 기 코드 는 surfaceCreated 와 surfaceDestroyed 사이 에서 실행 되 어야 합 니 다.그렇지 않 으 면 잘못 되 었 습 니 다.SurfaceHolder.Callback
의 리 셋 방법 은 UI 스 레 드 에서 실 행 됩 니 다.스 레 드 를 그 리 려 면 우리 가 수 동 으로 만들어 야 합 니 다.구체 적 으로 는 공식 문 서 를 볼 수 있다.https://developer.android.google.cn/reference/android/view/SurfaceView.html
View 와 Surface View 의 사용 장면
여기 서 저 희 는 사용자 정의 View 와 유사 합 니 다.Dynamic WeatherView 를 써 서 Surface View 의 상 태 를 계승 한 다음 에 Surface View 의 상 태 를 감청 하기 위해 서
SurfaceHolder.Callback
인 터 페 이 스 를 실현 하여 Surface View 의 상 태 를 감청 해 야 합 니 다.인터페이스의 리 셋 구체 적 인 시기 에 도 소개 되 었 습 니 다.
public class DynamicWeatherView extends SurfaceView implements SurfaceHolder.Callback{
public DynamicWeatherView(Context context) {
this(context, null);
}
public DynamicWeatherView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DynamicWeatherView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
// SurfaceView ( )
@Override
public void surfaceCreated(SurfaceHolder holder) {
}
// SurfaceView ( )
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
}
위 에서 언급 한 바 와 같이 Surface 를 제어 하려 면 Surface Holder 대상 이 필요 합 니 다.Surface ViewSurfaceHolder.Callback
를 호출 하면 얻 을 수 있 습 니 다.그리고 이 Surface Holder 에 getHolder()
리 셋 을 추가 합 니 다.여기 가 바로 Dynamic WeatherView 현재 대상 입 니 다.
private SurfaceHolder mHolder;
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setFormat(PixelFormat.TRANSPARENT);
그리고 우리 의 그리 기 라인 을 실현 합 니 다.
private class DrawThread extends Thread {
//
private boolean isRunning = false;
public void setRunning(boolean running) {
isRunning = running;
}
@Override
public void run() {
Canvas canvas;
//
while (isRunning) {
if (mType != null && mViewWidth != 0 && mViewHeight != 0) {
canvas = mHolder.lockCanvas();
if (canvas != null) {
mType.onDraw(canvas);
if (isRunning) {
mHolder.unlockCanvasAndPost(canvas);
} else {
//
break;
}
SystemClock.sleep(1);
}
}
}
}
}
위의 코드 를 통 해 알 수 있 듯 이 Surface View 의 업데이트 절 차 는 구체 적 으로 다음 과 같다.
// canvas
canvas = mHolder.lockCanvas();
// canvas
mType.onDraw(canvas);
//
mHolder.unlockCanvasAndPost(canvas);
스 레 드 코드 를 그 리 는 양 이 많 지 않 습 니 다.구체 적 인 그리 기 코드 는SurfaceHolder.Callback
에서 mType 은 우리 가 정의 하 는 인터페이스 로 날씨 유형 을 대표 합 니 다.
public interface WeatherType {
void onDraw(Canvas canvas);
void onSizeChanged(Context context, int w, int h);
}
이렇게 서로 다른 날씨 유형 을 실현 하려 면 이 인터페이스 에서 onDraw 와 onSize Changed 방법 을 다시 쓰 면 됩 니 다.여기 서 우 리 는 비가 오 는 효 과 를 실현 하기 때문에 RainTypeImpl 류 를 실현 합 니 다.
public class RainTypeImpl extends BaseType {
//
private Drawable mBackground;
//
private ArrayList<RainHolder> mRains;
//
private Paint mPaint;
public RainTypeImpl(Context context, DynamicWeatherView dynamicWeatherView) {
super(context, dynamicWeatherView);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.WHITE);
// 3
mPaint.setStrokeWidth(3);
mRains = new ArrayList<>();
}
@Override
public void generate() {
mBackground = getContext().getResources().getDrawable(R.drawable.rain_sky_night);
mBackground.setBounds(0, 0, getWidth(), getHeight());
for (int i = 0; i < 60; i++) {
RainHolder rain = new RainHolder(
getRandom(1, getWidth()),
getRandom(1, getHeight()),
getRandom(dp2px(9), dp2px(15)),
getRandom(dp2px(5), dp2px(9)),
getRandom(20, 100)
);
mRains.add(rain);
}
}
private RainHolder r;
@Override
public void onDraw(Canvas canvas) {
clearCanvas(canvas);
//
mBackground.draw(canvas);
//
for (int i = 0; i < mRains.size(); i++) {
r = mRains.get(i);
mPaint.setAlpha(r.a);
canvas.drawLine(r.x, r.y, r.x, r.y + r.l, mPaint);
}
//
for (int i = 0; i < mRains.size(); i++) {
r = mRains.get(i);
r.y += r.s;
if (r.y > getHeight()) {
r.y = -r.l;
}
}
}
private class RainHolder {
/**
* x
*/
int x;
/**
* y
*/
int y;
/**
*
*/
int l;
/**
*
*/
int s;
/**
*
*/
int a;
public RainHolder(int x, int y, int l, int s, int a) {
this.x = x;
this.y = y;
this.l = l;
this.s = s;
this.a = a;
}
}
}
코드 는 어렵 지 않 습 니 다.기본적으로 주석 이 있 습 니 다.Rain Holder 대상 은 빗방울 을 대표 합 니 다.한 번 그 릴 때마다 빗방울 의 위 치 를 바 꾸 고 다음 에 그 릴 준 비 를 해서 빗방울 의 이동 을 실현 합 니 다.BaseType 류 는 우리 의 추상 적 인 기류 로
mType.onDraw(canvas)
인 터 페 이 스 를 실 현 했 고 내부 에 일부 공공 방법 이 있 으 며 구체 적 으로 Demo 의 코드 를 볼 수 있다.마지막 으로 우리 의 Activity 코드:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DynamicWeatherView mDynamicWeatherView = (DynamicWeatherView) findViewById(R.id.dynamic_weather_view);
mDynamicWeatherView.setType(new RainTypeImpl(this, mDynamicWeatherView));
}
}
앞으로 서로 다른 날씨 유형 을 구현 하려 면 베이스 타 입 클래스 를 계승 해 재 작성 하 는 방법 만 있 으 면 된다.원본 다운로드:여 기 를 클릭 하 세 요.
총결산
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 안 드 로 이 드 개발 자 들 에 게 어느 정도 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.