Android 에서 SurfaceView 와 일반 view 의 차이 및 사용

1 Surface View 소개
在这里插入图片描述
Surface View 의 첫 인상 은 view 입 니 다.View 를 계승 하기 때문에 두 개의 직접 하위 클래스 인 GLSurface View,VideoView 가 있 습 니 다.그러나 SDK 문서 인 Surface View 와 일반적인 view 에 따라 차이 가 크다.
가장 현저 한 차이 점 은 일반 view 와 그의 숙주 창 이 하나의 그림 표면(Surface)을 공유 하 는 것 이다.Surface View 도 View 의 트 리 구조 에 있 지만 자신 만 의 그림 표면 이 있 고 Surface 내부 에 Canvas 가 있어 이 Canvas 를 이용 하여 그 릴 수 있다.
Surface View 는 보기 구조 차원 에 직접 그림 표면(Surface)을 삽입 합 니 다.이 Surface 의 형식,크기 를 제어 할 수 있 습 니 다.Surface View 는 화면 에 Surface 를 올 바 르 게 배치 하 는 것 을 책임 집 니 다.쉽게 말 하면 Surface View 는 자신의 Surface 를 가지 고 숙주 창 과 분리 된다.
창 에 있 는 view 가 하나의 window 를 공유 하고 window 는 하나의 Surface 에 대응 하 는 것 을 알 기 때문에 창의 view 는 하나의 Surface 를 공유 하고 Surface View 는 자신의 Surface 를 가지 고 있 습 니 다.Surface View 는 응용 창 뒤에 있 는 새 창 을 만 듭 니 다.Surface View 는 Window 에 구멍 을 파 는 것 과 같 습 니 다.바로 이 구멍 에 표 시 됩 니 다.다른 View 는 Window 에 표시 되 기 때문에 View 는 Surface View 에 표시 할 수도 있 고 일부 층 을 Surface View 에 추가 할 수도 있 습 니 다.
Surface View 의 창 을 새로 고 칠 때 프로그램의 창 을 다시 그 릴 필요 가 없습니다.안 드 로 이 드 일반 창의 보기 그리 기 체 제 는 한 층 한 층 입 니 다.모든 하위 요소 나 부분 적 인 새로 고침 은 전체 보기 구 조 를 다시 그 릴 수 있 습 니 다.
일반적인 view 에 대해 안 드 로 이 드 의 창 인 터 페 이 스 는 여러 View 로 구 성 된 View Hierachy 의 트 리 구 조 를 포함 하고 있 으 며,맨 윗 층 의 DecorView 만 WMS 에 보 입 니 다.이 DecorView 는 WMS 에 해당 하 는 WindowState 가 있 습 니 다.이때 앱 이 Surface 생 성 을 요청 할 때 Surface Flinger 내부 에 해당 하 는 Layer 를 만 듭 니 다.Surface View 에 대해 서 는 Surface 를 가지 고 있 습 니 다.이 Surface 는 WMS 에 해당 하 는 Window State 가 있 고 Surface Flinger 에 해당 하 는 layer 가 있 습 니 다.Surface View 는 앱 에서 볼 때 View hierachy 구조 에 있 지만 WMS 와 Surface Flinger 에 서 는 숙주 창 과 분 리 됩 니 다.따라서 Surface View 의 Surface 렌 더 링 은 단독 스 레 드 에 넣 을 수 있 고 메 인 스 레 드 가 이벤트 에 대한 응답 에 영향 을 주지 않 습 니 다.그러나 이 서 피 스 는 View hierachy 에 없 기 때문에 디 스 플레이 도 View 의 속성 에 의 해 제어 되 지 않 기 때문에 이동,크기 조정 등 변환 을 할 수 없습니다(Surface View 에 ScrollBy,ScrollTo 작업 은 효과 가 없습니다(투명도,회전 도 있 습 니 다).일반 View 는 이동 을 하고 내부 내용 은 이동 하 며 Surface View 는 이러한 작업 을 하면 내부 가 이동 하지 않 습 니 다.이 를 감 싼 View Group 을 이동 회전 시 키 는 등 작업 을 하면 우리 가 원 하 는 효 과 를 얻 을 수 없습니다.또한 SurfaceView 는 RecyclerView 나 ScrollView 와 같은 기능 에 넣 을 수 없고 일부 View 의 특성 도 사용 할 수 없습니다.
Surface View 는 이동,크기 조정,회전 등 애니메이션 을 지원 하지 않 지만 Surface View 를 이용 하여 지원 되 지 않 는 애니메이션 을 테스트 할 때 7.0,심지어 더 높 은 버 전의 Android 시스템 을 사용 하면 Surface View 도 이동,크기 조정 애니메이션 작업 을 지원 하 는 것 을 발견 할 수 있 습 니 다.
View 와 Surface View 의 차이 점:
View 는 주동 적 인 업 데 이 트 를 적용 하고 SurfaceView 는 잦 은 리 셋 과 같은 수 동적 인 업 데 이 트 를 적용 합 니 다.
View 는 UI 스 레 드 에서 업 데 이 트 됩 니 다.비 UI 스 레 드 에서 업 데 이 트 를 하면 오류 가 발생 할 수 있 습 니 다.주 스 레 드 에서 view 를 업데이트 할 때 시간 이 너무 오래 걸 리 면 오류 가 발생 할 수 있 습 니 다.Surface View 는 하위 스 레 드 에서 리 셋 하면 주 스 레 드 를 막 지 않 고 인터페이스 가 자주 업데이트 되 고 프레임 율 에 대한 요구 가 높 은 경우 에 적 용 됩 니 다.
Surface View 는 리 셋 주파 수 를 제어 할 수 있다.
Surface View 바 텀 은 더 블 캐 시 체 제 를 이용 하여 그림 을 그 릴 때 반 짝 임 문제 가 발생 하지 않 습 니 다.
더 블 버퍼 기술 은 게임 개발 에서 중요 한 기술 로 주로 부분 적 인 스크린 이 반복 되 는 반 짝 임 을 해결 하기 위해 서 이다.게임,동 영상 등 화면 변화 가 빈번 하고 앞 에 다 표시 되 지 않 았 으 며 프로그램 이 다시 그 려 달라 고 요청 하면 화면 이 계속 반 짝 거 린 다.더 블 버퍼 기술 은 처리 할 그림 을 메모리 에서 처리 한 후,그 릴 것 을 메모리 영역 에 먼저 그린 다음,전체적으로 한꺼번에 그 려 서 화면 에 표시 합 니 다.
2 SurfaceView 사용 절차
Surface View 를 사용 하 는 단계:
먼저 Surface View 를 계승 하여 Surface Holder.Callback 인 터 페 이 스 를 실현 해 야 한다.
다시 쓰 는 방법:
  • surfaceChanged:surface 크기 나 형식 이 변 했 을 때 촉발 되 며,surfaceCreated 호출 후 이 함 수 는 적어도 한 번 호출 됩 니 다
  • surfaceCreated:Surface 를 만 들 때 터치 합 니 다.보통 이 함수 에서 그림 스 레 드 를 엽 니 다(새로운 스 레 드,이 스 레 드 에서 Surface 를 그리 지 마 십시오)
  • surfaceDestroyed:소각 시 촉발 되 며,일반적으로 보이 지 않 을 때 소각 합 니 다.
  • getHolder()를 이용 하여 Surface Holder 대상 을 가 져 오고 Surface Holder.addCallback 을 호출 하여 리 셋 을 추가 합 니 다.
    Surface Holder.lockCanvas 는 Canvas 대상 을 가 져 오고 캔버스 를 잠 그 며 Canvas 그림 을 호출 합 니 다.Surface Holder.unlockCanvasAndPost 는 캔버스 잠 금 을 끝내 고 변경 사항 을 제출 합 니 다.
    3 SurfaceHolder
    Surface View 의 더 블 버퍼 메커니즘 은 시스템 메모 리 를 매우 소모 하 는데,안 드 로 이 드 는 Surface View 가 보이 지 않 을 때 Surface View 의 Surface Holder 를 즉시 폐기 해 시스템 자원 을 절약 하 는 목적 을 달성 하기 때문에 Surface Holder 의 리 셋 함 수 를 이용 해 Surface Holder 를 유지 해 야 한다 고 규정 하고 있다.
    Surface Holder 의 생 성,소각 또는 변 화 를 알 수 있 도록 세 개의 반전 함 수 를 제공 합 니 다.
    void surfaceDestroyed(SurfaceHolder holder):SurfaceHolder 가 소각 되 었 을 때 리 셋 합 니 다.
    void surfaceCreated(SurfaceHolder holder):SurfaceHolder 가 생 성 되 었 을 때 리 셋 합 니 다.
    void surfaceChange(SurfaceHolder holder):SurfaceHolder 의 크기 나 형식 이 바 뀌 었 을 때 리 셋 됩 니 다.
    abstract Canvas lockCanvas():
    Canvas 대상 을 가 져 오고 잠 그 고 얻 은 Canvas 대상 은 Surface 의 한 구성원 입 니 다.
    ** abstract Canvas lockCanvas(Rectdirty):**
    dirty 가 지정 한 사각형 영역 만 잠 금 합 니 다.
    abstract void unlockCanvasAndPost(Canvascanvas)
    서 피 스 의 데 이 터 를 변경 한 후 동기 화 잠 금 을 풀 고 변경 사항 을 제출 한 후 새로운 데 이 터 를 보 여 주 며 같은 때 서 피 스 의 관련 데 이 터 를 잃 어 버 립 니 다.
    public abstract void setType (int type):
    Surface 의 종 류 를 설정 합 니 다.높 은 버 전에 서 set Type 이라는 방법 은 depreciated 에 의 해 설정 되 었 고 시스템 은 자동 으로 설 정 됩 니 다.
  • SURFACE_TYPE_NORMAL:네 이 티 브 데 이 터 를 RAM 으로 캐 시 하 는 일반 Surface
  • SURFACE_TYPE_HARDWARE:DMA(Direct memory access)엔진 과 하드웨어 가속 에 적용 되 는
  • SurfaceSURFACE_TYPE_GPU:GPU 가속 에 적용 되 는 Surface
  • SURFACE_TYPE_PUSH_BUFFERS:이 Surface 는 네 이 티 브 데 이 터 를 포함 하지 않 음 을 나타 내 며 Surface 에 사용 되 는 데 이 터 는 다른 대상 이 제공 합 니 다.Camera 이미지 미리 보기 에 서 는 이 유형의 Surface 를 사용 합 니 다.Camera 는 Surface 데 이 터 를 미리 보기 위해 제공 하고 이미지 생 성 이 원활 합 니 다
  • 호환성:
    Surface View 의 호환성
    Android 4.0 이하 Surface View 는 버퍼 를 자동 으로 유지 하지 않 습 니 다.동 영상 을 재생 할 때 Surface View 를 사용 하여 게임 애플 리 케 이 션 을 개발 하려 면 우리 스스로 이 버퍼 를 유지 해 야 합 니 다.
    
    // 4.0           
    getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    
    
    4 Surface View 의 간단 한 사용
    원형 그리 기:
    
    public class SurfaceViewDemo extends SurfaceView implements SurfaceHolder.Callback{
        private SurfaceHolder mSurfaceHolder;
        private Canvas mCanvas;
        private Paint paint;
    
        public SurfaceViewDemo(Context context) {
            this(context,null,0);
        }
    
        public SurfaceViewDemo(Context context, AttributeSet attrs) {
            this(context, attrs,0);
        }
    
        public SurfaceViewDemo(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        private void init() {
            mSurfaceHolder = getHolder();
            mSurfaceHolder.addCallback(this);
            setFocusable(true);
            setFocusableInTouchMode(true);
            this.setKeepScreenOn(true);
            paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setColor(Color.RED);
            paint.setStrokeWidth(5);
            paint.setStyle(Paint.Style.STROKE);
        }
    
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            System.out.println("=========surfaceCreated========");
            new Thread(new Runnable() {
                @Override
                public void run() {
                    draw();
                }
            }).start();
        }
    
        private void draw() {
            try {
                System.out.println("============draw========");
                mCanvas = mSurfaceHolder.lockCanvas();
                mCanvas.drawCircle(500,500,300,paint);
                mCanvas.drawCircle(100,100,20,paint);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (mCanvas != null)
                    mSurfaceHolder.unlockCanvasAndPost(mCanvas);
            }
        }
    
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            System.out.println("=========surfaceChanged========");
        }
    
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            System.out.println("=========surfaceDestroyed========");
        }
    }
    
    在这里插入图片描述
    리 셋 함수 호출:
    첫 입장:
    =surfaceCreated
    =surfaceChanged
    ====draw
    홈 키 클릭:
    =surfaceDestroyed
    다시 원래 페이지 로 돌아 가기:
    =surfaceCreated
    =surfaceChanged
    ====draw
    그래서 Surface View 가 보이 지 않 을 때 Surface Holder 를 없 애고 다시 들 어가 면 surfaceCreated 를 다시 호출 하여 새로운 Surface Holder 를 생 성 합 니 다.surfaceChanged 함 수 는 surfaceCreated 호출 후 이 함 수 는 적어도 한 번 호출 됩 니 다.
    Surface View 에서 동 영상 재생,저장 권한 잊 지 마 세 요.
    mediaPlayer.setDisplay(getHolder());
    비디오 자원 은 시 뮬 레이 터 를 이용 하여 녹화 한 mp4 영상 이다.
    
    public class SurfaceViewDemo2 extends SurfaceView implements SurfaceHolder.Callback{
        private SurfaceHolder mSurfaceHolder;
        private Canvas mCanvas;
        private Paint paint;
        private MediaPlayer mediaPlayer;
    
        public SurfaceViewDemo2(Context context) {
            this(context,null,0);
        }
    
        public SurfaceViewDemo2(Context context, AttributeSet attrs) {
            this(context, attrs,0);
        }
    
        public SurfaceViewDemo2(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        private void init() {
            mSurfaceHolder = getHolder();
            mSurfaceHolder.addCallback(this);
            setFocusable(true);
            setFocusableInTouchMode(true);
            this.setKeepScreenOn(true);
            setZOrderOnTop(true);
            paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setColor(Color.RED);
            paint.setStrokeWidth(5);
            paint.setStyle(Paint.Style.STROKE);
        }
    
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            System.out.println("=========surfaceCreated========");
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //draw();
                  play();
                }
            }).start();
        }
    
        private void draw() {
    
            try {
                System.out.println("============draw========");
                mCanvas = mSurfaceHolder.lockCanvas();
                mCanvas.drawCircle(500,500,300,paint);
                mCanvas.drawCircle(100,100,20,paint);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (mCanvas != null)
                    mSurfaceHolder.unlockCanvasAndPost(mCanvas);
            }
        }
    
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            System.out.println("=========surfaceChanged========");
        }
    
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            System.out.println("=========surfaceDestroyed========");
            if (mediaPlayer != null ){
                stop();
            }
        }
    
    
        protected void stop() {
            if (mediaPlayer != null && mediaPlayer.isPlaying()) {
                mediaPlayer.stop();
                mediaPlayer.release();
                mediaPlayer = null;
            }
        }
    
        protected void play() {
            String path = "/sdcard/DCIM/Camera/VID_20190110_102218.mp4";
            File file = new File(path);
            if (!file.exists()) {
                return;
            }
                try {
                    mediaPlayer = new MediaPlayer();
                    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                    //         
                    mediaPlayer.setDataSource(file.getAbsolutePath());
                    //        SurfaceHolder
                    mediaPlayer.setDisplay(getHolder());
    
                    mediaPlayer.prepareAsync();
                    mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
    
                        @Override
                        public void onPrepared(MediaPlayer mp) {
                            mediaPlayer.start();
                        }
                    });
                    mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
    
                        @Override
                        public void onCompletion(MediaPlayer mp) {
                            replay();
                        }
                    });
    
                    mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
    
                        @Override
                        public boolean onError(MediaPlayer mp, int what, int extra) {
                            play();
                            return false;
                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                }
        }
    
        protected void replay() {
            if (mediaPlayer!=null){
             mediaPlayer.start();
            }else{
                play();
            }
        }
    
        protected void pause() {
            if (mediaPlayer != null && mediaPlayer.isPlaying()) {
                mediaPlayer.pause();
            }else{
                mediaPlayer.start();
            }
        }
    }
    
    图片7
    Surface View 를 평행 이동,회전 등 동작 을 추가 합 니 다.
    mSurfaceView 를 추가 합 니 다.scrollBy(10,10);
    효 과 는 다음 과 같다:전혀 효과 가 없다.
    在这里插入图片描述
    패키지 의 viewgroup 에 크기 조정 애니메이션 을 추가 합 니 다.
    
    mContainer.animate().scaleX(0.4f).scaleY(0.7f);
    
    
    在这里插入图片描述
    이때 찍 은 사진 은:
    在这里插入图片描述
    찍 은 사진 은 크기 조정 에 전혀 영향 을 받 지 않 았 다.
    안 드 로 이 드 에서 Surface View 와 일반 view 의 차이 점 및 사용 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 안 드 로 이 드 에서 Surface View 와 일반 view 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 도 많은 응원 부 탁 드 리 겠 습 니 다!

    좋은 웹페이지 즐겨찾기