如果写一个android桌面滑动切换屏幕的控件(二)
在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); } }); }
效果图:
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。