在微信5.3.1Android版本中,微信的导航栏切换的效果很不错,切换标题是,滑动条是滑动过去的,而不是直接跳过去的,给人一种很舒服的动画感觉。在这里,我就说说我对实现这种效果的理解,俗话说:眼见为实,先看看效果图吧:
怎样,效果是不是一样的,只是没有照搬微信里面的素材而已。
实现这个效果,我们先分步骤实现:
一:滑动条的实现。
首先,我是在上一次讲的 Android 启动引导页(动态生成底部导航圆点)的基础上添加的滑动功能(由于重建了项目文件,所以就把地图导航小圆点给去掉了,本来也不是本文的重点),没有看过的可以先看看,再看本文,效果才更好。
也先看看效果图:
在这里的滑动原理是:自定义一个控件(TransLateView继承自view),当此控件初始化时,获取控件的宽度,然后根据所要显示的节点(标题)数,计算出每个节点的宽度,然后在onDraw函数中,以某一点为起点(当然这是我们可以在程序中自己定义的,这是重点),绘制节点长度的一条直线,就实现了滑动条的绘制,然后动态的改变绘制的起点,就能实现滑动条的滑动条效果。
自定义控件(TransLateView)代码如下:
package com.ywl.slidetitle;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
public class TransLateView extends View {
private float x = 0;// 滑动条的起始坐标
private float initX = 0;// 每个节点的宽度(即:滑动条的宽度)
Paint paint = new Paint();
public TransLateView(Context context) {
super(context);
}
public TransLateView(Context context, AttributeSet attribute)
{
super(context, attribute);
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
paint.setColor(Color.BLUE);
paint.setStrokeWidth(15);
// 绘制滑动条,x为起始坐标,initX + x为终止坐标,就绘制了一条蓝色的线(滑动条)
canvas.drawLine(0 + x, 0, initX + x, 0, paint);
}
/**
* 传入要实现滑动的节点数(即:标题数),再根据节点数计算出每一个节点所占的宽度,然后在onDraw函数中绘制。
*
* @param count
*/
public void setInitX(final int count)
{
// 这是在加载控件时获取控件的总宽度(不一定是屏幕宽度,而是在布局文件中我们设置的:layout_width=“***”的宽度。
// 然后除以节点数,得到的就是每个节点要显示的长度
getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
initX = (float)getWidth() / count;
invalidate();
}
});
}
/**
* 得到此控件的宽
*
* @return
*/
public float getW()
{
invalidate();
return initX;
}
/**
* x:绘制滑动条的起始X坐标
*
* @param x
*/
public void setXx(float x)
{
this.x = x;
invalidate();
}
}
原理我已经说了,代码里注释也比较详细,这里也就不再多说什么了,很简单的。
然后是在MainActivity中的使用:
先看看布局文件(activity_main.xml):
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}" >
<LinearLayout
android:id="@+id/my_layout"
android:layout_width="match_parent"
android:layout_height="50dip"
android:gravity="center"
android:orientation="horizontal"
/>
<com.ywl.slidetitle.TransLateView
android:id="@+id/move"
android:layout_width="match_parent"
android:layout_height="3dip"
android:layout_marginTop="50dip"
android:background="#00ff00"/>
<View
android:id="@+id/lines"
android:layout_width="match_parent"
android:layout_height="1dip"
android:layout_below="@id/move"
android:background="#00ff00"/>
<android.support.v4.view.ViewPager
android:id="@+id/my_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/move"/>
</RelativeLayout>
其中“com.ywl.slidetitle.TransLateView”控件就是我们自定义的控件,只需设置它的长度和宽度就行,为了美观,可以设置背景颜色等等其他的效果。
然后是在MainActivity中引用:
<pre name="code" class="java">package com.ywl.slidetitle;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.LinearLayout.LayoutParams;
import android.widget.Toast;
public class MainActivity extends Activity implements OnPageChangeListener
{
private ViewPager vPager;
private VpAdapter vpAdapter;
private TransLateView move;
private static int[] imgs = { R.drawable.img1, R.drawable.img2,
R.drawable.img3 };// 要显示的图片资源
private ArrayList<ImageView> imageViews;// 用于包含引导页要显示的图片
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
vPager = (ViewPager) findViewById(R.id.my_viewpager);
move = (TransLateView) findViewById(R.id.move);
move.setInitX(3);// 设置节点数(标题数)
initImages();
vpAdapter = new VpAdapter(imageViews);
vPager.setAdapter(vpAdapter);
vPager.setOnPageChangeListener(this);
}
/**
* 把引导页要显示的图片添加到集合中,以传递给适配器,用来显示图片。
*/
private void initImages()
{
LayoutParams mParams = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);// 设置每一张图片都填充窗口
imageViews = new ArrayList<ImageView>();
for (int i = 0; i < imgs.length; i++)
{
ImageView iv = new ImageView(this);
iv.setLayoutParams(mParams);// 设置布局
iv.setImageResource(imgs[i]);// 为Imageview添加图片资源
iv.setScaleType(ScaleType.FIT_XY);// 设置图片拉伸效果
imageViews.add(iv);
if (i == imgs.length - 1)// 为最后一张添加点击事件
{
iv.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
Toast.makeText(MainActivity.this, "跳转。。。",
Toast.LENGTH_SHORT).show();
}
});
}
}
}
/**
* 根据引导页的数量,动态生成相应数量的导航小圆点,并添加到LinearLayout中显示。
*/
@Override
public void onPageScrollStateChanged(int arg0)
{
}
/**
* 动态绘制滑动条: arg0:表示实在第几个页面,也就是标题。arg0乘以滑动条的宽度,就是没有滑动时滑动条绘制的起始坐标。
* arg1:为页面偏移百分比,滑动时,偏移窗口左边的偏移量。偏移量乘以滑动条的宽度再加上,静止时的坐标,就是动态绘制时的起始坐标
* 起始坐标确定了,绘制滑动条就交给自定义控件里的onDraw绘制就可以了.
*/
@Override
public void onPageScrolled(int arg0, float arg1, int arg2)
{
move.setXx((float) arg0 * move.getW() + move.getW() * arg1);
}
/**
* arg0:当前滑动显示页面的索引值,可以根据这个值,来设置相应小圆点的状态。
*/
@Override
public void onPageSelected(int arg0)
{
}
}
这样就实现了滑动条的滑动效果。