Android自定义控件之自定义tabhost

这个效果很常见,网上开源的也挺多的,今天抽出了一些时间自己写了一个这个效果,自定义控件写的。所以灵活性很大,可以需求,随意变换样式。废话不多少了,直接贴代码和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>
















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值