首页 > 系统 > Android > 正文

Android开发实现自定义水平滚动的容器示例

2019-10-22 18:25:31
字体:
来源:转载
供稿:网友

本文实例讲述了Android开发实现自定义水平滚动的容器。分享给大家供大家参考,具体如下:

public class HorizontalScrollView extends ViewGroup {  //手势  private GestureDetector mGestureDetector;  private HorizontalScroller mScroller;  private int curID;  //快速滑动  private boolean isFlying;  //--回调函数-------------------------------------  private OnChangeListener mListener;  public void setOnChangeListener(OnChangeListener listener) {    if (listener != null) {      mListener = listener;    }  }  public interface OnChangeListener{    void move2dest(int curID);  }  public HorizontalScrollView(Context context) {    this(context, null);  }  public HorizontalScrollView(Context context, AttributeSet attrs) {    this(context, attrs, 0);  }  public HorizontalScrollView(Context context, AttributeSet attrs, int defStyle) {    super(context, attrs, defStyle);    mScroller = new HorizontalScroller();    isFlying = false;    initGesture(context);  }  @Override  protected void onLayout(boolean changed, int l, int t, int r, int b) {    // 模向移动,    for (int i = 0; i < getChildCount(); i++) {      View view = getChildAt(i);      //给水平方向的每个view定位      view.layout(i * getWidth(), 0, getWidth() + i * getWidth(), getHeight());    }  }  @Override  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    for (int i = 0; i < getChildCount(); i++) {      View view = getChildAt(i);      view.measure(widthMeasureSpec, heightMeasureSpec);    }    super.onMeasure(widthMeasureSpec, heightMeasureSpec);  }  @Override  public boolean onTouchEvent(MotionEvent event) {    mGestureDetector.onTouchEvent(event);    switch (event.getAction()) {    case MotionEvent.ACTION_DOWN:      if (!isFlying) {        move2dest();      }      isFlying = false;      break;    case MotionEvent.ACTION_MOVE:      break;    case MotionEvent.ACTION_UP:      break;    default:      break;    }    return true;  }  public void move2dest() {    //    int destID = (getScrollX() + getWidth() / 2) / getWidth();    move2dest(destID);  }  public void move2dest(int destID) {    curID = destID;    if (destID > getChildCount() - 1) {      destID = getChildCount() - 1;    }    if (mListener != null) {      mListener.move2dest(curID);    }    int distance = (int) (destID * getWidth() - getScrollX());    // scrollBy(distance, 0);    mScroller.startScroll(getScrollX(), getScrollY(), distance, 0);    invalidate();  }  /**   * invalidate()此方法会触发下面的方法   */  @Override  public void computeScroll() {    // 如果存在偏移,就不断刷新    if (mScroller.computeScrollOffset()) {      scrollTo(mScroller.getCurrX(), 0);      invalidate();    }    super.computeScroll();  }  private void initGesture(Context context) {    mGestureDetector = new GestureDetector(context, new OnGestureListener() {      @Override      public boolean onSingleTapUp(MotionEvent e) {        return false;      }      @Override      public void onShowPress(MotionEvent e) {      }      @Override      public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {        scrollBy((int) distanceX, 0);        return false;      }      @Override      public void onLongPress(MotionEvent e) {      }      @Override      /**       * 快速滑动时       */      public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {        isFlying = true;        if (curID > 0 && velocityX > 0) {// 表示向左移          move2dest(curID - 1);        } else if (curID < getChildCount() && velocityX < 0) {          move2dest(curID + 1);// 向右        } else {          move2dest();// 移到原位        }        return false;      }      @Override      public boolean onDown(MotionEvent e) {        return false;      }    });  }}
/** * 位移计算工具类 * * @author chenlin * */public class HorizontalScroller {  private int startX;  private int startY;  private int distanceX;  private int distanceY;  private int currentX;  private int currentY;  private long startTime;  private long duration = 1000L;  private boolean isFinish;  /**   *   * @param scrollX   *      x坐标   * @param scrollY   *      y坐标   * @param distanceX   *      X方向移动的距离   * @param distanceY   *      y方向移动的距离   */  public void startScroll(int scrollX, int scrollY, int distanceX, int distanceY) {    startX = scrollX;    startY = scrollY;    this.distanceX = distanceX;    this.distanceY = distanceY;    isFinish = false;    startTime = SystemClock.uptimeMillis();  }  /**   * 计算偏移量,   *   * @return true 还在移动 false:移动已经停止   */  public boolean computeScrollOffset() {    if (isFinish) {      return false;    }    long timePassed = SystemClock.uptimeMillis() - startTime;    if (timePassed < duration) {      currentX = (int) (startX + distanceX * timePassed / duration);      currentY = (int) (startY + distanceY * timePassed / duration);      System.out.println("currentX:::" + currentX);    } else if (timePassed >= duration) {      currentX = startX + distanceX;      currentY = startY + distanceY;      isFinish = true;    }    return true;  }  public int getCurrX() {    return currentX;  }  public void setCurrentX(int currentX) {    this.currentX = currentX;  }  public int getCurrentY() {    return currentY;  }  public void setCurrentY(int currentY) {    this.currentY = currentY;  }}

使用方法

public class ScrollActivity extends Activity implements OnCheckedChangeListener, OnChangeListener {  private int[] ids = { R.drawable.a1, R.drawable.a2, R.drawable.a3, R.drawable.a4, R.drawable.a5, R.drawable.a6 };  private HorizontalScrollView mView;  private LinearLayout mLayout;  private RadioGroup mGroup;  @Override  protected void onCreate(Bundle savedInstanceState) {    requestWindowFeature(Window.FEATURE_NO_TITLE);    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_myscrollview);    init();  }  private void init() {    mLayout = (LinearLayout) findViewById(R.id.body_layout);    mGroup = (RadioGroup) findViewById(R.id.radiogroup);    mView = new HorizontalScrollView(this);    for (int i = 0; i < ids.length; i++) {      ImageView imageView = new ImageView(this);      imageView.setBackgroundResource(ids[i]);      mView.addView(imageView);    }    mLayout.addView(mView);    // 随便添加一个view    View view = getLayoutInflater().inflate(R.layout.activity_progressview, null);    mView.addView(view, 3);    for (int i = 0; i < mView.getChildCount(); i++) {      RadioButton radioButton = new RadioButton(this);      // 设置id的编号      radioButton.setId(i);      mGroup.setOrientation(LinearLayout.HORIZONTAL);      mGroup.addView(radioButton);      if (i == 0) {        radioButton.setChecked(true);      }    }    mGroup.setOnCheckedChangeListener(this);    mView.setOnChangeListener(this);  }  @Override  public void onCheckedChanged(RadioGroup group, int checkedId) {    mView.move2dest(checkedId);  }  @Override  public void move2dest(int curID) {    RadioButton radioButton = (RadioButton) mGroup.getChildAt(curID);    radioButton.setChecked(true);  }}

布局文件

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="fill_parent"  android:layout_height="fill_parent"  android:orientation="vertical" >  <RadioGroup    android:id="@+id/radiogroup"    android:layout_width="wrap_content"    android:layout_height="wrap_content" >  </RadioGroup>  <LinearLayout    android:id="@+id/body_layout"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >  </LinearLayout></LinearLayout>

希望本文所述对大家Android程序设计有所帮助。


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表