1.OnViewChangeListener 类
public interface OnViewChangeListener {
public void OnViewChange(int view);
}
2.NavigitionActivity 类
package com.zqs.navigation.activity;
import com.zqs.navigation.listener.OnViewChangeListener;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
public class NavigitionActivity extends Activity implements OnViewChangeListener {
private NavigationLayout navigationLayout ;
private Button start_btn;
private PassBroadCast passBroadCast;
private int count;
private ImageView[] imgs;
private LinearLayout pointLLayout;
private int currentItem;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.navigation);
initBroadCastReceiver();
initView();
}
private void initView() {
navigationLayout = (NavigationLayout) findViewById(R.id.navigationLayout);
pointLLayout = (LinearLayout) findViewById(R.id.llayout);
start_btn = (Button) findViewById(R.id.start_btn);
start_btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setClass(NavigitionActivity.this, MainActivity.class);
NavigitionActivity.this.startActivity(intent);
NavigitionActivity.this.finish();
}
});
count = navigationLayout.getChildCount();
imgs = new ImageView[count];
for (int i = 0; i < count; i++) {
imgs[i] = (ImageView) pointLLayout.getChildAt(i);
imgs[i].setEnabled(true);
imgs[i].setTag(i);
}
currentItem = 0;
imgs[currentItem].setEnabled(false);
//方法二 注册监听器
navigationLayout.SetOnViewChangeListener(this);
}
private void initBroadCastReceiver() {
//注册该广播
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("passByValue");
passBroadCast = new PassBroadCast();
registerReceiver(passBroadCast, intentFilter);
}
private class PassBroadCast extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
int cunrrentPage = intent.getIntExtra("CurScreen",0);
setcurrentPoint(cunrrentPage);
}
}
private void setcurrentPoint(int position) {
if (position < 0 || position > count - 1 || currentItem == position) {
return;
}
imgs[currentItem].setEnabled(true);
imgs[position].setEnabled(false);
currentItem = position;
}
@Override
public void OnViewChange(int position) {
setcurrentPoint(position);
}
}
3.NavigationLayout 类
package com.zqs.navigation.activity;
import com.zqs.navigation.listener.OnViewChangeListener;
import android.content.Context;
import android.content.Intent;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;
public class NavigationLayout extends ViewGroup{
private static final String TAG = "ScrollLayout";
private VelocityTracker mVelocityTracker;
private static final int SNAP_VELOCITY = 1500;
private Scroller mScroller;
private int mCurScreen;
private int mDefaultScreen = 0;
private float mLastMotionX;
private Context context;
private OnViewChangeListener mOnViewChangeListener;
public NavigationLayout(Context context) {
super(context);
// TODO Auto-generated constructor stub
init(context);
}
public NavigationLayout(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init(context);
}
public NavigationLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
init(context);
}
private void init(Context context)
{
mCurScreen = mDefaultScreen;
this.context = context;
mScroller = new Scroller(context);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
if (changed) {
int childLeft = 0;
final int childCount = getChildCount();
for (int i=0; i<childCount; i++) {
final View childView = getChildAt(i);
if (childView.getVisibility() != View.GONE) {
final int childWidth = childView.getMeasuredWidth();
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);
final int width = MeasureSpec.getSize(widthMeasureSpec);
@SuppressWarnings("unused")
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
final int count = getChildCount();
for (int i = 0; i < count; i++) {
getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
}
scrollTo(mCurScreen * width, 0);
}
//我们是缓慢移动的,因此需要根据偏移值判断目标屏是哪个?
public void snapToDestination() {
final int screenWidth = getWidth();
//判断是否超过下一屏的中间位置,如果达到就抵达下一屏,否则保持在原屏幕
//直接使用这个公式判断是哪一个屏幕 前后或者自己
//判断是否超过下一屏的中间位置,如果达到就抵达下一屏,否则保持在原屏幕
// 这样的一个简单公式意思是:假设当前滑屏偏移值即 scrollCurX 加上每个屏幕一半的宽度,除以每个屏幕的宽度就是
// 我们目标屏所在位置了。 假如每个屏幕宽度为320dip, 我们滑到了500dip处,很显然我们应该到达第二屏
final int destScreen = (getScrollX()+ screenWidth/2)/screenWidth;
snapToScreen(destScreen);
}
public void snapToScreen(int whichScreen) {
//简单的移到目标屏幕,可能是当前屏或者下一屏幕
//直接跳转过去,不太友好
//scrollTo(mLastScreen * MultiScreenActivity.screenWidth, 0);
//为了友好性,我们在增加一个动画效果
//需要再次滑动的距离 屏或者下一屏幕的继续滑动距离
// //防止屏幕越界,即超过屏幕数
whichScreen = Math.max(0, Math.min(whichScreen, getChildCount()-1));
if (getScrollX() != (whichScreen*getWidth())) {
//为了达到下一屏幕或者当前屏幕,我们需要继续滑动的距离.根据dx值,可能想左滑动,也可能像又滑动
final int delta = whichScreen*getWidth()-getScrollX();
mScroller.startScroll(getScrollX(), 0,
delta, 0, Math.abs(delta)*2);
mCurScreen = whichScreen;
invalidate(); //由于触摸事件不会重新绘制View,所以此时需要手动刷新View 否则没效果
//方法一:创建广播监听 传当前启动页 给NavigationActivity改变指引图标
// Intent intent = new Intent();
// intent.setAction("passByValue");
// intent.putExtra("CurScreen", mCurScreen);
// context.sendBroadcast(intent);
//方法二:创建监听类监听改变, NavigationActivity实现监听器具体功能
if (mOnViewChangeListener != null)
{
mOnViewChangeListener.OnViewChange(mCurScreen);
}
}
}
//调用ondraw() 调用此方法
@Override
public void computeScroll() {
// TODO Auto-generated method stub
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
final int action = event.getAction();
final float x = event.getX();
@SuppressWarnings("unused")
final float y = event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
mVelocityTracker.addMovement(event);
}
if (!mScroller.isFinished()){
mScroller.abortAnimation();
}
mLastMotionX = x;
break;
case MotionEvent.ACTION_MOVE:
int deltaX = (int)(mLastMotionX - x);
if (IsCanMove(deltaX))
{
if (mVelocityTracker != null)
{
mVelocityTracker.addMovement(event);
}
mLastMotionX = x;
scrollBy(deltaX, 0);
}
break;
case MotionEvent.ACTION_UP:
int velocityX = 0;
if (mVelocityTracker != null)
{
mVelocityTracker.addMovement(event);
mVelocityTracker.computeCurrentVelocity(1000);
//计算速率
velocityX = (int) mVelocityTracker.getXVelocity();
}
//滑动速率达到了一个标准(快速向右滑屏,返回上一个屏幕) 马上进行切屏处理
if (velocityX > SNAP_VELOCITY && mCurScreen > 0) {
// Fling enough to move left
Log.e(TAG, "snap left");
snapToScreen(mCurScreen - 1);
}
//快速向左滑屏,返回下一个屏幕)
else if (velocityX < -SNAP_VELOCITY
&& mCurScreen < getChildCount() - 1) {
// Fling enough to move right
Log.e(TAG, "snap right");
snapToScreen(mCurScreen + 1);
}
//以上为快速移动的 ,强制切换屏幕
else {
//我们是缓慢移动的,因此先判断是保留在本屏幕还是到下一屏幕
snapToDestination();
}
//回收VelocityTracker对象
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
// mTouchState = TOUCH_STATE_REST;
break;
}
return true;
}
private boolean IsCanMove(int deltaX)
{
//简而言之,getScrollX() 就是当前view的左上角相对于母视图的左上角的X轴偏移量。(nice!)
if (getScrollX() <= 0 && deltaX < 0 )
{
return false;
}
//getWidth Return the width of the your view.
if (getScrollX() >= (getChildCount() - 1) * getWidth() && deltaX > 0)
{
return false;
}
return true;
}
public void SetOnViewChangeListener(OnViewChangeListener listener)
{
mOnViewChangeListener = listener;
}
}
总结:
自定义设置监听器方法:
(1)对清对象,被监听对象,监听器,实现监听器对象
监听器:public interface OnViewChangeListener {}
实现监听器对象:public class NavigitionActivity extends Activity implements OnViewChangeListener {}
被监听对象:public class NavigationLayout extends ViewGroup{}
(2) 实现监听器对象 NavigitionActivity :实现方法:
@Override
public void OnViewChange(int position) {
setcurrentPoint(position);
}
(3) 被监听对象 NavigationLayout : 设置监听器
public void SetOnViewChangeListener(OnViewChangeListener listener)
{
mOnViewChangeListener = listener;
}
(4) 关联监听器 与被监听对象
//方法二 注册监听器
navigationLayout.SetOnViewChangeListener(this);
(5)被监听对象 改变之后 调用监听器
if (mOnViewChangeListener != null)
{
mOnViewChangeListener.OnViewChange(mCurScreen);
}
Demo 地址:
http://download.csdn.net/detail/zqs62761130/8228427
(1)对清对象,被监听对象,监听器,实现监听器对象
监听器:public interface OnViewChangeListener {}
实现监听器对象:public class NavigitionActivity extends Activity implements OnViewChangeListener {}
被监听对象:public class NavigationLayout extends ViewGroup{}
(2) 实现监听器对象 NavigitionActivity :实现方法:
@Override
public void OnViewChange(int position) {
setcurrentPoint(position);
}
(3) 被监听对象 NavigationLayout : 设置监听器
public void SetOnViewChangeListener(OnViewChangeListener listener)
{
mOnViewChangeListener = listener;
}
(4) 关联监听器 与被监听对象
//方法二 注册监听器
navigationLayout.SetOnViewChangeListener(this);
(5)被监听对象 改变之后 调用监听器
if (mOnViewChangeListener != null)
{
mOnViewChangeListener.OnViewChange(mCurScreen);
}