안 드 로 이 드 는 읽 기 APP 페 이 징 효과 구현
페이지 를 넘 길 때 페이지 오른쪽 가장자리 에 그림자 가 그 려 져 효과 가 좋 습 니 다.이러한 페 이 징 컨트롤 을 실현 하 는 것 은 어렵 지 않 습 니 다.레이아웃 관리 페이지 만 정의 하면 됩 니 다.구체 적 인 실현 에는 다음 과 같은 난점 이 있다.
1.반복 적 으로 페이지 를 넘 기 고 페이지 의 중복 이용.
2.페이지 를 넘 길 때 여러 개의 접촉 을 걸 러 냅 니 다.
3.setAdapter 방식 으로 페이지 레이아웃 과 데 이 터 를 설정 합 니 다.
다음은 이 몇 가지 난점 을 하나하나 해결 하 겠 습 니 다.우선 순환 페이지 넘 기 문 제 를 살 펴 보면 어떻게 비교적 적은 페이지 로 이런 페이지 넘 기 를 실현 할 수 있 습 니까?화면 에 매번 완전한 페이지 만 표시 되 고 넘 어 가 는 페이지 도 보이 지 않 기 때문에 넘 어 가 는 페이지 를 다시 이용 할 수 있 습 니 다.매번 새로운 페이지 가 필요 하지 않 습 니 다.그래서 저 는 세 페이지 만 사용 하여 순환 적 으로 페이지 를 넘 겼 습 니 다.페이지 를 반복 적 으로 이용 하려 면 먼저 페이지 가 레이아웃 에서 번호 와 대응 하 는 차원 관 계 를 알 아야 한다.예 를 들 어 부모 컨트롤 의 하위 view 의 번호 가 클 수록 상층 부 에 있다.페이지 를 순환 적 으로 이용 하 는 원리 도 는 다음 과 같다.
오른쪽으로 페이지 를 넘 길 때 상태 도 는 이 렇 습 니 다.0,1,2 세 페이지 만 사 용 했 습 니 다.페이지 번호 가 2 인 것 은 맨 위 에 있 습 니 다.제 가 왼쪽 에 숨 겼 기 때문에 보 이 는 것 은 페이지 1 뿐 입 니 다.페이지 0 은 1 아래 에서 가 려 도 보이 지 않 습 니 다.오른쪽으로 페이지 를 넘 길 때 페이지 2 는 화면 에 미 끄 러 졌 습 니 다.이때 페이지 0 의 내용 을 페이지 2 의 앞 페이지 내용 으로 바 꾸 었 습 니 다.이전 페이지 2 의 위치 에 놓 으 면 상태 가 다시 초기 상태 로 돌아 가 오른쪽 으로 계속 넘 길 수 있 습 니 다!
왼쪽으로 페이지 를 넘 길 때 는 이 렇 습 니 다.초기 상 태 는 똑 같 습 니 다.페이지 1 이 왼쪽으로 넘 어 졌 을 때 페이지 0 을 보 았 습 니 다.이때 페이지 0 아래 에는 페이지 가 없 었 고 페이지 2 는 사용 할 수 없 었 습 니 다.이때 페이지 2 를 페이지 0 아래 에 놓 았 습 니 다.이때 상태 가 다시 초기 상태 로 돌아 가면 계속 왼쪽으로 페이지 를 넘 길 수 있 습 니 다.
이러한 순환 효과 의 실현 과 비슷 하 게 제 가 사용 해 온 해결 방안 은 모두 선택 한 것 을 가장 중간 에 두 는 것 입 니 다.예 를 들 어 원리 그림 의 페이지 1 은 페이지 를 넘 길 때마다 볼 수 있 는 것 은 모두 페이지 1 입 니 다.스크롤 선택 기 PickerView에서 도 같은 방안 이다.이것 은 페이지 의 중복 이용 문 제 를 해결 했다.
어 려 운 점 2 페이지 를 넘 길 때 다 중 터치 문 제 를 걸 러 내 는 것 은가짜 타 오 바 오 상품 탐색 창에서 해결 되 었 습 니 다.제어 변수 mEvents 로 pointer down 이나 up 을 걸 러 낸 첫 번 째 move 사건 입 니 다.
난점 해결 3 adapter 방식 으로 페이지 의 레이아웃 과 데 이 터 를 설정 합 니 다.이것 은 Android 의 AdapterView 에 사 용 됩 니 다.그러나 저 는 adapter 체 제 를 보지 않 았 습 니 다.너무 복잡 해서 저 는 간단 한 adapter 를 만 들 었 습 니 다.다음 과 같 습 니 다.
PageAdapter.java:
package com.jingchen.pagerdemo;
import android.view.View;
public abstract class PageAdapter
{
/**
* @return view
*/
public abstract View getView();
public abstract int getCount();
/**
* view
*
* @param view
* view
* @param position
* position
*/
public abstract void addContent(View view, int position);
}
이것 은 추상 적 인 클래스 입 니 다.getView()는 페이지 의 레이아웃 을 되 돌려 주 는 데 사 용 됩 니 다.getCount()는 데 이 터 를 되 돌려 주 는 데 총 몇 페이지 가 필요 합 니까?addContent(View view,int position)는 한 페이지 를 넘 길 때마다 페이지 데 이 터 를 요청 하 는 데 사 용 됩 니 다.매개 변수 view 는 페이지 이 고 position 는 몇 페이지 를 표시 합 니 다.잠시 후 사용자 정의 레이아웃 에서 setAdapter 방법 설정 기 를 정의 합 니 다.OK,어 려 운 점 이 모두 해결 되 었 습 니 다.ScanView 가 RelativeLayout 에서 계승 하 는 레이아웃 을 사용자 정의 합 니 다.
ScanView.java:
package com.jingchen.pagerdemo;
import java.util.Timer;
import java.util.TimerTask;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.graphics.Shader.TileMode;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.widget.RelativeLayout;
/**
* @author chenjing
*
*/
public class ScanView extends RelativeLayout
{
public static final String TAG = "ScanView";
private boolean isInit = true;
// ,
private boolean isPreMoving = true, isCurrMoving = true;
//
private int index;
private float lastX;
// , ,
private int prePageLeft = 0, currPageLeft = 0, nextPageLeft = 0;
//
private View prePage, currPage, nextPage;
//
private static final int STATE_MOVE = 0;
private static final int STATE_STOP = 1;
// ,
private static final int PRE = 2;
private static final int CURR = 3;
private int state = STATE_STOP;
// ,
private float right;
//
private float moveLenght;
//
private int mWidth, mHeight;
//
private VelocityTracker vt;
//
private float speed_shake = 20;
//
private float speed;
private Timer timer;
private MyTimerTask mTask;
//
public static final int MOVE_SPEED = 10;
//
private PageAdapter adapter;
/**
*
*/
private int mEvents;
public void setAdapter(ScanViewAdapter adapter)
{
removeAllViews();
this.adapter = adapter;
prePage = adapter.getView();
addView(prePage, 0, new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
adapter.addContent(prePage, index - 1);
currPage = adapter.getView();
addView(currPage, 0, new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
adapter.addContent(currPage, index);
nextPage = adapter.getView();
addView(nextPage, 0, new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
adapter.addContent(nextPage, index + 1);
}
/**
* 。
*
* @param which
*/
private void moveLeft(int which)
{
switch (which)
{
case PRE:
prePageLeft -= MOVE_SPEED;
if (prePageLeft < -mWidth)
prePageLeft = -mWidth;
right = mWidth + prePageLeft;
break;
case CURR:
currPageLeft -= MOVE_SPEED;
if (currPageLeft < -mWidth)
currPageLeft = -mWidth;
right = mWidth + currPageLeft;
break;
}
}
/**
* 。
*
* @param which
*/
private void moveRight(int which)
{
switch (which)
{
case PRE:
prePageLeft += MOVE_SPEED;
if (prePageLeft > 0)
prePageLeft = 0;
right = mWidth + prePageLeft;
break;
case CURR:
currPageLeft += MOVE_SPEED;
if (currPageLeft > 0)
currPageLeft = 0;
right = mWidth + currPageLeft;
break;
}
}
/**
*
*/
private void addPrePage()
{
removeView(nextPage);
addView(nextPage, -1, new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
//
adapter.addContent(nextPage, index - 1);
//
View temp = nextPage;
nextPage = currPage;
currPage = prePage;
prePage = temp;
prePageLeft = -mWidth;
}
/**
* ,
*/
private void addNextPage()
{
removeView(prePage);
addView(prePage, 0, new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
//
adapter.addContent(prePage, index + 1);
//
View temp = currPage;
currPage = nextPage;
nextPage = prePage;
prePage = temp;
currPageLeft = 0;
}
Handler updateHandler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
if (state != STATE_MOVE)
return;
//
// ,
if (prePageLeft > -mWidth && speed <= 0)
{
//
moveLeft(PRE);
} else if (currPageLeft < 0 && speed >= 0)
{
//
moveRight(CURR);
} else if (speed < 0 && index < adapter.getCount())
{
// ,
moveLeft(CURR);
if (currPageLeft == (-mWidth))
{
index++;
// , ,
addNextPage();
}
} else if (speed > 0 && index > 1)
{
// ,
moveRight(PRE);
if (prePageLeft == 0)
{
index--;
// , ,
addPrePage();
}
}
if (right == 0 || right == mWidth)
{
releaseMoving();
state = STATE_STOP;
quitMove();
}
ScanView.this.requestLayout();
}
};
public ScanView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
init();
}
public ScanView(Context context)
{
super(context);
init();
}
public ScanView(Context context, AttributeSet attrs)
{
super(context, attrs);
init();
}
/**
*
*/
public void quitMove()
{
if (mTask != null)
{
mTask.cancel();
mTask = null;
}
}
private void init()
{
index = 1;
timer = new Timer();
mTask = new MyTimerTask(updateHandler);
}
/**
* ,
*/
private void releaseMoving()
{
isPreMoving = true;
isCurrMoving = true;
}
@Override
public boolean dispatchTouchEvent(MotionEvent event)
{
if (adapter != null)
switch (event.getActionMasked())
{
case MotionEvent.ACTION_DOWN:
lastX = event.getX();
try
{
if (vt == null)
{
vt = VelocityTracker.obtain();
} else
{
vt.clear();
}
} catch (Exception e)
{
e.printStackTrace();
}
vt.addMovement(event);
mEvents = 0;
break;
case MotionEvent.ACTION_POINTER_DOWN:
case MotionEvent.ACTION_POINTER_UP:
mEvents = -1;
break;
case MotionEvent.ACTION_MOVE:
//
quitMove();
Log.d("index", "mEvents = " + mEvents + ", isPreMoving = "
+ isPreMoving + ", isCurrMoving = " + isCurrMoving);
vt.addMovement(event);
vt.computeCurrentVelocity(500);
speed = vt.getXVelocity();
moveLenght = event.getX() - lastX;
if ((moveLenght > 0 || !isCurrMoving) && isPreMoving
&& mEvents == 0)
{
isPreMoving = true;
isCurrMoving = false;
if (index == 1)
{
// , activity
state = STATE_MOVE;
releaseMoving();
} else
{
//
prePageLeft += (int) moveLenght;
//
if (prePageLeft > 0)
prePageLeft = 0;
else if (prePageLeft < -mWidth)
{
// , ,
prePageLeft = -mWidth;
releaseMoving();
}
right = mWidth + prePageLeft;
state = STATE_MOVE;
}
} else if ((moveLenght < 0 || !isPreMoving) && isCurrMoving
&& mEvents == 0)
{
isPreMoving = false;
isCurrMoving = true;
if (index == adapter.getCount())
{
//
state = STATE_STOP;
releaseMoving();
} else
{
currPageLeft += (int) moveLenght;
//
if (currPageLeft < -mWidth)
currPageLeft = -mWidth;
else if (currPageLeft > 0)
{
// , ,
currPageLeft = 0;
releaseMoving();
}
right = mWidth + currPageLeft;
state = STATE_MOVE;
}
} else
mEvents = 0;
lastX = event.getX();
requestLayout();
break;
case MotionEvent.ACTION_UP:
if (Math.abs(speed) < speed_shake)
speed = 0;
quitMove();
mTask = new MyTimerTask(updateHandler);
timer.schedule(mTask, 0, 5);
try
{
vt.clear();
vt.recycle();
} catch (Exception e)
{
e.printStackTrace();
}
break;
default:
break;
}
super.dispatchTouchEvent(event);
return true;
}
/*
* ( Javadoc)
*
* @see android.view.ViewGroup#dispatchDraw(android.graphics.Canvas)
*/
@Override
protected void dispatchDraw(Canvas canvas)
{
super.dispatchDraw(canvas);
if (right == 0 || right == mWidth)
return;
RectF rectF = new RectF(right, 0, mWidth, mHeight);
Paint paint = new Paint();
paint.setAntiAlias(true);
LinearGradient linearGradient = new LinearGradient(right, 0,
right + 36, 0, 0xffbbbbbb, 0x00bbbbbb, TileMode.CLAMP);
paint.setShader(linearGradient);
paint.setStyle(Style.FILL);
canvas.drawRect(rectF, paint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth = getMeasuredWidth();
mHeight = getMeasuredHeight();
if (isInit)
{
// , ,
prePageLeft = -mWidth;
currPageLeft = 0;
nextPageLeft = 0;
isInit = false;
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
{
if (adapter == null)
return;
prePage.layout(prePageLeft, 0,
prePageLeft + prePage.getMeasuredWidth(),
prePage.getMeasuredHeight());
currPage.layout(currPageLeft, 0,
currPageLeft + currPage.getMeasuredWidth(),
currPage.getMeasuredHeight());
nextPage.layout(nextPageLeft, 0,
nextPageLeft + nextPage.getMeasuredWidth(),
nextPage.getMeasuredHeight());
invalidate();
}
class MyTimerTask extends TimerTask
{
Handler handler;
public MyTimerTask(Handler handler)
{
this.handler = handler;
}
@Override
public void run()
{
handler.sendMessage(handler.obtainMessage());
}
}
}
코드 에 주석 이 매우 많아 서 원 리 를 이해 하면 코드 를 보면 쉽게 이해 할 수 있다.이 레이아웃 을 다 쓴 다음 ScanViewAdapter 계승 PageAdapter 를 쓰 십시오.
package com.jingchen.pagerdemo;
import java.util.Timer;
import java.util.TimerTask;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.graphics.Shader.TileMode;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.widget.RelativeLayout;
/**
* @author chenjing
*
*/
public class ScanView extends RelativeLayout
{
public static final String TAG = "ScanView";
private boolean isInit = true;
// ,
private boolean isPreMoving = true, isCurrMoving = true;
//
private int index;
private float lastX;
// , ,
private int prePageLeft = 0, currPageLeft = 0, nextPageLeft = 0;
//
private View prePage, currPage, nextPage;
//
private static final int STATE_MOVE = 0;
private static final int STATE_STOP = 1;
// ,
private static final int PRE = 2;
private static final int CURR = 3;
private int state = STATE_STOP;
// ,
private float right;
//
private float moveLenght;
//
private int mWidth, mHeight;
//
private VelocityTracker vt;
//
private float speed_shake = 20;
//
private float speed;
private Timer timer;
private MyTimerTask mTask;
//
public static final int MOVE_SPEED = 10;
//
private PageAdapter adapter;
/**
*
*/
private int mEvents;
public void setAdapter(ScanViewAdapter adapter)
{
removeAllViews();
this.adapter = adapter;
prePage = adapter.getView();
addView(prePage, 0, new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
adapter.addContent(prePage, index - 1);
currPage = adapter.getView();
addView(currPage, 0, new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
adapter.addContent(currPage, index);
nextPage = adapter.getView();
addView(nextPage, 0, new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
adapter.addContent(nextPage, index + 1);
}
/**
* 。
*
* @param which
*/
private void moveLeft(int which)
{
switch (which)
{
case PRE:
prePageLeft -= MOVE_SPEED;
if (prePageLeft < -mWidth)
prePageLeft = -mWidth;
right = mWidth + prePageLeft;
break;
case CURR:
currPageLeft -= MOVE_SPEED;
if (currPageLeft < -mWidth)
currPageLeft = -mWidth;
right = mWidth + currPageLeft;
break;
}
}
/**
* 。
*
* @param which
*/
private void moveRight(int which)
{
switch (which)
{
case PRE:
prePageLeft += MOVE_SPEED;
if (prePageLeft > 0)
prePageLeft = 0;
right = mWidth + prePageLeft;
break;
case CURR:
currPageLeft += MOVE_SPEED;
if (currPageLeft > 0)
currPageLeft = 0;
right = mWidth + currPageLeft;
break;
}
}
/**
*
*/
private void addPrePage()
{
removeView(nextPage);
addView(nextPage, -1, new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
//
adapter.addContent(nextPage, index - 1);
//
View temp = nextPage;
nextPage = currPage;
currPage = prePage;
prePage = temp;
prePageLeft = -mWidth;
}
/**
* ,
*/
private void addNextPage()
{
removeView(prePage);
addView(prePage, 0, new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
//
adapter.addContent(prePage, index + 1);
//
View temp = currPage;
currPage = nextPage;
nextPage = prePage;
prePage = temp;
currPageLeft = 0;
}
Handler updateHandler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
if (state != STATE_MOVE)
return;
//
// ,
if (prePageLeft > -mWidth && speed <= 0)
{
//
moveLeft(PRE);
} else if (currPageLeft < 0 && speed >= 0)
{
//
moveRight(CURR);
} else if (speed < 0 && index < adapter.getCount())
{
// ,
moveLeft(CURR);
if (currPageLeft == (-mWidth))
{
index++;
// , ,
addNextPage();
}
} else if (speed > 0 && index > 1)
{
// ,
moveRight(PRE);
if (prePageLeft == 0)
{
index--;
// , ,
addPrePage();
}
}
if (right == 0 || right == mWidth)
{
releaseMoving();
state = STATE_STOP;
quitMove();
}
ScanView.this.requestLayout();
}
};
public ScanView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
init();
}
public ScanView(Context context)
{
super(context);
init();
}
public ScanView(Context context, AttributeSet attrs)
{
super(context, attrs);
init();
}
/**
*
*/
public void quitMove()
{
if (mTask != null)
{
mTask.cancel();
mTask = null;
}
}
private void init()
{
index = 1;
timer = new Timer();
mTask = new MyTimerTask(updateHandler);
}
/**
* ,
*/
private void releaseMoving()
{
isPreMoving = true;
isCurrMoving = true;
}
@Override
public boolean dispatchTouchEvent(MotionEvent event)
{
if (adapter != null)
switch (event.getActionMasked())
{
case MotionEvent.ACTION_DOWN:
lastX = event.getX();
try
{
if (vt == null)
{
vt = VelocityTracker.obtain();
} else
{
vt.clear();
}
} catch (Exception e)
{
e.printStackTrace();
}
vt.addMovement(event);
mEvents = 0;
break;
case MotionEvent.ACTION_POINTER_DOWN:
case MotionEvent.ACTION_POINTER_UP:
mEvents = -1;
break;
case MotionEvent.ACTION_MOVE:
//
quitMove();
Log.d("index", "mEvents = " + mEvents + ", isPreMoving = "
+ isPreMoving + ", isCurrMoving = " + isCurrMoving);
vt.addMovement(event);
vt.computeCurrentVelocity(500);
speed = vt.getXVelocity();
moveLenght = event.getX() - lastX;
if ((moveLenght > 0 || !isCurrMoving) && isPreMoving
&& mEvents == 0)
{
isPreMoving = true;
isCurrMoving = false;
if (index == 1)
{
// , activity
state = STATE_MOVE;
releaseMoving();
} else
{
//
prePageLeft += (int) moveLenght;
//
if (prePageLeft > 0)
prePageLeft = 0;
else if (prePageLeft < -mWidth)
{
// , ,
prePageLeft = -mWidth;
releaseMoving();
}
right = mWidth + prePageLeft;
state = STATE_MOVE;
}
} else if ((moveLenght < 0 || !isPreMoving) && isCurrMoving
&& mEvents == 0)
{
isPreMoving = false;
isCurrMoving = true;
if (index == adapter.getCount())
{
//
state = STATE_STOP;
releaseMoving();
} else
{
currPageLeft += (int) moveLenght;
//
if (currPageLeft < -mWidth)
currPageLeft = -mWidth;
else if (currPageLeft > 0)
{
// , ,
currPageLeft = 0;
releaseMoving();
}
right = mWidth + currPageLeft;
state = STATE_MOVE;
}
} else
mEvents = 0;
lastX = event.getX();
requestLayout();
break;
case MotionEvent.ACTION_UP:
if (Math.abs(speed) < speed_shake)
speed = 0;
quitMove();
mTask = new MyTimerTask(updateHandler);
timer.schedule(mTask, 0, 5);
try
{
vt.clear();
vt.recycle();
} catch (Exception e)
{
e.printStackTrace();
}
break;
default:
break;
}
super.dispatchTouchEvent(event);
return true;
}
/*
* ( Javadoc)
*
* @see android.view.ViewGroup#dispatchDraw(android.graphics.Canvas)
*/
@Override
protected void dispatchDraw(Canvas canvas)
{
super.dispatchDraw(canvas);
if (right == 0 || right == mWidth)
return;
RectF rectF = new RectF(right, 0, mWidth, mHeight);
Paint paint = new Paint();
paint.setAntiAlias(true);
LinearGradient linearGradient = new LinearGradient(right, 0,
right + 36, 0, 0xffbbbbbb, 0x00bbbbbb, TileMode.CLAMP);
paint.setShader(linearGradient);
paint.setStyle(Style.FILL);
canvas.drawRect(rectF, paint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth = getMeasuredWidth();
mHeight = getMeasuredHeight();
if (isInit)
{
// , ,
prePageLeft = -mWidth;
currPageLeft = 0;
nextPageLeft = 0;
isInit = false;
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
{
if (adapter == null)
return;
prePage.layout(prePageLeft, 0,
prePageLeft + prePage.getMeasuredWidth(),
prePage.getMeasuredHeight());
currPage.layout(currPageLeft, 0,
currPageLeft + currPage.getMeasuredWidth(),
currPage.getMeasuredHeight());
nextPage.layout(nextPageLeft, 0,
nextPageLeft + nextPage.getMeasuredWidth(),
nextPage.getMeasuredHeight());
invalidate();
}
class MyTimerTask extends TimerTask
{
Handler handler;
public MyTimerTask(Handler handler)
{
this.handler = handler;
}
@Override
public void run()
{
handler.sendMessage(handler.obtainMessage());
}
}
}
여 기 는 제 demo 에 쓰 인 Adapter 일 뿐 더 많은 내용 을 가 진 Adapter 로 쓸 수 있 습 니 다.addContent 에 있 는 매개 변수 view 는 getView 에서 돌아 오 는 view 입 니 다.그러면 inflate 의 레이아웃 에 따라 내용 을 설정 할 수 있 습 니 다.getView 가 돌아 오 는 레이아웃 pagelayout.xml 는 다음 과 같 습 니 다.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/cover" >
<TextView
android:id="@+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="60dp"
android:padding="10dp"
android:textColor="#000000"
android:textSize="22sp" />
<TextView
android:id="@+id/index"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="60dp"
android:textColor="#000000"
android:textSize="30sp" />
</RelativeLayout>
두 개의 TextView 만 포함 되 어 있 기 때문에 adapter 에서 id 에 따라 이 두 개의 TextView 를 찾 아 내용 을 설정 할 수 있 습 니 다.OK,MainActivity 의 레이아웃 은 다음 과 같 습 니 다.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/cover" >
<TextView
android:id="@+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="60dp"
android:padding="10dp"
android:textColor="#000000"
android:textSize="22sp" />
<TextView
android:id="@+id/index"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="60dp"
android:textColor="#000000"
android:textSize="30sp" />
</RelativeLayout>
간단 합 니 다.ScanView 만 포함 되 어 있 습 니 다.MainActivity 코드:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/cover" >
<TextView
android:id="@+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="60dp"
android:padding="10dp"
android:textColor="#000000"
android:textSize="22sp" />
<TextView
android:id="@+id/index"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="60dp"
android:textColor="#000000"
android:textSize="30sp" />
</RelativeLayout>
ScanView 에 Adapter 를 설정 하면 됩 니 다.자,많이 본 것 을 본 떠 서 페이지 를 넘 기 면 됩 니 다.
본 고 는 여러분 들 이 안 드 로 이 드 소프트웨어 프로 그래 밍 을 배 우 는 데 도움 이 되 기 를 바 랍 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 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에 따라 라이센스가 부여됩니다.