在viewgroup执行:
public void snapToScreen(int whichScreen) {
whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));
boolean changingScreens = whichScreen != mCurrentScreen;
mNextScreen = whichScreen;
int mScrollX = this.getScrollX();
final int newX = whichScreen * getWidth();
final int delta = newX - mScrollX;
System.out.println("====snapToScreen delta="+delta);
<strong>mScroller.startScroll(mScrollX, 0, delta, 0, Math.abs(delta) * 2); //这个含义是从x坐标mScrollX的位置滑动delta距离</strong>
//invalidate非常重要,不然你移动一点页面不能回复原状
invalidate();
}
@Override
public void computeScroll() {
if (<strong>mScroller.computeScrollOffset()</strong>) {
<strong>scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();</strong>
} else if (mNextScreen != -1) { <strong>//这个是滑动完成后执行的,这个时候必须set当前的view</strong>
setCurrentScreen(Math.max(0,
Math.min(mNextScreen, getChildCount() - 1)));
mNextScreen = -1;
}
}
如果这个viewgroup一次性加载太多子控件,会造成性能的很大影响,为了解决这个问题,我们应该在显示当前的控件,其他的应该visible置为空
这样来处理:
void setCurrentScreen(int index) {
mCurrentScreen = index;
resetVisibilityForChildren();
}
private void resetVisibilityForChildren() {
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
if (Math.abs(mCurrentScreen - i) <= 0) {
child.setVisibility(View.VISIBLE);
} else {
child.setVisibility(View.INVISIBLE);
}
}
}
为了滑动的时候能显示下一页,我们必须重写dispatchDraw
@Override
protected void dispatchDraw(Canvas canvas) {
int childCount = getChildCount();
if (childCount == 0) {
return;
}
boolean restore = false;
int restoreCount = 0;
final long drawingTime = getDrawingTime();
final float scrollPos = (float) getScrollX() / getWidth();
final int leftScreen = (int) scrollPos;
final int rightScreen = leftScreen + 1;
if (leftScreen >= 0 && leftScreen < childCount) {
<strong>drawChild(canvas, getChildAt(leftScreen), drawingTime); //这个会使leftScreen由gone的状态显示出来</strong>
}
if (rightScreen < getChildCount()) {
drawChild(canvas, getChildAt(rightScreen), drawingTime);
}
if (restore) {
canvas.restoreToCount(restoreCount);
}
}
下面来说如何在这个界面上加入dot,来表示当前滑动哪个界面:
在myGroup类里加入:
public void setmListener(OnViewChangedListener mListener) {
this.mListener = mListener;
}
public interface OnViewChangedListener {
/**
* When view changed.
* @param viewIndex index.
*/
void onViewChanged(int viewIndex);
}
private static final int DEFAULT_POINT_MARGIN = 5;
/**
* 更新点点的状态,包括总数和当前位置。
* @param dotsLayout 用来放置点点的layout.
* @param total 总数。
* @param current 当前位置。
* @param state Bundle,参数扩展,可以为null.
*/
public static void updateDots(ViewGroup dotsLayout, int total, int current, Bundle state) {
if (total < 0) {
total = 0;
}
int lastIndex = -1;
Object tag = dotsLayout.getTag(R.id.dots_current);
if (tag != null) {
lastIndex = (Integer) tag;
}
int margin = DEFAULT_POINT_MARGIN;
if (state != null) {
margin = state.getInt(KEY_POINT_MARGIN, margin);
}
int childrenNum = dotsLayout.getChildCount();
for (int i = childrenNum; i < total; i++) {
ImageView pointView = new ImageView(dotsLayout.getContext());
pointView.setImageResource(R.drawable.dot);
dotsLayout.addView(pointView);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) pointView.getLayoutParams();
params.leftMargin = margin;
params.rightMargin = margin;
}
for (int i = childrenNum - 1; i >= total; i--) {
dotsLayout.removeViewAt(i);
}
if (current == lastIndex) {
return;
}
if (lastIndex >= 0 && lastIndex < total) {
ImageView pointView = (ImageView) dotsLayout.getChildAt(lastIndex);
pointView.setImageResource(R.drawable.dot);
}
if (current >= 0 && current < total) {
ImageView pointView = (ImageView) dotsLayout.getChildAt(current);
pointView.setImageResource(R.drawable.dot_current);
}
dotsLayout.setTag(R.id.dots_current, current);
}
public interface WorkspaceSnapListener {
void onSnapToScreen(MyGroup workspace, int whichScreen);
}
public void setSnapListener(WorkspaceSnapListener listener) {
snapListener = listener;
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
} else if (mNextScreen != -1) {
<strong>if (mListener != null) {
mListener.onViewChanged(mCurrentScreen);
}</strong>
}
}
public void snapToScreen(int whichScreen) {
<strong>if (snapListener != null) {
snapListener.onSnapToScreen(this, whichScreen);
}</strong>
}
在MainActivity的layout中加入:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/MainRoot"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<com.ringcentral.android.utils.ui.widget.MyGroup
android:background="@drawable/help_background_selector"
android:id="@+id/workspace"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
<LinearLayout android:id="@+id/dots_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="28dip"
android:layout_gravity="bottom|center_horizontal"
android:orientation="horizontal"/>
</FrameLayout>
点的画法:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<size android:width="6dip" android:height="6dip"/>
<solid android:color="#7fffffff"/>
</shape>
oncreate:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
final ViewGroup dotsLayout = (ViewGroup) findViewById(R.id.dots_layout);
final int[] images = new int[]{R.drawable.help_01,R.drawable.help_02,R.drawable.help_03};
final MyGroup myGroup = (MyGroup) findViewById(R.id.workspace);
final Bundle dotsState = new Bundle();
int margin = getResources().getDimensionPixelSize(R.dimen.workspace_dot_margin);
dotsState.putInt(MyGroup.KEY_POINT_MARGIN, margin);
MyGroup.updateDots(dotsLayout, images.length, 0, dotsState);
for (int i = 0; i < 3; i++) {
final View item = getLayoutInflater().inflate(
R.layout.introduction_item_test, null);
myGroup.addView(item);
final ImageView imageView = (ImageView) item
.findViewById(R.id.introduction_image_view);
try {
imageView.setImageResource(images[i]);
} catch (OutOfMemoryError e) {
}
}
myGroup.setmListener(new OnViewChangedListener() {
@Override
public void onViewChanged(int viewIndex) {
myGroup.updateDots(dotsLayout, images.length, viewIndex, dotsState);
}
});
myGroup.setSnapListener(new WorkspaceSnapListener() {
@Override
public void onSnapToScreen(MyGroup workspace, int whichScreen) {
myGroup.updateDots(dotsLayout, images.length, whichScreen, dotsState);
}
});
}
效果图: