• 模仿ViewPager控件


    自定义控件是开发中经常使用的技术。系统中自带的ViewPager实现的功能有时候不能满足开发的需要,如ViewPager没有滑动图片时的动画切换效果。通过对 ViewPager的模仿和部分功能的加强,可以使学习者了解自定义ViewGroup的实现过程,以及系统动画的实现原理。

     

    第一步:继承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);//移动到选中页
    }});
    }
     
    }
     
  • 相关阅读:
    Bootstrap 网格系统(Grid System)实例2
    Bootstrap 网格系统(Grid System)实例1
    Bootstrap 网格系统(Grid System)
    Bootstrap CSS概览
    Bootstrap响应式布局(1)
    46、谈谈你对面向对象的理解?
    算法--练习题1
    堆排序----赠品2
    计数排序----赠品1
    45、如何使用python删除一个文件?
  • 原文地址:https://www.cnblogs.com/android-blogs/p/5995671.html
Copyright © 2020-2023  润新知