안 드 로 이 드 고급 이미지 스크롤 컨트롤 3D 버 전 이미지 재생 기 구현

안녕하세요,오 랜 만 입 니 다.요즘 일이 너무 바 빠 서 한 달 넘 게 블 로 그 를 쓰 지 못 해서 저도 부 끄 럽 습 니 다.그럼 오늘 의 이 글 은 한 달 여 만 에 이별 한 글 이 니 더 힘 이 되 는 내용 을 가 져 와 야 지.그럼 더 이상 말 하지 말고 어서 오늘 의 본론 으로 들 어가 자.
사진 윤방송 기 에 대해 말하자면 많은 안 드 로 이 드 응용 프로그램 에서 이 기능 을 가지 고 있다.예 를 들 어 왕 이 뉴스,타 오 바 오 등 이다.최근 에 우리 회사 의 응용 프로그램 도 이 기능 을 추 가 했 고 사진 윤 방 을 바탕 으로 3 차원 입체 효 과 를 추 가 했 지만 전체적인 효과 가 이상 적 이지 않 고 사용자 의 체험 성 이 비교적 나쁘다 는 것 이 유감스럽다.그래서 저 는 효과 가 더 좋 은 3D 사진 재생 기 를 만 드 는 데 시간 이 좀 걸 렸 습 니 다.저 는 만족 합 니 다.여기 서 과감하게 블 로 그 를 써 서 여러분 께 공유 하 겠 습 니 다.
먼저 실현 원 리 를 소개 합 니 다.전통 적 인 이미지 재생 기 는 한 화면 에 한 장의 그림 만 표시 되 고 손가락 으로 좌우 로 미 끄 러 져 야 다른 그림 을 볼 수 있 습 니 다.여기 서 우 리 는 사 고 를 발산 하여 한 화면 에 세 장의 그림 을 동시에 표시 한 다음 에 Camera 의 방식 으로 좌우 의 두 장의 그림 을 3D 로 회전 시 키 면 입체 적 인 그림 윤 방송 기 를 만 들 수 있다.원리 설명도 는 다음 과 같다.

사진 을 입체 적 으로 조작 하려 면 Camera 기술 을 사용 해 야 합 니 다.만약 에 이 기술 에 대해 잘 모 르 면 인터넷 에서 관련 자 료 를 검색 하거나 제 앞의 글 을 참고 하 십시오Android 중축 회전 효과 구현 Android 다른 이미지 브 라 우 저 만 들 기
그럼 지금부터 시작 합 시다.먼저 안 드 로 이 드 프로젝트 를 새로 만 들 고 이미지 스위치 뷰 테스트 라 고 이름 을 지 었 습 니 다.
그리고 Image3DView 를 새로 만 들 면 ImageView 의 모든 속성 을 계승 하고 3D 회전 기능 을 추가 합 니 다.코드 는 다음 과 같 습 니 다.

public class Image3DView extends ImageView { 
 /** 
 *          
 */ 
 private static final float BASE_DEGREE = 50f; 
 /** 
 *          
 */ 
 private static final float BASE_DEEP = 150f; 
 private Camera mCamera; 
 private Matrix mMaxtrix; 
 private Bitmap mBitmap; 
 /** 
 *           
 */ 
 private int mIndex; 
 /** 
 *      X         
 */ 
 private int mScrollX; 
 /** 
 * Image3DSwitchView      
 */ 
 private int mLayoutWidth; 
 /** 
 *         
 */ 
 private int mWidth; 
 /** 
 *         
 */ 
 private float mRotateDegree; 
 /** 
 *        
 */ 
 private float mDx; 
 /** 
 *       
 */ 
 private float mDeep; 
 
 public Image3DView(Context context, AttributeSet attrs) { 
 super(context, attrs); 
 mCamera = new Camera(); 
 mMaxtrix = new Matrix(); 
 } 
 /** 
 *    Image3DView      ,      ,      。 
 */ 
 public void initImageViewBitmap() { 
 if (mBitmap == null) { 
 setDrawingCacheEnabled(true); 
 buildDrawingCache(); 
 mBitmap = getDrawingCache(); 
 } 
 mLayoutWidth = Image3DSwitchView.mWidth; 
 mWidth = getWidth() + Image3DSwitchView.IMAGE_PADDING * 2; 
 } 
 /** 
 *       。 
 * 
 * @param index 
 *         
 * @param scrollX 
 *      X         
 */ 
 public void setRotateData(int index, int scrollX) { 
 mIndex = index; 
 mScrollX = scrollX; 
 } 
 /** 
 *      Bitmap  ,     。 
 */ 
 public void recycleBitmap() { 
 if (mBitmap != null && !mBitmap.isRecycled()) { 
 mBitmap.recycle(); 
 } 
 } 
 @Override 
 public void setImageResource(int resId) { 
 super.setImageResource(resId); 
 mBitmap = null; 
 initImageViewBitmap(); 
 } 
 @Override 
 public void setImageBitmap(Bitmap bm) { 
 super.setImageBitmap(bm); 
 mBitmap = null; 
 initImageViewBitmap(); 
 } 
 @Override 
 public void setImageDrawable(Drawable drawable) { 
 super.setImageDrawable(drawable); 
 mBitmap = null; 
 initImageViewBitmap(); 
 } 
 @Override 
 public void setImageURI(Uri uri) { 
 super.setImageURI(uri); 
 mBitmap = null; 
 initImageViewBitmap(); 
 } 
 @Override 
 protected void onDraw(Canvas canvas) { 
 if (mBitmap == null) { 
 //   Bitmap      ,      onDraw       
 super.onDraw(canvas); 
 } else { 
 if (isImageVisible()) { 
 //        ,               ,           
 computeRotateData(); 
 mCamera.save(); 
 mCamera.translate(0.0f, 0.0f, mDeep); 
 mCamera.rotateY(mRotateDegree); 
 mCamera.getMatrix(mMaxtrix); 
 mCamera.restore(); 
 mMaxtrix.preTranslate(-mDx, -getHeight() / 2); 
 mMaxtrix.postTranslate(mDx, getHeight() / 2); 
 canvas.drawBitmap(mBitmap, mMaxtrix, null); 
 } 
 } 
 } 
 /** 
 *                。 
 */ 
 private void computeRotateData() { 
 float degreePerPix = BASE_DEGREE / mWidth; 
 float deepPerPix = BASE_DEEP / ((mLayoutWidth - mWidth) / 2); 
 switch (mIndex) { 
 case 0: 
 mDx = mWidth; 
 mRotateDegree = 360f - (2 * mWidth + mScrollX) * degreePerPix; 
 if (mScrollX < -mWidth) { 
 mDeep = 0; 
 } else { 
 mDeep = (mWidth + mScrollX) * deepPerPix; 
 } 
 break; 
 case 1: 
 if (mScrollX > 0) { 
 mDx = mWidth; 
 mRotateDegree = (360f - BASE_DEGREE) - mScrollX * degreePerPix; 
 mDeep = mScrollX * deepPerPix; 
 } else { 
 if (mScrollX < -mWidth) { 
 mDx = -Image3DSwitchView.IMAGE_PADDING * 2; 
 mRotateDegree = (-mScrollX - mWidth) * degreePerPix; 
 } else { 
 mDx = mWidth; 
 mRotateDegree = 360f - (mWidth + mScrollX) * degreePerPix; 
 } 
 mDeep = 0; 
 } 
 break; 
 case 2: 
 if (mScrollX > 0) { 
 mDx = mWidth; 
 mRotateDegree = 360f - mScrollX * degreePerPix; 
 mDeep = 0; 
 if (mScrollX > mWidth) { 
 mDeep = (mScrollX - mWidth) * deepPerPix; 
 } 
 } else { 
 mDx = -Image3DSwitchView.IMAGE_PADDING * 2; 
 mRotateDegree = -mScrollX * degreePerPix; 
 mDeep = 0; 
 if (mScrollX < -mWidth) { 
 mDeep = -(mWidth + mScrollX) * deepPerPix; 
 } 
 } 
 break; 
 case 3: 
 if (mScrollX < 0) { 
 mDx = -Image3DSwitchView.IMAGE_PADDING * 2; 
 mRotateDegree = BASE_DEGREE - mScrollX * degreePerPix; 
 mDeep = -mScrollX * deepPerPix; 
 } else { 
 if (mScrollX > mWidth) { 
 mDx = mWidth; 
 mRotateDegree = 360f - (mScrollX - mWidth) * degreePerPix; 
 } else { 
 mDx = -Image3DSwitchView.IMAGE_PADDING * 2; 
 mRotateDegree = BASE_DEGREE - mScrollX * degreePerPix; 
 } 
 mDeep = 0; 
 } 
 break; 
 case 4: 
 mDx = -Image3DSwitchView.IMAGE_PADDING * 2; 
 mRotateDegree = (2 * mWidth - mScrollX) * degreePerPix; 
 if (mScrollX > mWidth) { 
 mDeep = 0; 
 } else { 
 mDeep = (mWidth - mScrollX) * deepPerPix; 
 } 
 break; 
 } 
 } 
 /** 
 *           。 
 * 
 * @return         true,     false。 
 */ 
 private boolean isImageVisible() { 
 boolean isVisible = false; 
 switch (mIndex) { 
 case 0: 
 if (mScrollX < (mLayoutWidth - mWidth) / 2 - mWidth) { 
 isVisible = true; 
 } else { 
 isVisible = false; 
 } 
 break; 
 case 1: 
 if (mScrollX > (mLayoutWidth - mWidth) / 2) { 
 isVisible = false; 
 } else { 
 isVisible = true; 
 } 
 break; 
 case 2: 
 if (mScrollX > mLayoutWidth / 2 + mWidth / 2 
 || mScrollX < -mLayoutWidth / 2 - mWidth / 2) { 
 isVisible = false; 
 } else { 
 isVisible = true; 
 } 
 break; 
 case 3: 
 if (mScrollX < -(mLayoutWidth - mWidth) / 2) { 
 isVisible = false; 
 } else { 
 isVisible = true; 
 } 
 break; 
 case 4: 
 if (mScrollX > mWidth - (mLayoutWidth - mWidth) / 2) { 
 isVisible = true; 
 } else { 
 isVisible = false; 
 } 
 break; 
 } 
 return isVisible; 
 } 
} 
이 코드 는 비교적 길 고 복잡 하 니 천천히 분석 합 시다.Image3DView 의 구조 함수 에서 Camera 와 Matrix 대상 을 초기 화하 여 뒤에서 그림 을 3D 로 조작 합 니 다.그리고 initImageViewBitmap()방법 에서 필요 한 정 보 를 초기 화 했 습 니 다.예 를 들 어 현재 그림 을 캡 처 하여 후속 적 인 입체 작업 에 사용 하고 현재 그림 의 폭 을 얻 는 등 입 니 다.
그 다음 에 setRotateData()방법 도 제공 했다.현재 그림 의 아래 표 와 스크롤 거 리 를 설정 하 는 데 사용 된다.이 두 가지 데이터 가 있 으 면 coptute RotateData()방법 으로 회전 각도 의 일부 데 이 터 를 계산 하고 isImageVisible()방법 으로 현재 그림 이 보 이 는 지 여 부 를 판단 할 수 있다.구체 적 이 고 상세 한 알고리즘 논 리 는 코드 를 읽 고 천천히 분석 할 수 있다.
다음 에 그림 을 화면 에 그 려 야 할 때 onDraw()방법 을 사용 하고 onDraw()방법 에서 판단 합 니 다.현재 그림 을 볼 수 있 으 면 coptute RotateData()방법 으로 회전 할 때 필요 한 각종 데 이 터 를 계산 한 다음 에 Camera 와 Matrix 를 통 해 회전 작업 을 수행 하면 됩 니 다.
이 어 ViewGroup 에서 Image3D SwitchView 를 새로 만 들 었 습 니 다.코드 는 다음 과 같 습 니 다.

public class Image3DSwitchView extends ViewGroup { 
 /** 
 *             
 */ 
 public static final int IMAGE_PADDING = 10; 
 private static final int TOUCH_STATE_REST = 0; 
 private static final int TOUCH_STATE_SCROLLING = 1; 
 /** 
 *             
 */ 
 private static final int SNAP_VELOCITY = 600; 
 /** 
 *                
 */ 
 private static final int SCROLL_NEXT = 0; 
 /** 
 *                
 */ 
 private static final int SCROLL_PREVIOUS = 1; 
 /** 
 *              
 */ 
 private static final int SCROLL_BACK = 2; 
 private static Handler handler = new Handler(); 
 /** 
 *      
 */ 
 public static int mWidth; 
 private VelocityTracker mVelocityTracker; 
 private Scroller mScroller; 
 /** 
 *        ,               
 */ 
 private OnImageSwitchListener mListener; 
 /** 
 *           
 */ 
 private int mTouchState = TOUCH_STATE_REST; 
 /** 
 *                  
 */ 
 private int mTouchSlop; 
 /** 
 *        
 */ 
 private int mHeight; 
 /** 
 *           
 */ 
 private int mImageWidth; 
 /** 
 *          
 */ 
 private int mCount; 
 /** 
 *             
 */ 
 private int mCurrentImage; 
 /** 
 *             
 */ 
 private float mLastMotionX; 
 /** 
 *          
 */ 
 private boolean forceToRelayout; 
 private int[] mItems; 
 public Image3DSwitchView(Context context, AttributeSet attrs) { 
 super(context, attrs); 
 mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); 
 mScroller = new Scroller(context); 
 } 
 @Override 
 protected void onLayout(boolean changed, int l, int t, int r, int b) { 
 if (changed || forceToRelayout) { 
 mCount = getChildCount(); 
 //         5,         
 if (mCount < 5) { 
 return; 
 } 
 mWidth = getMeasuredWidth(); 
 mHeight = getMeasuredHeight(); 
 //                      
 mImageWidth = (int) (mWidth * 0.6); 
 if (mCurrentImage >= 0 && mCurrentImage < mCount) { 
 mScroller.abortAnimation(); 
 setScrollX(0); 
 int left = -mImageWidth * 2 + (mWidth - mImageWidth) / 2; 
 //                    
 int[] items = { getIndexForItem(1), getIndexForItem(2), 
 getIndexForItem(3), getIndexForItem(4), 
 getIndexForItem(5) }; 
 mItems = items; 
 //               
 for (int i = 0; i < items.length; i++) { 
 Image3DView childView = (Image3DView) getChildAt(items[i]); 
 childView.layout(left + IMAGE_PADDING, 0, left 
 + mImageWidth - IMAGE_PADDING, mHeight); 
 childView.initImageViewBitmap(); 
 left = left + mImageWidth; 
 } 
 refreshImageShowing(); 
 } 
 forceToRelayout = false; 
 } 
 } 
 @Override 
 public boolean onTouchEvent(MotionEvent event) { 
 if (mScroller.isFinished()) { 
 if (mVelocityTracker == null) { 
 mVelocityTracker = VelocityTracker.obtain(); 
 } 
 mVelocityTracker.addMovement(event); 
 int action = event.getAction(); 
 float x = event.getX(); 
 switch (action) { 
 case MotionEvent.ACTION_DOWN: 
 //           
 mLastMotionX = x; 
 break; 
 case MotionEvent.ACTION_MOVE: 
 int disX = (int) (mLastMotionX - x); 
 mLastMotionX = x; 
 scrollBy(disX, 0); 
 //                 
 refreshImageShowing(); 
 break; 
 case MotionEvent.ACTION_UP: 
 mVelocityTracker.computeCurrentVelocity(1000); 
 int velocityX = (int) mVelocityTracker.getXVelocity(); 
 if (shouldScrollToNext(velocityX)) { 
 //         
 scrollToNext(); 
 } else if (shouldScrollToPrevious(velocityX)) { 
 //         
 scrollToPrevious(); 
 } else { 
 //         
 scrollBack(); 
 } 
 if (mVelocityTracker != null) { 
 mVelocityTracker.recycle(); 
 mVelocityTracker = null; 
 } 
 break; 
 } 
 } 
 return true; 
 } 
 /** 
 *                         。 
 */ 
 @Override 
 public boolean onInterceptTouchEvent(MotionEvent ev) { 
 int action = ev.getAction(); 
 if ((action == MotionEvent.ACTION_MOVE) 
 && (mTouchState != TOUCH_STATE_REST)) { 
 return true; 
 } 
 float x = ev.getX(); 
 switch (action) { 
 case MotionEvent.ACTION_DOWN: 
 mLastMotionX = x; 
 mTouchState = TOUCH_STATE_REST; 
 break; 
 case MotionEvent.ACTION_MOVE: 
 int xDiff = (int) Math.abs(mLastMotionX - x); 
 if (xDiff > mTouchSlop) { 
 mTouchState = TOUCH_STATE_SCROLLING; 
 } 
 break; 
 case MotionEvent.ACTION_UP: 
 default: 
 mTouchState = TOUCH_STATE_REST; 
 break; 
 } 
 return mTouchState != TOUCH_STATE_REST; 
 } 
 @Override 
 public void computeScroll() { 
 if (mScroller.computeScrollOffset()) { 
 scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); 
 refreshImageShowing(); 
 postInvalidate(); 
 } 
 } 
 /** 
 *           ,              。 
 * 
 * @param listener 
 *         
 */ 
 public void setOnImageSwitchListener(OnImageSwitchListener listener) { 
 mListener = listener; 
 } 
 /** 
 *            ,                    ,         。 
 * 
 * @param currentImage 
 *       
 */ 
 public void setCurrentImage(int currentImage) { 
 mCurrentImage = currentImage; 
 requestLayout(); 
 } 
 /** 
 *         。 
 */ 
 public void scrollToNext() { 
 if (mScroller.isFinished()) { 
 int disX = mImageWidth - getScrollX(); 
 checkImageSwitchBorder(SCROLL_NEXT); 
 if (mListener != null) { 
 mListener.onImageSwitch(mCurrentImage); 
 } 
 beginScroll(getScrollX(), 0, disX, 0, SCROLL_NEXT); 
 } 
 } 
 /** 
 *         。 
 */ 
 public void scrollToPrevious() { 
 if (mScroller.isFinished()) { 
 int disX = -mImageWidth - getScrollX(); 
 checkImageSwitchBorder(SCROLL_PREVIOUS); 
 if (mListener != null) { 
 mListener.onImageSwitch(mCurrentImage); 
 } 
 beginScroll(getScrollX(), 0, disX, 0, SCROLL_PREVIOUS); 
 } 
 } 
 /** 
 *       。 
 */ 
 public void scrollBack() { 
 if (mScroller.isFinished()) { 
 beginScroll(getScrollX(), 0, -getScrollX(), 0, SCROLL_BACK); 
 } 
 } 
 /** 
 *         ,    。 
 */ 
 public void clear() { 
 for (int i = 0; i < mCount; i++) { 
 Image3DView childView = (Image3DView) getChildAt(i); 
 childView.recycleBitmap(); 
 } 
 } 
 /** 
 *              。 
 */ 
 private void beginScroll(int startX, int startY, int dx, int dy, 
 final int action) { 
 int duration = (int) (700f / mImageWidth * Math.abs(dx)); 
 mScroller.startScroll(startX, startY, dx, dy, duration); 
 invalidate(); 
 handler.postDelayed(new Runnable() { 
 @Override 
 public void run() { 
 if (action == SCROLL_NEXT || action == SCROLL_PREVIOUS) { 
 forceToRelayout = true; 
 requestLayout(); 
 } 
 } 
 }, duration); 
 } 
 /** 
 *              item  ,   item           。 
 * 
 * @param item 
 *      1-5 
 * @return   item           。 
 */ 
 private int getIndexForItem(int item) { 
 int index = -1; 
 index = mCurrentImage + item - 3; 
 while (index < 0) { 
 index = index + mCount; 
 } 
 while (index > mCount - 1) { 
 index = index - mCount; 
 } 
 return index; 
 } 
 /** 
 *            ,         。 
 */ 
 private void refreshImageShowing() { 
 for (int i = 0; i < mItems.length; i++) { 
 Image3DView childView = (Image3DView) getChildAt(mItems[i]); 
 childView.setRotateData(i, getScrollX()); 
 childView.invalidate(); 
 } 
 } 
 /** 
 *        ,             。 
 */ 
 private void checkImageSwitchBorder(int action) { 
 if (action == SCROLL_NEXT && ++mCurrentImage >= mCount) { 
 mCurrentImage = 0; 
 } else if (action == SCROLL_PREVIOUS && --mCurrentImage < 0) { 
 mCurrentImage = mCount - 1; 
 } 
 } 
 /** 
 *               。 
 */ 
 private boolean shouldScrollToNext(int velocityX) { 
 return velocityX < -SNAP_VELOCITY || getScrollX() > mImageWidth / 2; 
 } 
 /** 
 *               。 
 */ 
 private boolean shouldScrollToPrevious(int velocityX) { 
 return velocityX > SNAP_VELOCITY || getScrollX() < -mImageWidth / 2; 
 } 
 /** 
 *          
 */ 
 public interface OnImageSwitchListener { 
 /** 
 *              
 * 
 * @param currentImage 
 *         
 */ 
 void onImageSwitch(int currentImage); 
 } 
} 
이 코드 도 비교적 길 기 때문에 우 리 는 조금씩 분석 을 진행 합 시다.onLayout()방법 에 서 는 먼저 하위 보기 의 개수 가 5 보다 큰 지 판단 해 야 합 니 다.5 개가 부족 하면 그림 재생 기 가 정상적으로 표시 되 지 않 고 return 으로 떨 어 집 니 다.5 개 이상 이면 하나의 for 순환 을 통 해 모든 하위 보기 에 표 시 된 위 치 를 할당 합 니 다.각 하위 보 기 는 하나의 Image3DView 이 고,for 순환 에 서 는 Image3DView 의 initImageViewBitmap()방법 을 사용 하여 모든 컨트롤 에 초기 화 작업 을 수행 한 후 refreshImageShowing()방법 으로 그림 의 표시 상 태 를 새로 고 칩 니 다.
이 어 손가락 이 Image3D SwitchView 컨트롤 에서 미 끄 러 질 때 onTouchEvent()방법 에 들 어 갑 니 다.손가락 을 누 를 때 누 를 때의 가로 좌 표를 기록 한 다음 손가락 이 미 끄 러 질 때 미 끄 러 지 는 거 리 를 계산 하고 scrollBy()방법 으로 스크롤 합 니 다.손가락 이 화면 을 떠 날 때 현재 미 끄 러 지 는 거리 와 속 도 를 결정 합 니 다.다음 그림 으로 스크롤 하 시 겠 습 니까?이전 그림 으로 스크롤 하 시 겠 습 니까?원본 그림 으로 스크롤 하 시 겠 습 니까?각각 호출 하 는 방법 은 scrollToNext(),scrollToPrevious(),scrollBack()입 니 다.
scrollToNext()방법 에 서 는 스크롤 해 야 할 거 리 를 계산 한 다음 경계 검 사 를 통 해 현재 그림 의 아래 표 시 를 합 리 적 인 범 위 를 초과 하지 않도록 한 다음 begin Scroll()방법 으로 스크롤 합 니 다.begin Scroll()방법 에 서 는 스크롤 러 의 startScroll()방법 을 호출 하여 스크롤 작업 을 수행 하 는 것 입 니 다.스크롤 이 끝 난 후에 requestLayout()방법 으로 다시 레이아웃 을 요구 합 니 다.그 후에 onLayout()방법 은 다시 실 행 됩 니 다.그림 마다 위치 가 바 뀝 니 다.scrollToPrevious()와 scrollBack()방법의 원리 도 마찬가지 로 중복 분석 하지 않 습 니 다.
그렇다면 onLayout()방법의 마지막 호출 된 refreshImageShowing()방법 은 도대체 어떤 조작 을 실 행 했 습 니까?사실은 모든 Image3DView 컨트롤 을 옮 겨 다 니 며 setRotateData()방법 을 사용 하고 그림 의 아래 표지 와 스크롤 거 리 를 전달 하면 모든 그림 이 어떻게 회전 해 야 하 는 지 알 수 있 습 니 다.
다른 일부 다른 세부 사항 은 여기 서 설명 하지 않 습 니 다.주석 은 비교적 상세 하 게 쓰 여 있 습 니 다.당신 은 천천히 분석 하고 이해 할 수 있 습 니 다.
그러면 Image3D SwitchView 를 어떻게 사용 하 는 지 알 아 보 겠 습 니 다.이 컨트롤 을 열거 나 새로 만 드 는 activitymain.xml 는 프로그램의 주 레이아웃 파일 로 코드 는 다음 과 같 습 니 다.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 android:background="#fff" > 
 <com.example.imageswitchviewtest.Image3DSwitchView 
 android:id="@+id/image_switch_view" 
 android:layout_width="match_parent" 
 android:layout_height="150dp" > 
 <com.example.imageswitchviewtest.Image3DView 
 android:id="@+id/image1" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 android:scaleType="fitXY" 
 android:src="@drawable/image1" /> 
 <com.example.imageswitchviewtest.Image3DView 
 android:id="@+id/image2" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 android:scaleType="fitXY" 
 android:src="@drawable/image2" /> 
 <com.example.imageswitchviewtest.Image3DView 
 android:id="@+id/image3" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 android:scaleType="fitXY" 
 android:src="@drawable/image3" /> 
 <com.example.imageswitchviewtest.Image3DView 
 android:id="@+id/image4" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 android:scaleType="fitXY" 
 android:src="@drawable/image4" /> 
 <com.example.imageswitchviewtest.Image3DView 
 android:id="@+id/image5" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 android:scaleType="fitXY" 
 android:src="@drawable/image5" /> 
 <com.example.imageswitchviewtest.Image3DView 
 android:id="@+id/image6" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 android:scaleType="fitXY" 
 android:src="@drawable/image6" /> 
 <com.example.imageswitchviewtest.Image3DView 
 android:id="@+id/image7" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 android:scaleType="fitXY" 
 android:src="@drawable/image7" /> 
 </com.example.imageswitchviewtest.Image3DSwitchView> 
</RelativeLayout> 
여기에서 우 리 는 Image3DSwitchView 컨트롤 을 도입 한 다음 에 이 컨트롤 아래 에 7 개의 Image3DView 컨트롤 을 추가 했다.모든 Image3DView 는 사실상 ImageView 이기 때문에 우 리 는 android:src 를 통 해 그림 을 지정 할 수 있다.앞에서 도 말 했 듯 이 Image3D SwitchView 컨트롤 의 하위 컨트롤 은 5 개 이상 이 어야 합 니 다.그렇지 않 으 면 정상적으로 표시 되 지 않 습 니 다.
코드 는 여기까지 쓰 면 별로 차이 가 나 지 않 습 니 다.지금 프로그램 을 실행 하면 3D 버 전의 그림 재생 기 를 볼 수 있 습 니 다.손가락 으로 미 끄 러 지면 더 많은 그림 을 볼 수 있 습 니 다.다음 그림 과 같 습 니 다.

어때요?그래도 효과 가 좋 죠!이외에 도 Image3DSwitchView 에 서 는 setCurrentImage()방법 과 setOnImageSwitchListener()방법 을 제공 하여 현재 어떤 그림 을 표시 할 지 설정 하고 그림 이 굴 러 가 는 감청 기 를 설정 할 수 있 습 니 다.이러한 방법 이 있 으 면 Image3DSwitchView 를 바탕 으로 더욱 쉽게 확장 할 수 있 습 니 다.예 를 들 어 페이지 서명 표시 기능 을 추가 하 는 등 입 니 다.
자,오늘 설명 은 여기까지 입 니 다.의문 이 있 는 친 구 는 아래 에 메 시 지 를 남 길 수 있 습 니 다.
원본 다운로드,여 기 를 클릭 하 세 요.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기