这个效果很常见,网上开源的也挺多的,今天抽出了一些时间自己写了一个这个效果,自定义控件写的。所以灵活性很大,可以需求,随意变换样式。废话不多少了,直接贴代码和apk
运行后的效果图如下:
演示apk下载地址:http://pan.baidu.com/s/1hqeijfY
项目中用到的图片可以从apk解压后获取。
MainActivity.java
public class MainActivity extends Activity implements OnPageChangeListener, OnTabSelectedItemListener {
// tabhost每一项的内容
private String[] topContent = new String[] {"双色球", "大乐透", "3D", "刮刮乐", "双色器"};
// 需要显示view的个数
private static final int TYPE_NUM = 5;
private ViewPager viewPager;
private TopMenuLayout topMenuLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setUpViews();
}
private void setUpViews() {
topMenuLayout = (TopMenuLayout) findViewById(R.id.top_menu_layout);
viewPager = (ViewPager) findViewById(R.id.view_pager);
topMenuLayout.setTopMenuItemContent(topContent);
topMenuLayout.setTabSelectedListener(this);
// 存储视图集合
ArrayList<View> arrayViews = new ArrayList<View>();
View[] views = new View[TYPE_NUM];
for (int i = 0; i < TYPE_NUM; i++) {
views[i] = View.inflate(this, R.layout.view1, null);
arrayViews.add(views[i]);
}
ViewPagerAdapter pagerAdapter = new ViewPagerAdapter(arrayViews);
viewPager.setAdapter(pagerAdapter);
viewPager.setOnPageChangeListener(this);
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageSelected(int arg0) {
topMenuLayout.check(arg0);
}
@Override
public void onTabSelectedAction(int selection) {
Toast.makeText(this, String.valueOf(selection), 0).show();
}
class ViewPagerAdapter extends PagerAdapter {
private List<View> mListViews;
public ViewPagerAdapter(List<View> listViews) {
this.mListViews = listViews;
}
@Override
public int getCount() {
return mListViews.size();
}
// 来判断显示的是否是同一个view,这里我们将两个参数相比较返回即可
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
// PagerAdapter只缓存三张要显示的图片,如果滑动的图片超出了缓存的范围,就会调用这个方法,将view销毁
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(mListViews.get(position));
}
// 当要显示的view可以进行缓存时候,会调用这个方法进行显示图片的初始化,
// 我们将要显示的view加入到viewGroup中,然后作为返回值返回即可
@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(mListViews.get(position), 0);
return mListViews.get(position);
}
}
}
TopMenuLayout.java
/**
* 自定义控件,继承RelativeLayout.做成选项卡控件.
* @ClassName: TopMenuLayout
* @author lugq
* @date 2014年9月18日 上午10:24:08
*
*/
public class TopMenuLayout extends RelativeLayout implements OnClickListener {
private Context context;
// 获取手机屏幕信息类
private DisplayMetrics dm;
// 选项卡显示的内容
private String[] topMenuItemContent;
// 手机屏幕的宽度属性
private int screenWidth;
// 红三角的背景,选项卡移动到的位置设置的背景。
private ImageView shineImg;
// topMenuItemContent数组的长度.
private int itemLength;
// 上一个位置
private int lastIndex = -1;
private LinearLayout menuRadioGroup;
private OnTabSelectedItemListener onTabSelectedItemListener;
// 位移动画开始的位置
private int animationStartShine = 0;
// 通过构造方法把context传进来
// 两个个构造方法都要写上。否则会出错误。
public TopMenuLayout(Context context) {
super(context);
this.context = context;
init();
}
public TopMenuLayout(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
private void init() {
// 创建一个ImageView.
shineImg = new ImageView(context);
// 红三角背景
shineImg.setImageResource(R.drawable.tab_shine);
// 给自定义的RelativeLayout整个布局设置背景
this.setBackgroundResource(R.drawable.top_tab_bg);
}
/**
* 初始化选项卡每一项显示的内容。必须调用的方法,否则无数据显示
* @param topMenuItemContent 传递进来的显示的内容
*/
public void setTopMenuItemContent(String[] topMenuItemContent) {
this.topMenuItemContent = topMenuItemContent;
initViews();
}
private void initViews() {
densityUtil(context);
createTopMenu();
createSelectedFlag();
check(0);
}
private void createSelectedFlag() {
RelativeLayout.LayoutParams itemParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
addView(shineImg, itemParams);
initShineImgPosition();
}
/**
* 初始化红三角背景的位置(在第一个选项卡内容正下方)
*/
private void initShineImgPosition() {
RelativeLayout.LayoutParams imgParams =
new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
imgParams.leftMargin = (int) (screenWidth / (topMenuItemContent.length * 2) - 17 / 2);
shineImg.setLayoutParams(imgParams);
}
private void createTopMenu() {
// 选项卡内容的长度
itemLength = topMenuItemContent.length;
// 设置参数加进RelativeLayout布局中属性
RelativeLayout.LayoutParams params =
new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
// 居中
params.addRule(RelativeLayout.CENTER_IN_PARENT);
menuRadioGroup = new LinearLayout(context);
menuRadioGroup.setOrientation(LinearLayout.HORIZONTAL);
for (int i = 0; i < itemLength; i++) {
TextView menuItem = new TextView(context);
menuItem.setId(i);
LinearLayout.LayoutParams itemParams = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1.0f);
menuItem.setPadding(0, 0, 0, 0);
menuItem.setText(topMenuItemContent[i]);
menuItem.setGravity(Gravity.CENTER);
menuItem.setOnClickListener(this);
menuRadioGroup.addView(menuItem, itemParams);
}
this.addView(menuRadioGroup, params);
}
/**
* 获取手机屏幕的宽度
* @param context
*/
private void densityUtil(Context context) {
dm = new DisplayMetrics();
dm = context.getApplicationContext().getResources().getDisplayMetrics();
// 获取屏幕的宽度(像素)
screenWidth = dm.widthPixels;
}
/**
* 选中某一项
* @param position 从0开始,0代表选中第一项
*/
public void check(int position) {
// 如果点击已经选中的一项,不做任何操作.
if (position == lastIndex) {
return;
}
animateArrow(position);
// 恢复上一个位置的textview的颜色
if (lastIndex >= 0) {
((TextView) menuRadioGroup.getChildAt(lastIndex)).setTextColor(getResources().getColor(android.R.color.background_dark));
}
TextView childView0 = (TextView) menuRadioGroup.getChildAt(position);
childView0.setTextColor(getResources().getColor(android.R.color.holo_blue_bright));
lastIndex = position;
if (onTabSelectedItemListener != null) {
onTabSelectedItemListener.onTabSelectedAction(position);
}
}
/**
* 箭头移动的动画效果.
* @param position
*/
private void animateArrow(int position) {
int animationEndShine = screenWidth / itemLength * position;
TranslateAnimation anim = new TranslateAnimation(animationStartShine, animationEndShine, 0, 0);
// 最后一个位置赋值给上一个位置
animationStartShine = animationEndShine;
anim.setDuration(100);
anim.setFillAfter(true);
shineImg.startAnimation(anim);
}
@Override
public void onClick(View v) {
int position = v.getId();
check(position);
}
/**
* 对外提供的回调方法.
* @param tabSelectedListener
*/
public void setTabSelectedListener(OnTabSelectedItemListener onTabSelectedItemListener) {
this.onTabSelectedItemListener = onTabSelectedItemListener;
}
public interface OnTabSelectedItemListener {
/**
* 选择了那个tab
* @param selection 从0开始,0代表第一个
*/
public void onTabSelectedAction(int selection);
}
}
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" >
<RelativeLayout
android:id="@+id/guess_top_title"
android:layout_width="fill_parent"
android:layout_height="40dp"
android:background="@android:color/holo_blue_light"
android:orientation="horizontal" >
<TextView
android:id="@+id/guess_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="积分竞猜"
android:textSize="20dp" />
</RelativeLayout>
<com.example.custom_tabhost.TopMenuLayout
android:id="@+id/top_menu_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/guess_top_title" />
<android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="@id/top_menu_layout"
/>
</RelativeLayout>
view1.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="204dp"
android:text="TextView" />
</RelativeLayout>
</LinearLayout>