通过scroller实现轮播View控件:
效果:
public class BannerLoopLayout extends ViewGroup {
private Scroller mScroller;
public BannerLoopLayout(Context context) {
this(context,null,0);
}
public BannerLoopLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BannerLoopLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mScroller = new Scroller(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int w = MeasureSpec.getSize(widthMeasureSpec);
int h = MeasureSpec.getSize(heightMeasureSpec);
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
LayoutParams lp = child.getLayoutParams();
lp.width = w;
lp.height = h;
child.setLayoutParams(lp);
measureChild(child,widthMeasureSpec,heightMeasureSpec);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (i == childCount - 1) {
child.layout(-1 * getMeasuredWidth(), 0,
-1 * getMeasuredWidth() + child.getMeasuredWidth(),
child.getMeasuredHeight());
} else {
child.layout(i * getMeasuredWidth(), 0,
i * getMeasuredWidth() + child.getMeasuredWidth(),
child.getMeasuredHeight());
}
}
}
private float startX;
private float lastX;
private int offX;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
startX = ev.getX();
lastX = startX;
break;
case MotionEvent.ACTION_MOVE:
offX = (int) Math.abs(ev.getX() - startX);
if (offX > 2){
return true;
}
lastX = ev.getX();
break;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_MOVE:
offX = (int) (event.getX() - startX);
scrollBy(-(int) (event.getX() - lastX), 0);
lastX = event.getX();
break;
case MotionEvent.ACTION_UP:
int scrollX;
if (getScrollX()>0){
scrollX = (offX > 0)?getWidth()/4:getWidth()*3/4;
}else {
scrollX = ((offX > 0)?getWidth()*3/4:getWidth()/4) * -1;
}
int targetIndex = (getScrollX() + scrollX) / getWidth();
int dx = targetIndex * getWidth() - getScrollX();
mScroller.startScroll(getScrollX(), 0, dx, 0);
invalidate();
checkChildLayout(targetIndex);
break;
}
return super.onTouchEvent(event);
}
private void checkChildLayout(int targetIndex){
int childCount = getChildCount();
int curIndex = (targetIndex+childCount*1000)%childCount;
View childLeft;
if (curIndex == 0) {
childLeft = getChildAt(childCount - 1);
}else {
childLeft = getChildAt(curIndex - 1);
}
childLeft.layout((targetIndex-1)*childLeft.getWidth()
,0,targetIndex*childLeft.getWidth(),childLeft.getHeight());
View childRight;
if (curIndex == childCount-1) {
childRight = getChildAt(0);
}else {
childRight = getChildAt(curIndex + 1);
}
childRight.layout((targetIndex+1)*childRight.getWidth()
,0,(targetIndex+2)*childRight.getWidth(),childRight.getHeight());
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()){
scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
invalidate();
}
}
}
布局文件:
<com.rong.launchmode.view.BannerLoopLayout
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="100dp">
<Button
android:textSize="30sp"
android:text="btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:textSize="25sp"
android:text="btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:textSize="20sp"
android:text="btn3"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:textSize="15sp"
android:text="btn4"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</com.rong.launchmode.view.BannerLoopLayout>
有点赶时间。。还没来得及注释,先发表再说。