Android 는 Horizontal ScrollView 를 이용 하여 ViewPager 를 모방 하여 간단 한 앨범 을 디자인 합 니 다.

최근 한 동 영상 공개 수업 을 배 웠 는데 Horizontal ScrollView 를 이용 하여 ViewPager 디자인 을 모방 한 간단 한 앨범 이 있 는데 사실은 주로 ViewPager 캐 시 를 사용 한 다 는 사상 을 강의 했다.이 글 참고:Android 사용자 정의 Horizontal ScrollView 강력 한 갤러리 효과 만 들 기
 여기 서 ViewPager 의 캐 시 메커니즘 을 간단히 말씀 드 리 겠 습 니 다.
       1.ViewPager 에 들 어 갈 때 현재 페이지 와 다음 페이지 를 불 러 옵 니 다.
       2.ViewPager 를 다음 페이지 로 미 끄 러 뜨 릴 때 다음 페이지 를 불 러 옵 니 다.이때 첫 페이지 는 삭제 되 지 않 고 현재 페이지 의 다음 페이지 를 불 러 옵 니 다.
사실은 기본적으로 3 페이지,현재 페이지,앞 페이지 와 뒤 페이지 를 불 러 옵 니 다.
이 Horizontal ScrollView 는 기본적으로 두 페이지 를 불 러 옵 니 다.그렇지 않 으 면 스케줄 링 코드 가 어 지 럽 습 니 다.
말 이 많 지 않 습 니 다.코드 를 올 립 니 다.
코드 구 조 는 다음 그림 과 같다.

하나의 View,하나의 Adapter,하나의 MainActivity,설명 할 필요 가 없다 고 믿 습 니 다.여러분 도 잘 알 고 있 습 니 다.전형 적 인 MVC 모델~

package com.ssa.horizontalscrollview.myview; 
 
import java.util.HashMap; 
import java.util.Map; 
 
import com.ssa.horizontalscrollview.myUtils.DisplayUtil; 
 
import android.content.Context; 
import android.graphics.Color; 
import android.util.AttributeSet; 
import android.util.Log; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.HorizontalScrollView; 
import android.widget.LinearLayout; 
 
public class GalleryHorizontalScrollView extends HorizontalScrollView implements 
    OnClickListener { 
  private LinearLayout mContainer;// MyHorizontalScrollView  LinearLayout 
  private int mChildWidth;//        
  private int mChildHeight;//        
 
  private int mAllLastIndex;//         index 
  private int mdisplayLastIndex;//           index 
  private int mAllFirstIndex;//       index 
 
  private GalleryHorizontalScrollViewAdapter mAdapter;//       
  private int mScreenWidth;//       
 
  private int mCountOneScreen; 
 
  private Map<View, Integer> mViewPos = new HashMap<View, Integer>(); 
 
  private OnCurrentImageChangeListener mOnCurrentImageChangeListener; 
 
  private OnClickImageChangeListener mOnClickImageChangeListener; 
 
  public void setmOnCurrentImageChangeListener( 
      OnCurrentImageChangeListener mListener) { 
    this.mOnCurrentImageChangeListener = mListener; 
  } 
 
  public void setmOnClickImageListener(OnClickImageChangeListener mListener) { 
    this.mOnClickImageChangeListener = mListener; 
  } 
 
  /** 
   *           
   */ 
  public interface OnCurrentImageChangeListener { 
    void onCurrentImgChanged(int position, View view); 
  } 
 
  /** 
   *           
   */ 
  public interface OnClickImageChangeListener { 
    void onClickImageChangeListener(int position, View view); 
  } 
 
  public GalleryHorizontalScrollView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    //        
    mScreenWidth = getResources().getDisplayMetrics().widthPixels; 
  } 
 
  /** 
   *      ,      
   */ 
  public void initData(GalleryHorizontalScrollViewAdapter mAdapter) { 
    this.mAdapter = mAdapter; 
    mContainer = (LinearLayout) getChildAt(0); 
    final View view = mAdapter.getView(0, null, mContainer); 
    mContainer.addView(view); 
    if (mChildHeight == 0 && mChildWidth == 0) { 
      /*int w = View.MeasureSpec.makeMeasureSpec(0, 
          View.MeasureSpec.UNSPECIFIED); 
      int h = View.MeasureSpec.makeMeasureSpec(0, 
          View.MeasureSpec.UNSPECIFIED);*/ 
      /** 
       *               ,        ,   0 View.MeasureSpec.UNSPECIFIED          ; 
       *         
       *  View match_parent ,     View   (       ,        ,              ,           ) 
       *  View         ,  100px: 
       * int w =View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY); 
       * int h =View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY); 
       * view.measure(w, h); 
       *  View   wrap_content : 
       * int w =View.MeasureSpec.makeMeasureSpec((1<<30)-1, View.MeasureSpec.AT_MOST); 
       * int h =View.MeasureSpec.makeMeasureSpec((1<<30)-1, View.MeasureSpec.AT_MOST); 
       * view.measure(w, h); 
       * 
       *    View      150dip,   wrap_content 
       */ 
      int heightPx = DisplayUtil.dip2px(getContext(), 150); 
      int w =View.MeasureSpec.makeMeasureSpec((1<<30)-1, View.MeasureSpec.AT_MOST); 
      int h =View.MeasureSpec.makeMeasureSpec(heightPx, View.MeasureSpec.EXACTLY); 
      view.measure(w, h); 
      mChildHeight = view.getMeasuredHeight(); 
      mChildWidth = view.getMeasuredWidth(); 
      //          item 
      mdisplayLastIndex = mScreenWidth / mChildWidth; 
      mCountOneScreen = mdisplayLastIndex + 1; 
      initFirstScreenChildren(mdisplayLastIndex + 1); 
 
    } 
  } 
 
  /** 
   *          
   * 
   * @param mDisplayCountOneScreen 
   */ 
  private void initFirstScreenChildren(int mDisplayCountOneScreen) { 
    mContainer = (LinearLayout) getChildAt(0); 
    mContainer.removeAllViews(); 
    mViewPos.clear(); 
    for (int i = 0; i < mDisplayCountOneScreen; i++) { 
      View view = mAdapter.getView(i, null, mContainer); 
      //          
      view.setOnClickListener(this); 
      mContainer.addView(view); 
      mViewPos.put(view, i); 
      mAllLastIndex = i; 
    } 
 
    //          
    if (null != mOnCurrentImageChangeListener) { 
      notifyCurrentImgChanged(); 
    } 
  } 
 
  private void notifyCurrentImgChanged() { 
    //           ,         
    for (int i = 0; i < mContainer.getChildCount(); i++) { 
      mContainer.getChildAt(i).setBackgroundColor(Color.WHITE); 
    } 
    mOnCurrentImageChangeListener.onCurrentImgChanged(mAllFirstIndex, 
        mContainer.getChildAt(0)); 
  } 
 
  @Override 
  public boolean onTouchEvent(MotionEvent ev) { 
    /* 
     * Log.e("X", getX()+""); Log.e("ChildX", 
     * mContainer.getChildAt(0).getX()+""); Log.e("RawX",getLeft() +""); 
     */ 
    switch (ev.getAction()) { 
 
    case MotionEvent.ACTION_MOVE: 
      int scrollX = getScrollX(); 
      Log.e("ScrollX", scrollX + ""); 
      if (scrollX >= mChildWidth) { 
        //      ,      
        loadNextImg(); 
      } 
      if (scrollX == 0) { 
        //      ,       
        loadPreImg(); 
      } 
      break; 
    } 
 
    return super.onTouchEvent(ev); 
  } 
 
  private void loadNextImg() {//         
    if (mAllLastIndex == mAdapter.getCount() - 1) { 
      return; 
    } 
    //        ,         0 
    scrollTo(0, 0); 
    mViewPos.remove(mContainer.getChildAt(0)); 
    mContainer.removeViewAt(0); 
 
    //        ,    onclick  ,       
    View view = mAdapter.getView(++mAllLastIndex, null, mContainer); 
    view.setOnClickListener(this); 
    mContainer.addView(view); 
    mViewPos.put(view, mAllLastIndex); 
 
    //           
    mAllFirstIndex++; 
    //              
    if (mOnCurrentImageChangeListener != null) { 
      notifyCurrentImgChanged(); 
    } 
 
  } 
 
  private void loadPreImg() { 
    if (mAllFirstIndex == 0) { 
      return; 
    } 
    int index = mAllLastIndex - mCountOneScreen; 
    if (index >= 0) { 
      //        
      int oldViewPos = mContainer.getChildCount() - 1; 
      mViewPos.remove(mContainer.getChildAt(oldViewPos)); 
      mContainer.removeViewAt(oldViewPos); 
      //     View        
      View view = mAdapter.getView(index, null, mContainer); 
      mViewPos.put(view, index); 
      mContainer.addView(view, 0); 
      view.setOnClickListener(this); 
      //           View       
      scrollTo(mChildWidth, 0); 
 
      mAllLastIndex--; 
      mAllFirstIndex--; 
 
      if (null != mOnCurrentImageChangeListener) { 
        notifyCurrentImgChanged(); 
      } 
    } 
  } 
 
  @Override 
  public void onClick(View v) { 
    if(null!=mOnClickImageChangeListener){ 
      mOnClickImageChangeListener.onClickImageChangeListener(mViewPos.get(v), v); 
    } 
  } 
} 
다음은 Adapter 의 원본 코드 입 니 다.

package com.ssa.horizontalscrollview.myview; 
 
import java.util.List; 
 
import com.ssa.horizontalscrollview.R; 
 
import android.content.Context; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.ImageView; 
import android.widget.TextView; 
 
public class GalleryHorizontalScrollViewAdapter { 
  private LayoutInflater mInflater; 
  private List<Integer> mDatas; 
 
  public GalleryHorizontalScrollViewAdapter(Context context, List<Integer> mDatas) { 
    mInflater = LayoutInflater.from(context); 
    this.mDatas = mDatas; 
  } 
 
  public Object getItem(int position) { 
    return mDatas.get(position); 
  } 
 
  public long getItemId(int position) { 
    return position; 
  } 
 
  public int getCount() { 
    return mDatas.size(); 
  } 
   
  public View getView(int position, View contentView, ViewGroup parent) { 
    ViewHolder myHolder = null; 
    if (null == contentView) { 
      contentView = mInflater.inflate(R.layout.activity_gallery_item, 
          parent, false); 
      myHolder = new ViewHolder(contentView); 
      contentView.setTag(myHolder); 
    }else { 
      myHolder = (ViewHolder)contentView.getTag(); 
    } 
    myHolder.ivImg.setImageResource(mDatas.get(position)); 
    myHolder.tvText.setText("Img_"+position); 
     
     
    return contentView; 
  } 
 
  private static class ViewHolder { 
    ImageView ivImg; 
    TextView tvText; 
 
    public ViewHolder(View view) { 
      ivImg = (ImageView)view.findViewById(R.id.iv_content); 
      tvText =(TextView)view.findViewById(R.id.tv_index); 
    } 
  } 
 
} 
다음은 MainActivity 의 소스 코드 입 니 다.

package com.ssa.horizontalscrollview; 
 
import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.List; 
 
import android.app.Activity; 
import android.graphics.Color; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.ImageView; 
 
import com.ssa.horizontalscrollview.myview.GalleryHorizontalScrollView; 
import com.ssa.horizontalscrollview.myview.GalleryHorizontalScrollView.OnClickImageChangeListener; 
import com.ssa.horizontalscrollview.myview.GalleryHorizontalScrollView.OnCurrentImageChangeListener; 
import com.ssa.horizontalscrollview.myview.GalleryHorizontalScrollViewAdapter; 
 
public class MainActivity extends Activity { 
  private GalleryHorizontalScrollView mHorizontalScrollView; 
  private GalleryHorizontalScrollViewAdapter mAdapter; 
  private ImageView mImg; 
  private List<Integer> mDatas = new ArrayList<Integer>(Arrays.asList( 
      R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, 
      R.drawable.e,R.drawable.f,R.drawable.g)); 
   
   
 
  @Override 
  protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    mImg = (ImageView)findViewById(R.id.iv_content); 
    mHorizontalScrollView = (GalleryHorizontalScrollView)findViewById(R.id.mhsv_gallery_container); 
    mAdapter = new GalleryHorizontalScrollViewAdapter(this, mDatas); 
    mHorizontalScrollView.setmOnCurrentImageChangeListener(new OnCurrentImageChangeListener() { 
       
      @Override 
      public void onCurrentImgChanged(int position, View view) { 
        mImg.setImageResource(mDatas.get(position)); 
        view.setBackgroundColor(Color.parseColor("#6d9eeb")); 
      } 
    }); 
    mHorizontalScrollView.setmOnClickImageListener(new OnClickImageChangeListener() { 
       
      @Override 
      public void onClickImageChangeListener(int position, View view) { 
        mImg.setImageResource(mDatas.get(position)); 
      } 
    }); 
    mHorizontalScrollView.initData(mAdapter); 
  } 
} 
일부 에 이 르 러 디 버 깅 운행 을 하면 독자 들 은 전체 앨범 이 매우 끊 길 것 이라는 것 을 알 게 될 것 이다.

심지어 어떤 그림 은 img 처럼 보이 지 않 는 다.4.logcat 를 보면 원인 을 발견 할 수 있 을 거 라 고 믿 습 니 다.

정 보 는 이미 명확 하 게 제시 되 었 고 그림 이 너무 크다.
이때 여러분 은 필자 가 일부러 몇 장의 큰 그림 을 선택 하여 불 러 왔 다 는 것 을 알 아야 합 니 다.비록 응용 프로그램 을 무 너 뜨 릴 정도 로 크 지 는 않 지만 체험 성 이 매우 나 빠 졌 습 니 다.이것 은 수업 시간 에 선생님 이 강의 할 때 사용 하 는 그림 이 모두 몇 십 K 의 작은 그림 이기 때문에 불 러 오 는 데 문제 가 없 을 것 입 니 다.그래서 이 앨범 을 실 용적 인 앨범 으로 만 들 려 면그림 이 너무 큰 문 제 를 처리 해 야 한다.그렇지 않 으 면 여전히 OOM 을 초래 할 것 이다.
이 때 이 도구 류 를 사용 합 니 다.

package com.ssa.horizontalscrollview.myUtils; 
 
import android.content.res.Resources; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
 
public class BitmapUtil { 
  public static Bitmap decodeSampledBitmapFromResources(Resources res, 
      int resId, int reqWidth, int reqHeight) { 
    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeResource(res, resId, options); 
    options.inSampleSize = calculateInsampleSize(options, reqWidth, 
        reqHeight); 
    options.inJustDecodeBounds = false; 
    return BitmapFactory.decodeResource(res, resId, options); 
 
  } 
 
  public static int calculateInsampleSize(BitmapFactory.Options options, 
      int reqWidth, int reqHeight) { 
    final int height = options.outHeight; 
    final int width = options.outWidth; 
    int inSampleSize = 1; 
    if (height > reqHeight || width > reqWidth) { 
      final int halfHeight = height / 2; 
      final int halfWidth = width / 2; 
      while ((halfHeight / inSampleSize) >= reqHeight 
          && (halfWidth / inSampleSize) >= reqWidth) { 
        inSampleSize *= 2; 
      } 
    } 
 
    return inSampleSize; 
  } 
} 
이 도구 류 를 추 가 했 습 니 다.위의 몇 가지 코드 도 약간 수정 해 야 합 니 다.구체 적 으로 어떻게 고 치 는 지 아래 에 제 가 올 린 소스 코드 를 다운로드 하 실 수 있 습 니 다.
효 과 는 다음 과 같 습 니 다.

원본 다운로드:Horizontal ScrollView 모조 ViewPager 디자인 앨범
이상 은 본 고의 모든 내용 입 니 다.여러분 이 안 드 로 이 드 소프트웨어 프로 그래 밍 을 배 우 는 데 도움 이 되 기 를 바 랍 니 다.

좋은 웹페이지 즐겨찾기