Android UI设计与开发之ViewPager仿微信引导界面以及动画效果
基于前两篇比较简单的实例做铺垫之后,这一篇我们来实现一个稍微复杂一点的引导界面的效果,当然也只是稍微复杂了一点,对于会的人来说当然还是so easy!正所谓会者不难,难者不会,大概说的就是这个意思了吧。好的,话不多说,回归正题。
这篇要实现的是一个仿微信的动画效果,虽然这种效果的实现在网上到处都有,但是我还是想站在中低端开发者的角度去告诉大家是如何实现的,当然实现的方式有很多,我也只是列出了我认为实现起来比较方便的一种方法,希望大家能够受用。
一、实现的效果图
有图才有真相,上图先:
点击按钮后出现动画效果,然后进入到另一个界面:
二 、程序的目录结构
三、具体的编码实现
1、 在主布局界面中加入ViewPager组件,以及底部的小点,activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="wrap_content" > <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="fill_parent" android:layout_height="fill_parent" /> <LinearLayout android:id="@+id/ll" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="24.0dip" android:orientation="horizontal" > <ImageView android:id="@+id/page0" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:clickable="true" android:padding="5dip" android:src="@drawable/page_indicator_focused" /> <ImageView android:id="@+id/page1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:clickable="true" android:padding="5dip" android:src="@drawable/page_indicator_unfocused" /> <ImageView android:id="@+id/page2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:clickable="true" android:padding="5dip" android:src="@drawable/page_indicator_unfocused" /> <ImageView android:id="@+id/page3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:clickable="true" android:padding="5dip" android:src="@drawable/page_indicator_unfocused" /> <ImageView android:id="@+id/page4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:clickable="true" android:padding="5dip" android:src="@drawable/page_indicator_unfocused" /> <ImageView android:id="@+id/page5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:clickable="true" android:padding="5dip" android:src="@drawable/page_indicator_unfocused" /> </LinearLayout> </RelativeLayout>
2、接着在guide_view01.xml等几个布局页面中添加引导界面要显示的图片和控件,因为这几个布局界面都大同小异,所以在这里我就不一一贴出来了吧,有需要的同学可以直接下载源码,guide_view01.xml:
<?xml version="1.0" encoding="UTF-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/w01" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_marginTop="35dp" android:gravity="center" android:text="@string/guide_text01" android:textColor="@color/TextColor" android:textSize="22sp" /> </RelativeLayout>
3、然后是要实现动画效果的布局界面,guide_door.xml:
<?xml version="1.0" encoding="UTF-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ImageView android:id="@+id/imageLeft" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_alignParentLeft="true" android:scaleType="fitXY" android:src="@drawable/w_left" /> <ImageView android:id="@+id/imageRight" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_alignParentRight="true" android:scaleType="fitXY" android:src="@drawable/w_right" android:visibility="visible" /> <TextView android:id="@+id/anim_text" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_marginTop="35dp" android:gravity="center" android:text=" \n \n微信,是一个生活方式\n \n " android:textColor="#fff" android:textSize="22sp" /> </RelativeLayout>
4、最后是完成动画效果之后进入的布局界面,activity_other.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="亲,可以开始你的微信生活了!" /> </LinearLayout>
5、在这里还要创建一个xml文件来实现自定义按钮的效果,关于自定义按钮的效果实现我会在后面的文章中专题详细介绍,这里就不在赘述,start_weixin_btn.xml:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_enabled="true" android:state_pressed="true" android:drawable="@drawable/whatsnew_btn_pressed" /> <!--按下时的效果--> <item android:state_enabled="true" android:drawable="@drawable/whatsnew_btn_nor" /> <!--正常状态的效果--> </selector>
6、布局界面已经讲解完毕,接下来让我们进行详细的代码讲解,ViewPager适配器代码,ViewPagerAdapter.java:
package com.yangyu.myguideview02; import java.util.ArrayList; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.view.View; /** * @author yangyu * 功能描述:ViewPager适配器,用来绑定数据和view */ public class ViewPagerAdapter extends PagerAdapter { //界面列表 private ArrayList<View> views; public ViewPagerAdapter (ArrayList<View> views){ this.views = views; } /** * 获得当前界面数 */ @Override public int getCount() { if (views != null) { return views.size(); } return 0; } /** * 初始化position位置的界面 */ @Override public Object instantiateItem(View view, int position) { ((ViewPager) view).addView(views.get(position), 0); return views.get(position); } /** * 判断是否由对象生成界面 */ @Override public boolean isViewFromObject(View view, Object arg1) { return (view == arg1); } /** * 销毁position位置的界面 */ @Override public void destroyItem(View view, int position, Object arg2) { ((ViewPager) view).removeView(views.get(position)); } }
7、主程序入口activity类,MainActivity.java:
package com.yangyu.myguideview02; import java.util.ArrayList; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; /** * @author yangyu * 功能描述:主程序入口activity */ public class MainActivity extends Activity { // 定义ViewPager对象 private ViewPager viewPager; // 定义ViewPager适配器 private ViewPagerAdapter vpAdapter; // 定义一个ArrayList来存放View private ArrayList<View> views; //定义各个界面View对象 private View view1,view2,view3,view4,view5,view6; // 定义底部小点图片 private ImageView pointImage0, pointImage1, pointImage2, pointImage3,pointImage4, pointImage5; //定义开始按钮对象 private Button startBt; // 当前的位置索引值 private int currIndex = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initData(); } /** * 初始化组件 */ private void initView() { //实例化各个界面的布局对象 LayoutInflater mLi = LayoutInflater.from(this); view1 = mLi.inflate(R.layout.guide_view01, null); view2 = mLi.inflate(R.layout.guide_view02, null); view3 = mLi.inflate(R.layout.guide_view03, null); view4 = mLi.inflate(R.layout.guide_view04, null); view5 = mLi.inflate(R.layout.guide_view05, null); view6 = mLi.inflate(R.layout.guide_view06, null); // 实例化ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager); // 实例化ArrayList对象 views = new ArrayList<View>(); // 实例化ViewPager适配器 vpAdapter = new ViewPagerAdapter(views); // 实例化底部小点图片对象 pointImage0 = (ImageView) findViewById(R.id.page0); pointImage1 = (ImageView) findViewById(R.id.page1); pointImage2 = (ImageView) findViewById(R.id.page2); pointImage3 = (ImageView) findViewById(R.id.page3); pointImage4 = (ImageView) findViewById(R.id.page4); pointImage5 = (ImageView) findViewById(R.id.page5); //实例化开始按钮 startBt = (Button) view6.findViewById(R.id.startBtn); } /** * 初始化数据 */ private void initData() { // 设置监听 viewPager.setOnPageChangeListener(new MyOnPageChangeListener()); // 设置适配器数据 viewPager.setAdapter(vpAdapter); //将要分页显示的View装入数组中 views.add(view1); views.add(view2); views.add(view3); views.add(view4); views.add(view5); views.add(view6); // 给开始按钮设置监听 startBt.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { startbutton(); } }); } public class MyOnPageChangeListener implements OnPageChangeListener { @Override public void onPageSelected(int position) { switch (position) { case 0: pointImage0.setImageDrawable(getResources().getDrawable(R.drawable.page_indicator_focused)); pointImage1.setImageDrawable(getResources().getDrawable(R.drawable.page_indicator_unfocused)); break; case 1: pointImage1.setImageDrawable(getResources().getDrawable(R.drawable.page_indicator_focused)); pointImage0.setImageDrawable(getResources().getDrawable(R.drawable.page_indicator_unfocused)); pointImage2.setImageDrawable(getResources().getDrawable(R.drawable.page_indicator_unfocused)); break; case 2: pointImage2.setImageDrawable(getResources().getDrawable(R.drawable.page_indicator_focused)); pointImage1.setImageDrawable(getResources().getDrawable(R.drawable.page_indicator_unfocused)); pointImage3.setImageDrawable(getResources().getDrawable(R.drawable.page_indicator_unfocused)); break; case 3: pointImage3.setImageDrawable(getResources().getDrawable(R.drawable.page_indicator_focused)); pointImage4.setImageDrawable(getResources().getDrawable(R.drawable.page_indicator_unfocused)); pointImage2.setImageDrawable(getResources().getDrawable(R.drawable.page_indicator_unfocused)); break; case 4: pointImage4.setImageDrawable(getResources().getDrawable(R.drawable.page_indicator_focused)); pointImage3.setImageDrawable(getResources().getDrawable(R.drawable.page_indicator_unfocused)); pointImage5.setImageDrawable(getResources().getDrawable(R.drawable.page_indicator_unfocused)); break; case 5: pointImage5.setImageDrawable(getResources().getDrawable(R.drawable.page_indicator_focused)); pointImage4.setImageDrawable(getResources().getDrawable(R.drawable.page_indicator_unfocused)); break; } currIndex = position; // animation.setFillAfter(true);// True:图片停在动画结束位置 // animation.setDuration(300); // mPageImg.startAnimation(animation); } @Override public void onPageScrollStateChanged(int arg0) { } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } } /** * 相应按钮点击事件 */ private void startbutton() { Intent intent = new Intent(); intent.setClass(MainActivity.this,GuideViewDoor.class); startActivity(intent); this.finish(); } }
PS:在这段代码中,有个地方需要注意,尽管我们写代码的时候一直很小心,但还是避免不了会犯一些低级的错误,以至于调试耽误了时间
//实例化开始按钮 startBt = (Button) view6.findViewById(R.id.startBtn);
这是最后一个布局界面中的一个开始按钮,由于在findvViewById()方法前面忘记使用了view6来调用该方法,以至于模拟器报出空指针异常。
8、实现动画效果的入口activity类,在这个类中主要实现了点击开始按钮后实现一个动画效果来达到进入另一个界面的目的,该类中的主要使用了动画类。我会在后面的章节中以专题的形式来介绍动画这一块的类容,所以这里也不再赘述,
GuideViewDoor.Java:
package com.yangyu.myguideview02; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.ScaleAnimation; import android.view.animation.TranslateAnimation; import android.widget.ImageView; import android.widget.TextView; /** * @author yangyu * 功能描述:实现动画效果的入口activity */ public class GuideViewDoor extends Activity { //定义左右两张图片对象 private ImageView mLeft,mRight; //定义一个文本对象 private TextView mText; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.guide_door); //实例化对象 mLeft = (ImageView)findViewById(R.id.imageLeft); mRight = (ImageView)findViewById(R.id.imageRight); mText = (TextView)findViewById(R.id.anim_text); //实例化动画对象 AnimationSet anim = new AnimationSet(true); //实例化位移动画对象 TranslateAnimation mytranslateanim = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0f,Animation.RELATIVE_TO_SELF,-1f,Animation.RELATIVE_TO_SELF,0f,Animation.RELATIVE_TO_SELF,0f); //设置动画持续时间 mytranslateanim.setDuration(2000); //设置启动时间 anim.setStartOffset(800); //将位移动画添加进动画效果中 anim.addAnimation(mytranslateanim); //动画结束后,保留在终止位 anim.setFillAfter(true); //左边图启动该动画效果 mLeft.startAnimation(anim); AnimationSet anim1 = new AnimationSet(true); TranslateAnimation mytranslateanim1 = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0f,Animation.RELATIVE_TO_SELF,+1f,Animation.RELATIVE_TO_SELF,0f,Animation.RELATIVE_TO_SELF,0f); mytranslateanim1.setDuration(1500); anim1.addAnimation(mytranslateanim1); anim1.setStartOffset(800); anim1.setFillAfter(true); mRight.startAnimation(anim1); AnimationSet anim2 = new AnimationSet(true); ScaleAnimation myscaleanim = new ScaleAnimation(1f,3f,1f,3f,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f); myscaleanim.setDuration(1000); AlphaAnimation myalphaanim = new AlphaAnimation(1,0.0001f); myalphaanim.setDuration(1500); anim2.addAnimation(myscaleanim); anim2.addAnimation(myalphaanim); anim2.setFillAfter(true); mText.startAnimation(anim2); new Handler().postDelayed(new Runnable(){ @Override public void run(){ Intent intent = new Intent (GuideViewDoor.this,OtherActivity.class); startActivity(intent); GuideViewDoor.this.finish(); } }, 2300); } }
9、最后是另一个activity类,我为了只是达到进入到另一个界面的这种效果,所以代码比较简单,就是调用了一个layout布局页面,OtherActivity.java:
package com.yangyu.myguideview02; import android.app.Activity; import android.os.Bundle; /** * @author yangyu * 功能描述:另一个activity */ public class OtherActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_other); } }
10、最后大家别忘了在AndroidManifest.xml清单文件中为程序添加GuideViewDoor、OtherActivity这两个activity,否则会报出异常。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。