package yanbin.switchLayout;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;
public class SwitchLayout extends ViewGroup {
private int mCurScreen ;
private static final int SNAP_VELOCITY = 600;//瞬间速度
private Scroller scroller ;//滚动控制器
private VelocityTracker tracker;//拖动手势的速率跟踪器
private float mLastMotionX;
private Context context;
private OnViewChangeListener onViewChangeListener;//改变imageView
public SwitchLayout(Context context) {
super(context);
this.context = context;
init(context);
}
public SwitchLayout(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init(context);
}
public SwitchLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
init(context);
}
//初始化控件
private void init(Context context) {
mCurScreen = 0;
scroller = new Scroller(context);
}
/**
* 必须要调用的方法
* 目的:当前的view在给自己的子控件指派大小和位置必须要调用的方法
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if(changed){
int childLeft = 0;
int childCount = getChildCount();
for(int i = 0;i < childCount;i++){
View childView = getChildAt(i);
if(childView.getVisibility() != View.GONE){
int childWidth = childView.getMeasuredWidth();
//子控件被填充在父控件中(第二个阶段,第一个阶段为onMeasure,即计算)
childView.layout(childLeft, 0, childLeft + childWidth, childView.getMeasuredHeight());
childLeft += childWidth;//改变左边的起始位置
}
}
}
}
/**
* 计算控件的宽和高
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int count = getChildCount();
for(int i = 0;i < count;i++){
getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
}
//滚到到哪一屏,通过width来控制
scrollTo(mCurScreen*width, 0);
}
public void setOnViewChangeListener(OnViewChangeListener changeListener){
this.onViewChangeListener = changeListener;
}
/**
* 设置自定义控件中的哪个子控件展示在当前屏幕中
* @param pos
*/
public void snapToScreen(int pos) {
System.out.println("当前的位置:" + pos);
if(getScrollX() != (pos * getWidth())){
int destina = pos * getWidth() - getScrollX();//要移动的距离
//开始滚动,从起始地开始,后两个参数为滚动的距离。用坐标来表示
scroller.startScroll(getScrollX(), 0, destina, 0);
mCurScreen = pos;
invalidate();//在主线程中调用这个方法来重绘view,必须在主线程中调用
//改变imageView的显示(根据guide_round.xml可以看出,当状态enabled的
//的时候,用黑点表示,也就是不是当前选中。)
System.out.println("ImageView改变监听" + onViewChangeListener);
if(onViewChangeListener != null){
onViewChangeListener.onViewChange(pos);
}
}
}
@Override
public void computeScroll() {
if(scroller.computeScrollOffset()){
scrollTo(scroller.getCurrX(), scroller.getCurrY());
postInvalidate();
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//Return the kind of action being performed --
//one of either ACTION_DOWN, ACTION_MOVE, ACTION_UP, or ACTION_CANCEL.
int action = event.getAction();
/**
* 屏幕上的每一次触摸都会被onTouchEvent捕获到,可以从event得到其x,y的值。
* 特别注意:并且得到的是你当前的触点的x,y坐标的值,也就是说,往左划动的话,
* 你的x的值是变小的。
*/
float x = event.getX();
System.out.println("onTouchEvent--" + x);
switch (action) {
//按下
case MotionEvent.ACTION_DOWN:
if(tracker == null){
tracker = VelocityTracker.obtain();
tracker.addMovement(event);
}
if(!scroller.isFinished())
//防止scroller滚动到最终的x和y的位置
scroller.abortAnimation();
mLastMotionX = x;
System.out.println("mLastMotionX--" + mLastMotionX);
break;
//移动
case MotionEvent.ACTION_MOVE:
int deltalX = (int)(mLastMotionX - x);//开始位置的触点与当前位置的差值
if(canMove(deltalX)){
if(tracker != null){
tracker.addMovement(event);
}
mLastMotionX = x;
//控件滚动的位置
scrollBy(deltalX, 0);
}
break;
//松手
/**
* 往左滑动,因为x是在减小,所以横向速率是负值。
* 往右滑动,因为x是在增大,所以横向速率是正值。
*/
case MotionEvent.ACTION_UP:
int velocityX = 0;
if(tracker != null){
tracker.addMovement(event);
tracker.computeCurrentVelocity(1000);//计算1s滚动的速度
System.out.println("tracker -- "+tracker);
velocityX = (int) tracker.getXVelocity();//得到最终的横向速率
System.out.println("横向速率--" + velocityX);
System.out.println("mCurScreen--" + mCurScreen);
}
//不是第一屏,且是往右滑动
if(velocityX > SNAP_VELOCITY && mCurScreen >0)
snapToScreen(mCurScreen - 1);
//往左滑动,且不是最后一个
else if(velocityX < -SNAP_VELOCITY && mCurScreen < (getChildCount() -1)){
snapToScreen(mCurScreen + 1);
}
//往左滑动,且是最后一个,这里直接finish掉activity
else if(velocityX == 0 && mCurScreen == (getChildCount() -1)){
System.out.println("-----------");
Activity activity = (Activity) context;
Intent intent = new Intent();
intent.setClass(context, yanbin.switchDemo.OtherActivity.class);
context.startActivity(intent);
activity.finish();
}
//速率不够快是,另一种跳转方式
else{
snapToDestination();
}
if(tracker != null){
tracker.recycle();
tracker = null;
}
break;
}
return true;
}
//滑动到下一屏
private void snapToDestination() {
int screenWidth = getWidth();
//最终滑动的位置超过1\2时,才滚动,否则,destScreen得到将是当前屏的值。
int destScreen = (getScrollX() + screenWidth/2)/screenWidth;
snapToScreen(destScreen);
}
//可滚动的条件
private boolean canMove(int deltalX) {
//getScrollX(),得到触点view在左边的x轴的坐标,它的值是从第一张图到最后一张图算的,
//也就是说:getScrollX()得到的值是 将整个图展开,然后相对的那个x坐标。
if(getScrollX() <= 0 && deltalX <0){//显示的是第一张图,并且是往右划
return false;
}
//显示的是最后一张图并且是往左划
if(getScrollX() >= (getChildCount()-1)*getWidth() && deltalX > 0){
return false;
}
return true;
}
}
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
switchTest.rar (54个子文件)
switchTest
bin
classes.dex 10KB
res
drawable-ldpi
icon.png 2KB
drawable-hdpi
icon.png 4KB
drawable
a.png 366KB
c.png 218KB
e.png 317KB
guide_dot_black.png 192B
b.png 282KB
d.png 90KB
guide_dot_white.png 192B
drawable-mdpi
icon.png 2KB
switchTest.apk 1.26MB
jarlist.cache 119B
classes
yanbin
switchDemo
BuildConfig.class 343B
OtherActivity.class 518B
R$layout.class 420B
SwitchActivity$MOnViewChangeListener.class 1KB
R$id.class 426B
R$drawable.class 635B
R$attr.class 337B
R.class 524B
SwitchActivity$MOnClickListener.class 2KB
SwitchActivity.class 2KB
R$string.class 424B
switchLayout
OnViewChangeListener.class 171B
SwitchLayout.class 6KB
resources.ap_ 1.26MB
AndroidManifest.xml 806B
res
drawable-ldpi
icon.png 2KB
drawable-hdpi
icon.png 4KB
drawable
a.png 378KB
c.png 229KB
e.png 327KB
guide_dot_black.png 192B
b.png 293KB
d.png 91KB
guide_dot_white.png 192B
guide_round.xml 301B
values
strings.xml 186B
drawable-mdpi
icon.png 3KB
layout
other.xml 394B
main.xml 3KB
assets
gen
yanbin
switchDemo
BuildConfig.java 159B
R.java 1KB
proguard.cfg 1KB
.settings
org.eclipse.core.resources.prefs 55B
src
yanbin
switchDemo
OtherActivity.java 299B
SwitchActivity.java 3KB
switchLayout
SwitchLayout.java 7KB
OnViewChangeListener.java 114B
.project 846B
.classpath 380B
project.properties 562B
AndroidManifest.xml 806B
共 54 条
- 1
资源评论
- qq_333086322015-12-17这个Demo挺好用的。
suzhtlm
- 粉丝: 2
- 资源: 14
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功