Android仿微信的开机滑动界面
首先谢谢提供这个代码的同学。之前曾写了一篇随笔,是介绍如何判断应用程序是否是第一次进入使用,结合着这个滑动界面,当用户第一次使用时候就跳转到那个滑动界面,判断不是第一次使用,就直接跳转到主界面。
首先用代码自定义一个布局 MyScrollLayout
View Code
package com.chen.weixin.test; import android.content.Context; 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 MyScrollLayout extends ViewGroup{ private static final String TAG = "ScrollLayout"; private VelocityTracker mVelocityTracker; // 用于判断甩动手势 private static final int SNAP_VELOCITY = 600; private Scroller mScroller; // 滑动控制�? private int mCurScreen; private int mDefaultScreen = 0; private float mLastMotionX; // private int mTouchSlop; // private static final int TOUCH_STATE_REST = 0; // private static final int TOUCH_STATE_SCROLLING = 1; // private int mTouchState = TOUCH_STATE_REST; private OnViewChangeListener mOnViewChangeListener; public MyScrollLayout(Context context) { super(context); // TODO Auto-generated constructor stub init(context); } public MyScrollLayout(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub init(context); } public MyScrollLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // TODO Auto-generated constructor stub init(context); } private void init(Context context) { mCurScreen = mDefaultScreen; // mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); 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); 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(); final int destScreen = (getScrollX()+ screenWidth/2)/screenWidth; snapToScreen(destScreen); } public void snapToScreen(int whichScreen) { // get the valid layout page whichScreen = Math.max(0, Math.min(whichScreen, getChildCount()-1)); if (getScrollX() != (whichScreen*getWidth())) { final int delta = whichScreen*getWidth()-getScrollX(); mScroller.startScroll(getScrollX(), 0, delta, 0, Math.abs(delta)*2); mCurScreen = whichScreen; invalidate(); // Redraw the layout if (mOnViewChangeListener != null) { mOnViewChangeListener.OnViewChange(mCurScreen); } } } @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(); final float y = event.getY(); switch (action) { case MotionEvent.ACTION_DOWN: Log.i("", "onTouchEvent 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(); } if (mVelocityTracker != null) { mVelocityTracker.recycle(); mVelocityTracker = null; } // mTouchState = TOUCH_STATE_REST; break; } return true; } // // public boolean onInterceptTouchEvent(MotionEvent ev) { // // TODO Auto-generated method stub // final int action = ev.getAction(); // if ((action == MotionEvent.ACTION_MOVE) // && (mTouchState != TOUCH_STATE_REST)) { // Log.i("", "onInterceptTouchEvent return true"); // return true; // } // final float x = ev.getX(); // final float y = ev.getY(); // switch (action) { // case MotionEvent.ACTION_MOVE: // final int xDiff = (int) Math.abs(mLastMotionX - x); // if (xDiff > mTouchSlop) { // mTouchState = TOUCH_STATE_SCROLLING; // } // break; // // case MotionEvent.ACTION_DOWN: // mLastMotionX = x; // // mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST // : TOUCH_STATE_SCROLLING; // break; // // case MotionEvent.ACTION_CANCEL: // case MotionEvent.ACTION_UP: // mTouchState = TOUCH_STATE_REST; // break; // } // // if (mTouchState != TOUCH_STATE_REST) // { // Log.i("", "mTouchState != TOUCH_STATE_REST return true"); // } // // // return mTouchState != TOUCH_STATE_REST; // } private boolean IsCanMove(int deltaX) { if (getScrollX() <= 0 && deltaX < 0 ) { return false; } if (getScrollX() >= (getChildCount() - 1) * getWidth() && deltaX > 0) { return false; } return true; } public void SetOnViewChangeListener(OnViewChangeListener listener) { mOnViewChangeListener = listener; } }
写一个监听的接口:
public interface OnViewChangeListener { public void OnViewChange(int view); }
然后在主类中实现这个接口:
View Code
1 public class TestWeiXinWhatsNewActivity extends Activity implements OnViewChangeListener{ 2 3 private MyScrollLayout mScrollLayout; 4 private ImageView[] imgs; 5 private int count; 6 private int currentItem; 7 private Button startBtn; 8 private RelativeLayout mainRLayout; 9 private LinearLayout pointLLayout; 10 private LinearLayout leftLayout; 11 private LinearLayout rightLayout; 12 private LinearLayout animLayout; 13 @Override 14 public void onCreate(Bundle savedInstanceState) { 15 super.onCreate(savedInstanceState); 16 setContentView(R.layout.main); 17 initView(); 18 } 19 20 private void initView() { 21 mScrollLayout = (MyScrollLayout) findViewById(R.id.ScrollLayout); 22 pointLLayout = (LinearLayout) findViewById(R.id.llayout); 23 mainRLayout = (RelativeLayout) findViewById(R.id.mainRLayout); 24 startBtn = (Button) findViewById(R.id.startBtn); 25 startBtn.setOnClickListener(onClick); 26 animLayout = (LinearLayout) findViewById(R.id.animLayout); 27 leftLayout = (LinearLayout) findViewById(R.id.leftLayout); 28 rightLayout = (LinearLayout) findViewById(R.id.rightLayout); 29 count = mScrollLayout.getChildCount(); 30 imgs = new ImageView[count]; 31 for(int i = 0; i< count;i++) { 32 imgs[i] = (ImageView) pointLLayout.getChildAt(i); 33 imgs[i].setEnabled(true); 34 imgs[i].setTag(i); 35 } 36 currentItem = 0; 37 imgs[currentItem].setEnabled(false); 38 mScrollLayout.SetOnViewChangeListener(this); 39 } 40 41 private View.OnClickListener onClick = new View.OnClickListener() { 42 @Override 43 public void onClick(View v) { 44 switch (v.getId()) { 45 case R.id.startBtn: 46 mScrollLayout.setVisibility(View.GONE); 47 pointLLayout.setVisibility(View.GONE); 48 animLayout.setVisibility(View.VISIBLE); 49 mainRLayout.setBackgroundResource(R.drawable.whatsnew_bg); 50 Animation leftOutAnimation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.translate_left); 51 Animation rightOutAnimation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.translate_right); 52 // Animation leftOutAnimation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.fadedout_to_left_down); 53 // Animation rightOutAnimation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.fadedout_to_right_down); 54 leftLayout.setAnimation(leftOutAnimation); 55 rightLayout.setAnimation(rightOutAnimation); 56 leftOutAnimation.setAnimationListener(new AnimationListener() { 57 @Override 58 public void onAnimationStart(Animation animation) { 59 mainRLayout.setBackgroundColor(R.color.bgColor); 60 } 61 @Override 62 public void onAnimationRepeat(Animation animation) { 63 } 64 @Override 65 public void onAnimationEnd(Animation animation) { 66 leftLayout.setVisibility(View.GONE); 67 rightLayout.setVisibility(View.GONE); 68 Intent intent = new Intent(TestWeiXinWhatsNewActivity.this,OtherActivity.class); 69 TestWeiXinWhatsNewActivity.this.startActivity(intent); 70 TestWeiXinWhatsNewActivity.this.finish(); 71 overridePendingTransition(R.anim.zoom_out_enter, R.anim.zoom_out_exit); 72 } 73 }); 74 break; 75 } 76 } 77 }; 78 79 @Override 80 public void OnViewChange(int position) { 81 setcurrentPoint(position); 82 } 83 84 private void setcurrentPoint(int position) { 85 if(position < 0 || position > count -1 || currentItem == position) { 86 return; 87 } 88 imgs[currentItem].setEnabled(true); 89 imgs[position].setEnabled(false); 90 currentItem = position; 91 } 92 }
下面就是实现布局文件还有动画的xml文件了:
用到的动画xml文件 translate_left.xml:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <set android:fillAfter="false" 3 xmlns:android="http://schemas.android.com/apk/res/android"> 4 <translate android:duration="2000" android:fromXDelta="0.0" android:toXDelta="-50.0%p" android:fromYDelta="0.0" android:toYDelta="0.0" /> 5 </set>
translate_right.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <set xmlns:android="http://schemas.android.com/apk/res/android" 3 android:fillAfter="false" > 4 <translate 5 android:duration="2000" 6 android:fromXDelta="0.0" 7 android:fromYDelta="0.0" 8 android:toXDelta="50.0%p" 9 android:toYDelta="0.0" /> 10 </set>
zoom_out_enter.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <set xmlns:android="http://schemas.android.com/apk/res/android" 3 android:interpolator="@android:anim/overshoot_interpolator" > 4 <scale 5 android:duration="@android:integer/config_shortAnimTime" 6 android:fromXScale="0.7" 7 android:fromYScale="0.7" 8 android:pivotX="50.0%" 9 android:pivotY="50.0%" 10 android:toXScale="1.0" 11 android:toYScale="1.0" /> 12 </set>
zoom_out_exit.xml
<?xml version="1.0" encoding="UTF-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_interpolator" > <scale android:duration="@android:integer/config_shortAnimTime" android:fromXScale="1.0" android:fromYScale="1.0" android:pivotX="50.0%" android:pivotY="50.0%" android:toXScale="0.8" android:toYScale="0.8" /> <alpha android:duration="@android:integer/config_shortAnimTime" android:fromAlpha="1.0" android:toAlpha="0.0" /> </set>
界面main.xml
View Code
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="fill_parent" 4 android:layout_height="fill_parent" 5 android:id="@+id/mainRLayout" 6 android:background="#000000" 7 > 8 <com.chen.weixin.test.MyScrollLayout 9 xmlns:android="http://schemas.android.com/apk/res/android" 10 android:id="@+id/ScrollLayout" 11 android:layout_width="fill_parent" 12 android:layout_height="fill_parent" 13 android:visibility="visible" 14 > 15 <RelativeLayout android:background="@drawable/w01" 16 android:layout_width="fill_parent" 17 android:layout_height="fill_parent" 18 > 19 <TextView 20 android:layout_width="wrap_content" 21 android:layout_height="wrap_content" 22 android:layout_alignParentBottom="true" 23 android:layout_centerHorizontal="true" 24 android:layout_marginBottom="89dp" 25 android:text="微信,不只是个聊天工具" 26 android:textColor="@color/TextColor" 27 android:textSize="18sp" /> 28 </RelativeLayout> 29 <RelativeLayout android:background="@drawable/w02" 30 android:layout_width="fill_parent" 31 android:layout_height="fill_parent" 32 > 33 <TextView 34 android:id="@+id/t1" 35 android:layout_width="wrap_content" 36 android:layout_height="wrap_content" 37 android:layout_alignParentTop="true" 38 android:layout_centerHorizontal="true" 39 android:layout_marginTop="96dp" 40 android:text="第一次,你可以使用透明背景的动画表情,来表达你此刻的心情" 41 android:gravity="center_horizontal" 42 android:textColor="@color/TextColor" 43 android:textSize="18sp" /> 44 </RelativeLayout> 45 <RelativeLayout android:background="@drawable/w03" 46 android:layout_width="fill_parent" 47 android:layout_height="fill_parent" 48 /> 49 <RelativeLayout android:background="@drawable/w04" 50 android:layout_width="fill_parent" 51 android:layout_height="fill_parent" 52 /> 53 <RelativeLayout android:background="@drawable/w05" 54 android:layout_width="fill_parent" 55 android:layout_height="fill_parent" 56 /> 57 <RelativeLayout android:background="@drawable/w06" 58 android:layout_width="fill_parent" 59 android:layout_height="fill_parent" 60 /> 61 <RelativeLayout android:background="@drawable/w07" 62 android:layout_width="fill_parent" 63 android:layout_height="fill_parent" 64 /> 65 <RelativeLayout android:background="@drawable/w08" 66 android:layout_width="fill_parent" 67 android:layout_height="fill_parent" 68 /> 69 <RelativeLayout android:background="@drawable/w01" 70 android:layout_width="fill_parent" 71 android:layout_height="fill_parent"> 72 <Button 73 android:id="@+id/startBtn" 74 android:layout_width="wrap_content" 75 android:layout_height="wrap_content" 76 android:layout_alignParentBottom="true" 77 android:layout_centerHorizontal="true" 78 android:layout_marginBottom="98dp" 79 android:text="开始我的微信生活" 80 android:textSize="18sp" 81 android:textColor="@color/TextColor" 82 android:background="@drawable/button_bg" 83 android:layout_marginLeft="8dp" 84 android:layout_marginRight="8dp" 85 android:layout_gravity="center_vertical" 86 /> 87 </RelativeLayout> 88 </com.chen.weixin.test.MyScrollLayout> 89 <LinearLayout 90 android:orientation="horizontal" 91 android:id="@+id/llayout" 92 android:layout_width="wrap_content" 93 android:layout_height="wrap_content" 94 android:layout_marginBottom="24.0dip" 95 android:layout_alignParentBottom="true" 96 android:layout_centerHorizontal="true" 97 android:visibility="visible"> 98 99 <ImageView android:clickable="true" android:padding="5.0dip" android:layout_gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/page_indicator_bg" /> 100 <ImageView android:clickable="true" android:padding="5.0dip" android:layout_gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/page_indicator_bg" /> 101 <ImageView android:clickable="true" android:padding="5.0dip" android:layout_gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/page_indicator_bg" /> 102 <ImageView android:clickable="true" android:padding="5.0dip" android:layout_gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/page_indicator_bg" /> 103 <ImageView android:clickable="true" android:padding="5.0dip" android:layout_gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/page_indicator_bg" /> 104 <ImageView android:clickable="true" android:padding="5.0dip" android:layout_gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/page_indicator_bg" /> 105 <ImageView android:clickable="true" android:padding="5.0dip" android:layout_gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/page_indicator_bg" /> 106 <ImageView android:clickable="true" android:padding="5.0dip" android:layout_gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/page_indicator_bg" /> 107 <ImageView android:clickable="true" android:padding="5.0dip" android:layout_gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/page_indicator_bg" /> 108 </LinearLayout> 109 <LinearLayout android:layout_width="fill_parent" 110 android:layout_height="fill_parent" 111 android:visibility="gone" 112 android:id="@+id/animLayout" 113 > 114 <LinearLayout 115 android:id="@+id/leftLayout" 116 android:layout_width="wrap_content" 117 android:layout_height="fill_parent"> 118 <ImageView android:layout_height="wrap_content" 119 android:layout_width="wrap_content" 120 android:src="@drawable/whatsnew_left"/> 121 <ImageView android:layout_height="wrap_content" 122 android:layout_width="wrap_content" 123 android:src="@drawable/whatsnew_left_m"/> 124 </LinearLayout> 125 <LinearLayout 126 android:id="@+id/rightLayout" 127 android:layout_width="fill_parent" 128 android:layout_height="fill_parent"> 129 <ImageView android:layout_height="wrap_content" 130 android:layout_width="wrap_content" 131 android:src="@drawable/whatsnew_right_m"/> 132 <ImageView android:layout_height="wrap_content" 133 android:layout_width="wrap_content" 134 android:src="@drawable/whatsnew_right"/> 135 </LinearLayout> 136 </LinearLayout> 137 </RelativeLayout>
button_bg.xml
View Code
1 <?xml version="1.0" encoding="utf-8"?> 2 <selector xmlns:android="http://schemas.android.com/apk/res/android"> 3 <item android:state_pressed="true" 4 android:drawable="@drawable/whatsnew_btn_pressed" /> <!-- pressed --> 5 <item android:state_focused="true" 6 android:drawable="@drawable/whatsnew_btn_pressed" /> <!-- focused --> 7 <item android:drawable="@drawable/whatsnew_btn_nor" /> <!-- default --> 8 </selector>
page_indicator_bg.xml
View Code
1 <?xml version="1.0" encoding="utf-8"?> 2 <selector 3 xmlns:android="http://schemas.android.com/apk/res/android"> 4 <item android:state_enabled="true" android:drawable="@drawable/page_indicator_unfocused" /> 5 <item android:state_enabled="false" android:drawable="@drawable/page_indicator_focused" /> 6 </selector>
用到的基本图片