Android 는 Horizontal ScrollView 를 이용 하여 ViewPager 를 모방 하여 간단 한 앨범 을 디자인 합 니 다.
여기 서 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 디자인 앨범
이상 은 본 고의 모든 내용 입 니 다.여러분 이 안 드 로 이 드 소프트웨어 프로 그래 밍 을 배 우 는 데 도움 이 되 기 를 바 랍 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.