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

时间:2022-07-28
本文章向大家介绍Android开发实现自定义水平滚动的容器示例,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

本文实例讲述了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基本组件用法总结》、《Android开发入门与进阶教程》、《Android布局layout技巧总结》、《Android视图View技巧总结》、《Android编程之activity操作技巧总结》、《Android资源操作技巧汇总》及《Android控件用法总结》

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