android高仿微信布局(二)

前言

这期我们讲讲怎么实现微信的左右滑动的效果和底部的tabs栏
废话不多说,开工吧!

首先我们先看看总体布局是怎么写的。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:hyman="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.poulwalker.demobar.AppBarActivity">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="微信"
            android:textColor="#ffffff"
            android:textSize="20sp"/>
    </android.support.v7.widget.Toolbar>



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

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



        <com.example.poulwalker.demobar.ChangeColorIconWithText
            android:id="@+id/id_indicator_one"
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            hyman:icon="@mipmap/ic_weixin"
            android:padding="5dp"
            hyman:text="微信"
            hyman:text_size="12sp"
            hyman:color="#3F51B5"/>

        <com.example.poulwalker.demobar.ChangeColorIconWithText
            android:id="@+id/id_indicator_two"
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            hyman:icon="@mipmap/ic_friend"
            android:padding="5dp"
            hyman:text="通信录"
            hyman:text_size="12sp"
            hyman:color="#3F51B5"/>

        <com.example.poulwalker.demobar.ChangeColorIconWithText
            android:id="@+id/id_indicator_three"
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            hyman:icon="@mipmap/ic_find"
            android:padding="5dp"
            hyman:text="发现"
            hyman:text_size="12sp"
            hyman:color="#3F51B5"/>

        <com.example.poulwalker.demobar.ChangeColorIconWithText
            android:id="@+id/id_indicator_four"
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            hyman:icon="@mipmap/ic_me"
            android:padding="5dp"
            hyman:text="我"
            hyman:text_size="12sp"
            hyman:color="#3F51B5"/>
    </LinearLayout>
</LinearLayout>

关于第一个控件toolbar,我们在第一期已经讲了。不懂的童鞋可以查看上期讲的内容。


根据布局我们可以看到有ViewPager、还有ChangeColorIconWithText。其中ChangeColorIconWithText是自己定义的。这个布局的效果是怎么样的呢?诸位打开自己的手机微信就能看到啦。


接下来我们要在代码里实现微信的左划右划和变色的功能。

ChangeColorIconWithText.java的实现

第一步定义。

    private int mColor = 0xFF45C01A;
    private Bitmap mIconBitmap;
    private String mText = "微信";
    private int mTextSize = (int) TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_SP, 12, getResources().getDisplayMetrics());

    private Canvas mCanvas;
    private Bitmap mBitmap;
    private Paint mPaint;

    private float mAlpha;

    private Rect mIconRect;
    private Rect mTextBound;
    private Paint mTextPaint;

    public ChangeColorIconWithText(Context context)
    {
        this(context, null);
    }

    public ChangeColorIconWithText(Context context, AttributeSet attrs)
    {
        this(context, attrs, 0);
    }

第二步获取自定义属性的值

/**
     * 获取自定义属性的值
     * 
     * @param context
     * @param attrs
     * @param defStyleAttr
     */
    public ChangeColorIconWithText(Context context, AttributeSet attrs,
                                   int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);

        TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.ChangeColorIconWithText);

        int n = a.getIndexCount();

        for (int i = 0; i < n; i++)
        {
            int attr = a.getIndex(i);
            switch (attr)
            {
            case R.styleable.ChangeColorIconWithText_icon:
                BitmapDrawable drawable = (BitmapDrawable) a.getDrawable(attr);
                mIconBitmap = drawable.getBitmap();
                break;
            case R.styleable.ChangeColorIconWithText_color:
                mColor = a.getColor(attr, 0xFF45C01A);
                break;
            case R.styleable.ChangeColorIconWithText_text:
                mText = a.getString(attr);
                break;
            case R.styleable.ChangeColorIconWithText_text_size:
                mTextSize = (int) a.getDimension(attr, TypedValue
                        .applyDimension(TypedValue.COMPLEX_UNIT_SP, 12,
                                getResources().getDisplayMetrics()));
                break;
            }

        }

        a.recycle();

        mTextBound = new Rect();
        mTextPaint = new Paint();
        mTextPaint.setTextSize(mTextSize);
        mTextPaint.setColor(0Xff555555);
        mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBound);

    }

第三步各函数的定义

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int iconWidth = Math.min(getMeasuredWidth() - getPaddingLeft()
                - getPaddingRight(), getMeasuredHeight() - getPaddingTop()
                - getPaddingBottom() - mTextBound.height());

        int left = getMeasuredWidth() / 2 - iconWidth / 2;
        int top = getMeasuredHeight() / 2 - (mTextBound.height() + iconWidth)
                / 2;
        mIconRect = new Rect(left, top, left + iconWidth, top + iconWidth);
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        canvas.drawBitmap(mIconBitmap, null, mIconRect, null);

        int alpha = (int) Math.ceil(255 * mAlpha);

        // 内存去准备mBitmap , setAlpha , 纯色 ,xfermode , 图标
        setupTargetBitmap(alpha);
        // 1、绘制原文本 ; 2、绘制变色的文本
        drawSourceText(canvas, alpha);
        drawTargetText(canvas, alpha);

        canvas.drawBitmap(mBitmap, 0, 0, null);

    }

    /**
     * 绘制变色的文本
     * 
     * @param canvas
     * @param alpha
     */
    private void drawTargetText(Canvas canvas, int alpha)
    {
        mTextPaint.setColor(mColor);
        mTextPaint.setAlpha(alpha);
        int x = getMeasuredWidth() / 2 - mTextBound.width() / 2;
        int y = mIconRect.bottom + mTextBound.height();
        canvas.drawText(mText, x, y, mTextPaint);

    }

    /**
     * 绘制原文本
     * 
     * @param canvas
     * @param alpha
     */
    private void drawSourceText(Canvas canvas, int alpha)
    {
        mTextPaint.setColor(0xff333333);
        mTextPaint.setAlpha(255 - alpha);
        int x = getMeasuredWidth() / 2 - mTextBound.width() / 2;
        int y = mIconRect.bottom + mTextBound.height();
        canvas.drawText(mText, x, y, mTextPaint);

    }

    /**
     * 在内存中绘制可变色的Icon
     */
    private void setupTargetBitmap(int alpha)
    {
        mBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(),
                Config.ARGB_8888);
        mCanvas = new Canvas(mBitmap);
        mPaint = new Paint();
        mPaint.setColor(mColor);
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setAlpha(alpha);
        mCanvas.drawRect(mIconRect, mPaint);
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        mPaint.setAlpha(255);
        mCanvas.drawBitmap(mIconBitmap, null, mIconRect, mPaint);
    }

    private static final String INSTANCE_STATUS = "instance_status";
    private static final String STATUS_ALPHA = "status_alpha";

    @Override
    protected Parcelable onSaveInstanceState()
    {
        Bundle bundle = new Bundle();
        bundle.putParcelable(INSTANCE_STATUS, super.onSaveInstanceState());
        bundle.putFloat(STATUS_ALPHA, mAlpha);
        return bundle;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state)
    {
        if (state instanceof Bundle)
        {
            Bundle bundle = (Bundle) state;
            mAlpha = bundle.getFloat(STATUS_ALPHA);
            super.onRestoreInstanceState(bundle.getParcelable(INSTANCE_STATUS));
            return;
        }
        super.onRestoreInstanceState(state);
    }

    public void setIconAlpha(float alpha)
    {
        this.mAlpha = alpha;
        invalidateView();
    }

    /**
     * 重绘
     */
    private void invalidateView()
    {
        if (Looper.getMainLooper() == Looper.myLooper())
        {
            invalidate();
        } else
        {
            postInvalidate();
        }
    }
TabFragment.java的实现
public class TabFragment extends Fragment
{
    private String mTitle = "Default";

    public static final String TITLE = "title";

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState)
    {
        if (getArguments() != null)
        {
            mTitle = getArguments().getString(TITLE);
        }

        TextView tv = new TextView(getActivity());
        tv.setTextSize(20);
        tv.setBackgroundColor(Color.parseColor("#ffffffff"));
        tv.setText(mTitle);
        tv.setGravity(Gravity.CENTER);
        return tv;

    }
}

接下来就是在主活动里调用了

public class AppBarActivity extends AppCompatActivity implements View.OnClickListener,ViewPager.OnPageChangeListener{}

第一步定义变量。

private ViewPager mViewPager;
    private List<Fragment> mTabs = new ArrayList<Fragment>();
    private String[] mTitles = new String[]
            { "First Fragment !", "Second Fragment !","Three Fragment !","four"};
    private FragmentPagerAdapter mAdapter;

    private List<ChangeColorIconWithText> mTabIndicators = new ArrayList<ChangeColorIconWithText>();

第二步,初始化所有事件

    /**
     * 初始化所有事件
     */
    private void initEvent()
    {

        mViewPager.setOnPageChangeListener(this);

    }


    private void initView()
    {
        mViewPager = (ViewPager) findViewById(R.id.id_viewpager);

        ChangeColorIconWithText one = (ChangeColorIconWithText) findViewById(R.id.id_indicator_one);
        mTabIndicators.add(one);
        ChangeColorIconWithText two = (ChangeColorIconWithText) findViewById(R.id.id_indicator_two);
        mTabIndicators.add(two);
        ChangeColorIconWithText three = (ChangeColorIconWithText) findViewById(R.id.id_indicator_three);
        mTabIndicators.add(three);
        ChangeColorIconWithText four = (ChangeColorIconWithText) findViewById(R.id.id_indicator_four);
        mTabIndicators.add(four);

        one.setOnClickListener(this);
        two.setOnClickListener(this);
        three.setOnClickListener(this);
        four.setOnClickListener(this);

        one.setIconAlpha(1.0f);

    }

左划右划的实现

private void initDatas()
    {
        for (String title : mTitles)
        {
            TabFragment tabFragment = new TabFragment();
            Bundle bundle = new Bundle();
            bundle.putString(TabFragment.TITLE, title);
            tabFragment.setArguments(bundle);
            mTabs.add(tabFragment);
        }


        mAdapter = new FragmentPagerAdapter(getSupportFragmentManager())
        {

            @Override
            public int getCount()
            {
                return mTabs.size();
            }

            @Override
            public Fragment getItem(int position)
            {
                return mTabs.get(position);
            }
        };
    }

点击事件及其余函数的实现

 @Override
    public void onClick(View v) {
        clickTab(v);

    }

    private void clickTab(View v) {
        resetOtherTabs();

        switch (v.getId())
        {
            case R.id.id_indicator_one:
                mTabIndicators.get(0).setIconAlpha(1.0f);
                mViewPager.setCurrentItem(0, false);
                break;
            case R.id.id_indicator_two:
                mTabIndicators.get(1).setIconAlpha(1.0f);
                mViewPager.setCurrentItem(1, false);
                break;
            case R.id.id_indicator_three:
                mTabIndicators.get(2).setIconAlpha(1.0f);
                mViewPager.setCurrentItem(2, false);
                break;
            case R.id.id_indicator_four:
                mTabIndicators.get(3).setIconAlpha(1.0f);
                mViewPager.setCurrentItem(3, false);
                break;
        }
    }

    private void resetOtherTabs() {
        for (int i = 0; i < mTabIndicators.size(); i++)
        {
            mTabIndicators.get(i).setIconAlpha(0);
        }
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        if (positionOffset > 0)
        {
            ChangeColorIconWithText left = mTabIndicators.get(position);
            ChangeColorIconWithText right = mTabIndicators.get(position + 1);
            left.setIconAlpha(1 - positionOffset);
            right.setIconAlpha(positionOffset);
        }

    }

    @Override
    public void onPageSelected(int position) {

    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }

最后在onCreate方法里再初始化一遍

        initView();
        initDatas();
        mViewPager.setAdapter(mAdapter);
        initEvent();

授人以鱼不如授人以渔,这里我就不发布整个工程了,剩下的事情留给大家慢慢去发挥吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值