模仿ViewPager控件

自定義控件是開發中常用的技術。系統中自帶的ViewPager實現的功能有時候不能知足開發的須要,如ViewPager沒有滑動圖片時的動畫切換效果。經過對 ViewPager的模仿和部分功能的增強,能夠使學習者瞭解自定義ViewGroup的實現過程,以及系統動畫的實現原理。android

 

第一步:繼承ViewGroup,就必須重載父類的構造方法,和onLayout()方法。首先建立一個類,起名MyViewPager,繼承ViewGroup
public class MyViewPager extends ViewGroup {
private int page;//當前頁的索引
private GestureDetector detector;//手勢探測
private Context context;//控件創立的上下文
private MyScroller scroller;//緩慢頁面切換幫助類,
private boolean isFling;//用於判斷
private MyViewOnPageChangedListener listener;//頁面變化監聽事件
/**
*創建兩個參數的構造函數,用於在佈局文件中使用。在構造函數中,調用initView()方法初始化控件,建立GestureDetector對象,響應屏幕觸摸事件。
*/
public MyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.context=context;
// TODO Auto-generated constructor stub
initView();
}
public void initView(){
scroller=new MyScroller();
detector=new GestureDetector(context,new GestureDetector.OnGestureListener(){
 
@Override
public boolean onDown(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
 
@Override
public void onShowPress(MotionEvent e) {
// TODO Auto-generated method stub
 
}
 
@Override
public boolean onSingleTapUp(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
/**
 * 圖片緩慢滑動效果
 */
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
// TODO Auto-generated method stub
scrollBy((int)distanceX,0);
return false;
}
 
@Override
public void onLongPress(MotionEvent e) {
// TODO Auto-generated method stub
 
}
/**
 * 圖片快速滑動切換
 */
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2,
float velocityX, float velocityY) {
// TODO Auto-generated method stub
isFling=true;
if(velocityX<0&&page<getChildCount()-1){
page++;
}else if(velocityX>0&&page>0){
page--;
}
moveToDes(page);
return false;
}});
}
/** * 設置子view的佈局,使其按照父控件的大小沿着水平方向展開 */
 
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
for(int i=0;i<getChildCount();i++){
getChildAt(i).layout(i*getWidth(),0,getWidth()+i*getWidth(),getHeight());
}
}
/** * 重載onTouchEvent方法,設置page值,當手指滑動超過二分之一屏幕寬度時,切換到下一個或上一個頁面, * 當不足二分之一屏幕寬度時,頁面不切換 */
 
private int firstPosition;//記錄手指按下時的位置
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
detector.onTouchEvent(event);
 super.onTouchEvent(event);
 
 switch (event.getAction()) {
 
case MotionEvent.ACTION_DOWN:
firstPosition=(int)event.getX();
break;
case MotionEvent.ACTION_UP:
/**
 * 用isFling區分緩慢移動和快速移動
 */
if(!isFling){
if(event.getX()-firstPosition>getWidth()/2){
page=page-1;
}else if(firstPosition-event.getX()>getWidth()/2){
page=page+1;
}
moveToDes(page);
break;
}
isFling=false;
}
 return true;
}
 
/**
 * 使其移動到page相應的頁面
 * @param page
 */
public  void moveToDes(int page) {
// TODO Auto-generated method stub
if(page<=0){
page=0;
}
if(page>=getChildCount()-1){
page=getChildCount()-1;
}
/**
 * 迅速頁面切換
 */
//scrollTo(page*getWidth(), 0);
/**
 * 添加頁面變化監聽,監聽事件放入常常調用的方法裏,顯示事件的常常調用
 */
listener.onPageChanged(page);
 
//緩慢頁面切換動畫
int distance=page*getWidth()-getScrollX();
scroller.startScroll(getScrollX(), distance);
invalidate();//刷新頁面,重畫,而且從新執行computeScroll()
}
//重複執行該方法,實現動畫效果
@Override
public void computeScroll() {
// TODO Auto-generated method stub
super.computeScroll();
if(scroller.isScrolling()){
scrollTo(scroller.getCurrentX(), 0);
invalidate();
}
 
}
 
/**
 * 設置監聽事件方法
 * @param listener
 */
public void setPageChangedListener(MyViewOnPageChangedListener listener){
this.listener=listener;
}
/**
 * 監聽事件接口,監聽頁面變化
 * @author Charles
 *
 */
interface MyViewOnPageChangedListener{
public void onPageChanged(int page);
}
 
}
 
第二步:自定義MyScroller
public class MyScroller {
public int distance;//動畫運行距離
public int startX;//動畫開始位置
public boolean isFinish;//判斷動畫是否完成
public int startTime;//動畫開始時間
public int duration=500;//動畫持續時間
public int currentX;//當前座標
 
public void startScroll(int startX,int distance){
this.distance=distance;
this.startX=startX;
startTime=(int)SystemClock.uptimeMillis();
isFinish=false;
}
public boolean isScrolling(){
if(isFinish){
return false;
}
 
int lastTime=(int)SystemClock.uptimeMillis()-startTime;
if(lastTime<=duration){
currentX=startX+lastTime*distance/duration;//經過當前時間,判斷當前位置
 
}else{
currentX=startX+distance;
isFinish=true;
}
return true;
}
public int getCurrentX(){
return currentX;
}
}
 
第三步:定義佈局文件,將自定義的控件放到佈局文件中
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.define_ViewPager.MainActivity" >
<RadioGroup
    android:id="@+id/group"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="30dp"/>
 
    <com.example.define_ViewPager.MyViewPager
        android:id="@+id/myViewPager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        />
 
</LinearLayout>
 
 
第四步:在Activity中,將準備好的圖片加載到MyViewPager中
public class MainActivity extends Activity {
private MyViewPager viewPager;
private RadioGroup group;//選擇按鈕組
private int[] images={R.drawable.a1,R.drawable.a2,R.drawable.a3
,R.drawable.a4,R.drawable.a5,R.drawable.a6};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager=(MyViewPager) findViewById(R.id.myViewPager);
group=(RadioGroup) findViewById(R.id.group);
//加載圖片
for(int i=0;i<images.length;i++){
View view=new View(this);
view.setBackgroundResource(images[i]);
viewPager.addView(view);
 
}
//添加單選按鈕到group中
for(int i=0;i<viewPager.getChildCount();i++){
RadioButton button=new RadioButton(this);
button.setId(i);
if(i==0){
button.setChecked(true);
}
group.addView(button);
}
/**
 * 設置監聽方法,當頁面變化時,使相應的RadioButton選中
 */
viewPager.setPageChangedListener(new MyViewOnPageChangedListener(){
 
@Override
public void onPageChanged(int page) {
// TODO Auto-generated method stub
RadioButton button=(RadioButton)group.getChildAt(page);
button.setChecked(true);
 
}});
group.setOnCheckedChangeListener(new OnCheckedChangeListener(){
 
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
// TODO Auto-generated method stub
viewPager.moveToDes(checkedId);//移動到選中頁
}});
}
 
}
相關文章
相關標籤/搜索