先看效果:
这个效果实现起来相对比较复杂,我们先看下都有哪些文件:
滑动的效果我使用的是viewPager,使用这个类需要导入兼容包android-support-v4.jar
导入的方法很简单,这里就不说了。你可以百度下,或者下载我的demo,把里面的包拿出来使用都行。
下面直接看代码吧:
扫描二维码关注公众号,回复:
813441 查看本文章
DotMarks.java
/** * This class is used to wrap the dot marks which displayed in the bottom of the View * 这个类将底部的显示页面索引的小标记包装起来 * * @author Michael 叶坤 * @since 2012-08-07 * */ public class DotMarks extends LinearLayout { public DotMarks(Context context, AttributeSet attrs) { super(context, attrs); ini(context); } public DotMarks(Context context) { super(context); ini(context); } private ImageView viewOne; private ImageView viewTwo; private ImageView viewThree; private ImageView viewFour; private ImageView viewFive; private void ini(Context context) { LayoutInflater mInflater = ((Activity)context).getLayoutInflater(); View dotViews = mInflater.inflate(R.layout.dot_marks, null); this.addView(dotViews); viewOne = (ImageView)dotViews.findViewById(R.id.iv_one); viewTwo = (ImageView)dotViews.findViewById(R.id.iv_two); viewThree = (ImageView)dotViews.findViewById(R.id.iv_three); viewFour = (ImageView)dotViews.findViewById(R.id.iv_four); viewFive = (ImageView)dotViews.findViewById(R.id.iv_five); //initialize the dots viewOne.setImageDrawable(whiteDot); viewTwo.setImageDrawable(darkDot); viewThree.setImageDrawable(darkDot); viewFour.setImageDrawable(darkDot); viewFive.setImageDrawable(darkDot); } /** * display the dot marks dynamic by the viewPager index which passed in * * 根据传递进来的页面的索引切换小图标的显示 * * */ private Drawable whiteDot = this.getResources().getDrawable(R.drawable.dot_white); private Drawable darkDot = this.getResources().getDrawable(R.drawable.dot_dark); public void updateMark(int index) { switch(index) { case 0: viewOne.setImageDrawable(whiteDot); viewTwo.setImageDrawable(darkDot); viewThree.setImageDrawable(darkDot); viewFour.setImageDrawable(darkDot); viewFive.setImageDrawable(darkDot); break; case 1: viewOne.setImageDrawable(darkDot); viewTwo.setImageDrawable(whiteDot); viewThree.setImageDrawable(darkDot); viewFour.setImageDrawable(darkDot); viewFive.setImageDrawable(darkDot); break; case 2: viewOne.setImageDrawable(darkDot); viewTwo.setImageDrawable(darkDot); viewThree.setImageDrawable(whiteDot); viewFour.setImageDrawable(darkDot); viewFive.setImageDrawable(darkDot); break; case 3: viewOne.setImageDrawable(darkDot); viewTwo.setImageDrawable(darkDot); viewThree.setImageDrawable(darkDot); viewFour.setImageDrawable(whiteDot); viewFive.setImageDrawable(darkDot); break; case 4: viewOne.setImageDrawable(darkDot); viewTwo.setImageDrawable(darkDot); viewThree.setImageDrawable(darkDot); viewFour.setImageDrawable(darkDot); viewFive.setImageDrawable(whiteDot); break; } } }
WhatIsNewAdapter.java
/** * The ViewPager's adapter,just override these methods * * ViewPager的适配器,覆写它的方法就好了 * * @author Michael 叶坤 * @since 2012-08-07 * */ public class WhatIsNewAdapter extends PagerAdapter { public List<View> mListViews; public WhatIsNewAdapter(List<View> mListViews) { this.mListViews = mListViews; } @Override public void destroyItem(View arg0, int arg1, Object arg2) { ((ViewPager) arg0).removeView(mListViews.get(arg1)); } @Override public void finishUpdate(View arg0) { } @Override public int getCount() { return mListViews.size(); } @Override public Object instantiateItem(View arg0, int arg1) { ((ViewPager) arg0).addView(mListViews.get(arg1), 0); return mListViews.get(arg1); } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == (arg1); } @Override public void restoreState(Parcelable arg0, ClassLoader arg1) { } @Override public Parcelable saveState() { return null; } @Override public void startUpdate(View arg0) { } }
WhatIsNewUtils.java
/** * This class is used for : * judge whether the application is first been used.-->isFirstUse(Context context) * And save the data if users has opened the application.-->saveFirstUseFlag(Context context) * * example:when user open the application first time ,the method isFirstUse(Context context)will return true. * after user opened the application,the method saveFirstUseFlag(Context context) should be called * so that when user opened the application next time ,the method isFirstUse(Context context)will return false. * * see MainActivity.java to know how to use these methods. * * * * 这个类用来判断应用程序是否是第一次使用-->isFirstUse(Context context) * 如果用户打开过了这个程序,将标记保存-->saveFirstUseFlag(Context context) * * 例如:当用户第一次打开应用程序的时候,isFirstUse(Context context)方法返回的是true. * 之后你可以调用saveFirstUseFlag(Context context)方法。这样下次用户再打开程序员的时候 * isFirstUse(Context context)方法返回的是false. * * 具体使用,参见MainActivity.java * * @author Michael 叶坤 * @since 2012-08-07 * */ public class WhatIsNewUtils { private static String WHAT_IS_NEW_PRE_NAME = "what_is_new_pre_name"; private static String FIRST_USE_FLAG = "first_use_flag"; /** * judge whether the first time to use this application * * 判断是否是第一次使用该应用程序 * * */ public static boolean isFirstUse(Context context) { SharedPreferences sharedPreferences = context.getSharedPreferences(WHAT_IS_NEW_PRE_NAME, Activity.MODE_PRIVATE); boolean flag = sharedPreferences.getBoolean(FIRST_USE_FLAG, true); return flag; } /** * save the flag of first use the application * * 保存第一次使用的信息 * * */ public static void saveFirstUseFlag(Context context) { SharedPreferences sharedPreferences = context.getSharedPreferences(WHAT_IS_NEW_PRE_NAME, Activity.MODE_PRIVATE); SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putBoolean(FIRST_USE_FLAG, false); editor.commit(); } }
WhatIsNewView.java
/** * This class encapsulate the View which used for introduce something new of your application, * or how to use your application etc to users.Of course,you can also encapsulate this in a Activity, * but if you do that, you can not achieve the effect of animations perfectly. * So,I decide to encapsulate this in a LinearLayout(View).Because most animations * can be achieve perfectly in the same Activity,not between two Activity. * You can do this by use the method setContentView(); * * setContentView(R.layout.activity_main); * setContentView(new WhatIsNewView(context)); * just switch these method dynamic in the same Activity MainActivity.java. * * * * 一般应用程序第一次使用的时候,都有一个关于你的程序的新特性,或者任何是任何使用你的程序的介绍等等。 * 你可以把这个功能封装在一个Activity里面,但是这样做有一点不好的地方,当你要实现一些动画效果的时候, * 在Activity之间实现起来不是很完美,会闪一下,为了实现类似微信那样的效果,我们需要将它封装为一个View * 也就是说和程序的主界面在同一个Activity中,通过setContentView方法来切换视图,这样就可以较好的实现效果 * 而且不需要在Manifest中申明一个Activity,也方便使用。 * * @author Michael 叶坤 * * @since 2012-08-07 * */ public class WhatIsNewView extends LinearLayout { private Context context; private ImageView ivLeftImage; private ImageView ivRightImage; private TextView tvLeftButton; private TextView tvRightButton; private DotMarks dotViews; public WhatIsNewView(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; ini(context); } public WhatIsNewView(Context context) { super(context); this.context = context; ini(context); } private void ini(Context context) { LayoutInflater mInflater = ((Activity)context).getLayoutInflater(); View layoutWhatIsNew = mInflater.inflate(R.layout.layout_what_is_new, null); View viewPagerOne = mInflater.inflate(R.layout.viewpager_one, null); View viewPagerTwo = mInflater.inflate(R.layout.viewpager_two, null); View viewPagerThree = mInflater.inflate(R.layout.viewpager_three, null); View viewPagerFour = mInflater.inflate(R.layout.viewpager_four, null); View viewPagerFive = mInflater.inflate(R.layout.viewpager_five, null); ViewPager viewPager = (ViewPager)layoutWhatIsNew.findViewById(R.id.view_pager); List<View> viewItems = new ArrayList<View>(); viewItems.add(viewPagerOne); viewItems.add(viewPagerTwo); viewItems.add(viewPagerThree); viewItems.add(viewPagerFour); viewItems.add(viewPagerFive); viewPager.setAdapter(new WhatIsNewAdapter(viewItems)); dotViews = (DotMarks)layoutWhatIsNew.findViewById(R.id.dot_marks); viewPager.setOnPageChangeListener(new OnPageChangeListener() { /** * Update the marks when viewPager's index changed * 根据ViewPager的页面的变化来实时更新索引小图标 * * */ @Override public void onPageSelected(int arg0) { dotViews.updateMark(arg0); } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageScrollStateChanged(int arg0) { } }); ivLeftImage = (ImageView)viewPagerFive.findViewById(R.id.iv_left_image01); ivRightImage = (ImageView)viewPagerFive.findViewById(R.id.iv_left_image02); LinearLayout llStartApp = (LinearLayout)viewPagerFive.findViewById(R.id.ll_start_app); tvLeftButton = (TextView)viewPagerFive.findViewById(R.id.tv_left_btn01); tvRightButton = (TextView)viewPagerFive.findViewById(R.id.tv_left_btn02); llStartApp.setOnClickListener(new OnClickListener() { /** * Here you can do some animations and finish this Activity * * 这里你可以执行一些界面切换的动画,并finish这个Activity * * */ @Override public void onClick(View v) { startAnimation(); } }); this.addView(layoutWhatIsNew); } /** * startAnimation * * 开始动画 * * */ private void startAnimation() { Animation leftAnim = AnimationUtils.loadAnimation(context, R.anim.slide_left_anim); Animation rightAnim = AnimationUtils.loadAnimation(context, R.anim.slide_right_anim); final Animation fadeAnim = AnimationUtils.loadAnimation(context, R.anim.fade_anim); leftAnim.setFillAfter(true); rightAnim.setFillAfter(true); rightAnim.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { if(onAnimListener != null) { onAnimListener.onAnimationStart(); dotViews.startAnimation(fadeAnim); } } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { if(onAnimListener != null) { onAnimListener.onAnimationEnd(); } } }); ivLeftImage.startAnimation(leftAnim); tvLeftButton.startAnimation(leftAnim); ivRightImage.startAnimation(rightAnim); tvRightButton.startAnimation(rightAnim); } private OnAppAnimationListener onAnimListener; /** * Here add a listener,to listen the event of animation started and ended. * * 这里设置一个监听,当动画开始和结束的时候通知外面setContentView改变 * * */ public interface OnAppAnimationListener { public void onAnimationStart(); public void onAnimationEnd(); } public void setOnAppAnimationListener(OnAppAnimationListener onAnimListener) { this.onAnimListener = onAnimListener; } }
最后看看是如何使用的:
/** * * This is the MainActivity of the Application * * 这个是程序的主界面 * * @author Michael 叶坤 * @since 2012-08-07 * */ public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //judge the application is first used //判断是否是第一次使用 if(WhatIsNewUtils.isFirstUse(MainActivity.this)) { showWhatIsNew(); } else { setContentView(R.layout.activity_main);//normally } } /** * show something about you application * * 显示关于你的程序的介绍 * */ private void showWhatIsNew() { WhatIsNewView whatIsNewView = new WhatIsNewView(MainActivity.this); whatIsNewView.setOnAppAnimationListener(new OnAppAnimationListener() { @Override public void onAnimationStart() { } @Override public void onAnimationEnd() { LayoutInflater mInflater = MainActivity.this.getLayoutInflater(); final View mainActivityView = mInflater.inflate(R.layout.activity_main, null); setContentView(mainActivityView); Animation enterAnim = AnimationUtils.loadAnimation(MainActivity.this, R.anim.main_activity_enter_anim); enterAnim.setFillAfter(true); mainActivityView.startAnimation(enterAnim); } }); setContentView(whatIsNewView); //save the flag ,so next time when user open this application,WhatIsNewUtils.isFirstUse(MainActivity.this) will return false //保存标记,下一次打开程序WhatIsNewUtils.isFirstUse(MainActivity.this)返回的是false WhatIsNewUtils.saveFirstUseFlag(MainActivity.this); } }
代码中应该可以看出思路。布局文件和动画文件太多了,这里就不贴了,如果有兴趣您可以下载我的demo参看。如果发现问题欢迎指正。
demo下载地址:https://github.com/michaelye/DemoWhatIsNewComponent