在上一节 Android仿微信滑动导航栏的实现(上)中我们已经实现了导航条的滑动条效果,只是还没有添加标题栏,现在我们就把标题栏给加上:
效果图和源码在本文末尾处。
在这里增加了一个显示标题栏的自定义控件:TitleLayout,继承于LinearLayout,其原理是:根据传递的标题栏的标题(其中隐藏着标题的数量),动态生成对应标题内容的TextView来显示标题,并控制其在控件中居中显示,还提供了一个方法,用于返回生成的标题控件,为了在调用activity中为每个标题添加不同的相应,其代码如下:
package com.ywl.slidetitle;
import android.content.Context;
import android.view.Gravity;
import android.widget.LinearLayout;
import android.widget.TextView;
public class TitleLayout extends LinearLayout {
public TextView[] textViews;// 标题栏数组,用于存储要显示的标题
/**
* titles:即要显示的标题栏的数组
*
* @param context
* @param titles
*/
public TitleLayout(Context context, String[] titles)
{
super(context);
// 控件中的子空间整体横向排列,控件本身填充父控件
this.setOrientation(HORIZONTAL);
LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
this.setLayoutParams(layoutParams);
// 初始化,标题栏
this.textViews = new TextView[titles.length];
// 循环,根据标题栏动态生成TextView来显示标题,每个标题栏的宽度比例为1:1,其中的内容居中。
for(int i = 0; i < titles.length; i++)
{
TextView textView = new TextView(context);
textView.setText(titles[i]);
textView.setGravity(Gravity.CENTER);
textViews[i] = textView;
LayoutParams params = new LayoutParams(0,LayoutParams.WRAP_CONTENT);
params.weight = 1;
params.gravity = Gravity.CENTER;
addView(textView, params);
}
}
/**
* 获取标题栏的标题TextView控件,为了在MainActi中添加对标题栏点击事件的相应和切换。
*
* @return
*/
public TextView[] getTextViews()
{
return textViews;
}
}
<pre name="code" class="html"><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>
id为my_layout的LinearLayout就是用来放置标题控件的。
在MainActivity对标题控件的使用如下:
package com.ywl.slidetitle;
import java.util.ArrayList;
import android.app.Activity;
import android.graphics.Color;
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;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity implements OnPageChangeListener
{
private ViewPager vPager;
private VpAdapter vpAdapter;
private TransLateView move;// 滑动条控件
private TitleLayout myLayout;// 标题栏控件
private LinearLayout titleLayout;// 用于包含标题栏控件
private static int[] imgs = { R.drawable.img1, R.drawable.img2,
R.drawable.img3 };// 要显示的图片资源
private ArrayList<ImageView> imageViews;// 用于包含引导页要显示的图片
private TextView[] textViews;// 存储标题栏返回的标题TextView控件
private String[] titles = { "标题一", "标题二", "标题三" };// 要显示的标题
@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);// 设置节点数(标题数)
titleLayout = (LinearLayout) findViewById(R.id.my_layout);
myLayout = new TitleLayout(this, titles);
textViews = myLayout.getTextViews();
for (int i = 0; i < textViews.length; i++)
{
if (i == 0)
{
textViews[i].setTextColor(Color.RED);
;
}
final int id = i;
textViews[i].setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
// TODO Auto-generated method stub
vPager.setCurrentItem(id);
}
});
}
titleLayout.addView(myLayout);
move.setInitX(titles.length);
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)
{
for (int n = 0; n < textViews.length; n++)
{
if (arg0 == n)
{
textViews[n].setTextColor(Color.RED);
}
else
{
textViews[n].setTextColor(Color.BLACK);
}
}
}
}
在activity中,主要是对TitleLayout控件的初始化,并添加到my_layout容器中,代码里注释也很详细,这里也不再啰嗦了。
最终效果如下:
好了 ,全部搞定,哈哈哈