仿微信切换view

本文介绍了一种使用自定义View实现带图标的TabView的方法,并通过ViewPager进行页面切换时平滑过渡的效果。自定义View中集成了颜色、图标、文本等属性的设置,通过XML属性配置简化了使用过程。

效果图如下:


import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.View;

public class IConStyleView extends View {

	// 字体颜色
	private int mColor = 0xFF45C01A;
	// 图片(icon图标)
	private Bitmap mIconBitmap;
	// tabitem的文本
	private String mText;
	// 字体大小
	private float mTextSize;
	private Paint mTextPaint;
	private Rect mTextBounds;
	private Rect mIconRect;
	private Rect mTextRect;

	// 透明度
	private float alpha;
	private Bitmap mBgBitmap;
	private Canvas mBgCanvas;
	private Paint mBgPaint;

	public void setMAlpha(float alpha) {
		this.alpha = alpha;
		invalidate();
	}

	public IConStyleView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	public IConStyleView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initParams(context, attrs);
	}

	public IConStyleView(Context context) {
		super(context);
	}

	private void initParams(Context context, AttributeSet attrs) {
		TypedArray typedArray = context.obtainStyledAttributes(attrs,
				R.styleable.DreamIconStyle);
		for (int i = 0; i < typedArray.getIndexCount(); i++) {
			int attr = typedArray.getIndex(i);
			switch (attr) {
			case R.styleable.DreamIconStyle_style_color:
				mColor = typedArray.getColor(attr, 0xFF45C01A);
				break;
			case R.styleable.DreamIconStyle_style_icon:
				BitmapDrawable bitmapDrawable = (BitmapDrawable) typedArray
						.getDrawable(attr);
				mIconBitmap = bitmapDrawable.getBitmap();
				break;
			case R.styleable.DreamIconStyle_style_text:
				mText = typedArray.getString(attr);
				break;
			case R.styleable.DreamIconStyle_style_text_size:
				mTextSize = typedArray.getDimension(attr, 10);
				break;

			default:
				break;
			}
		}
		typedArray.recycle();

		initTextPaint();
	}

	/**
	 * 初始化文本画笔
	 */
	private void initTextPaint() {
		mTextPaint = new Paint();
		mTextPaint.setColor(mColor);
		mTextPaint.setTextSize(mTextSize);
		mTextPaint.setAntiAlias(true);

		// 获取文本宽高
		mTextBounds = new Rect();
		mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBounds);
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		// 计算图片的宽高(动态计算)
		int mBitmapWidth = (int) (h * 0.6f);
		int mBitmapHeight = mBitmapWidth;
		setIconRect(w, h, mBitmapWidth, mBitmapHeight);
		setTextTect(w, h, mBitmapWidth);
	}

	/**
	 * 设置图片要绘制的矩形区域
	 * 
	 * @param w
	 * @param h
	 * @param mBitmapWidth
	 * @param mBitmapHeight
	 */
	private void setIconRect(int w, int h, int mBitmapWidth, int mBitmapHeight) {
		int left = (w - mBitmapWidth) / 2;
		int right = left + mBitmapWidth;
		int top = (h - mTextBounds.height() - mBitmapHeight) / 2;
		int bottom = top + mBitmapHeight;
		mIconRect = new Rect(left, top, right, bottom);
	}

	/**
	 * 计算文本的显示的矩形区域
	 * 
	 * @param w
	 * @param h
	 * @param mBitmapWidth
	 */
	private void setTextTect(int w, int h, int mBitmapWidth) {
		int textWidth = this.mTextBounds.width();
		int textHeight = this.mTextBounds.height();
		int left = (w - textWidth) / 2;
		int right = left + textWidth;
		int top = h - textHeight / 3;
		int bottom = top + textHeight;
		mTextRect = new Rect(left, top, right, bottom);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);

		// 1、清空画板
		canvasClear(canvas);
		// 2、绘制图片(2.1-绘制背景 2.2-绘制图片)
		canvasBitmap(canvas);
		// 3、绘制文字(2.1-绘制默认颜色的文本 2.2-绘制选中的文本)
		canvasText(canvas);
	}

	/**
	 * 清空画板
	 * 
	 * @param canvas
	 */
	private void canvasClear(Canvas canvas) {
		canvas.drawBitmap(mIconBitmap, null, mIconRect, null);
	}

	/**
	 * 画图片和画背景
	 * 
	 * @param canvas
	 */
	private void canvasBitmap(Canvas canvas) {
		// 计算透明度(透明度由ViewPager的滑动来决定)
		// 向上取整
		int alpha = (int) Math.ceil(255 * this.alpha);
		// 二级缓存(缓存背景图片和图标图片)
		mBgBitmap = Bitmap.createBitmap(getMeasuredWidth(),
				getMeasuredHeight(), Config.ARGB_8888);
		mBgCanvas = new Canvas(mBgBitmap);
		// 缓存画笔
		mBgPaint = new Paint();
		// 设置颜色块
		mBgPaint.setColor(this.mColor);
		mBgPaint.setAntiAlias(true);
		// 防抖动
		mBgPaint.setDither(true);
		// 设置背景图片的透明度
		mBgPaint.setAlpha(alpha);
		// 绘制颜色块(背景图片)
		mBgCanvas.drawRect(mIconRect, mBgPaint);

		// 根据系统API 我们得知graphics/Xfermodes
		mBgPaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));

		// 绘制图片
		// 恢复透明度、不影响绘制icon
		mBgPaint.setAlpha(255);
		mBgCanvas.drawBitmap(mIconBitmap, null, mIconRect, mBgPaint);

		// 将我们的缓存的图片绘制到自定义控件的画布上
		canvas.drawBitmap(mBgBitmap, 0, 0, null);
	}

	private void canvasText(Canvas canvas) {
		int alpha = (int) Math.ceil(255 * this.alpha);
		// 1、绘制默认文本
		mTextPaint.setColor(0xff555555);
		mTextPaint.setAlpha(255);
		canvas.drawText(mText, mTextRect.left, mTextRect.top, mTextPaint);

		// 2、绘制选中的文本
		mTextPaint.setColor(this.mColor);
		mTextPaint.setAlpha(alpha);
		canvas.drawText(mText, mTextRect.left, mTextRect.top, mTextPaint);
	}

}

import android.annotation.SuppressLint;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

@SuppressLint("NewApi")
public class TabFragment extends Fragment {
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		TextView textView = new TextView(getActivity());
		textView.setTextColor(Color.WHITE);
		textView.setBackgroundColor(Color.GRAY);
		Bundle arguments = getArguments();
		if (arguments != null) {
			textView.setText(arguments.getString("title"));
		}
		return textView;
	}
}

activity布局:

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:iconStyle="http://schemas.android.com/apk/res/com.tz.dream_10_21_viewpager_tab"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="${relativePackage}.${activityClass}" >

    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="0dip"
        android:layout_weight="1" />

    <LinearLayout
        android:id="@+id/ll_tab"
        android:layout_width="match_parent"
        android:layout_height="55dp"
        android:background="@drawable/tab_bg"
        android:orientation="horizontal" >

        <com.tz.dream_10_21_viewpager_tab.IConStyleView
            android:id="@+id/icon_message_view"
            android:layout_width="0dip"
            android:layout_height="match_parent"
            android:layout_weight="1"
            iconStyle:style_icon="@drawable/icon_tab_one"
            iconStyle:style_text="@string/tab_message_text"
            iconStyle:style_text_size="12sp" />

        <com.tz.dream_10_21_viewpager_tab.IConStyleView
            android:id="@+id/icon_tongxunlu_view"
            android:layout_width="0dip"
            android:layout_height="match_parent"
            android:layout_weight="1"
            iconStyle:style_icon="@drawable/icon_tab_two"
            iconStyle:style_text="@string/tab_tongxunlu_text"
            iconStyle:style_text_size="12sp" />

        <com.tz.dream_10_21_viewpager_tab.IConStyleView
            android:id="@+id/icon_faxian_view"
            android:layout_width="0dip"
            android:layout_height="match_parent"
            android:layout_weight="1"
            iconStyle:style_icon="@drawable/icon_tab_threen"
            iconStyle:style_text="@string/tab_faxian_text"
            iconStyle:style_text_size="12sp" />

        <com.tz.dream_10_21_viewpager_tab.IConStyleView
            android:id="@+id/icon_wo_view"
            android:layout_width="0dip"
            android:layout_height="match_parent"
            android:layout_weight="1"
            iconStyle:style_icon="@drawable/icon_tab_fore"
            iconStyle:style_text="@string/tab_wo_text"
            iconStyle:style_text_size="12sp" />
    </LinearLayout>

</LinearLayout>
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.widget.LinearLayout;

public class MainActivity extends FragmentActivity {

	private String[] titles = { "微信主页", "微信通讯录", "微信发现", "微信我的" };

	private LinearLayout linearLayout;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initView();
	}

	private void initView() {
		linearLayout = (LinearLayout) findViewById(R.id.ll_tab);
		ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
		viewPager
				.setAdapter(new MyFragmentAdapter(getSupportFragmentManager()));
		viewPager.setOnPageChangeListener(new OnPageChangeListener() {

			@Override
			public void onPageSelected(int arg0) {

			}

			@Override
			public void onPageScrolled(int position, float positionOffset,
					int positionOffsetPixels) {
				if (positionOffset > 0) {
					IConStyleView left = (IConStyleView) linearLayout
							.getChildAt(position);
					IConStyleView right = (IConStyleView) linearLayout
							.getChildAt(position + 1);
					left.setMAlpha(1 - positionOffset);
					right.setMAlpha(positionOffset);
				}
			}

			@Override
			public void onPageScrollStateChanged(int arg0) {

			}
		});
	}

	public class MyFragmentAdapter extends FragmentPagerAdapter {

		public MyFragmentAdapter(FragmentManager fm) {
			super(fm);
		}

		@Override
		public Fragment getItem(int arg0) {
			TabFragment tabFragment = new TabFragment();
			Bundle args = new Bundle();
			args.putString("title", titles[arg0]);
			tabFragment.setArguments(args);
			return tabFragment;
		}

		@Override
		public int getCount() {
			return titles.length;
		}

	}

}

整理自教程




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值