高仿微信6.0Tab bar
来源:互联网 发布:守序中立 知乎 编辑:程序博客网 时间:2024/05/17 02:08
微信6.0版本的底部Tab Bar,切换图标变色的效果还不错,之前看过鸿洋大神的Android高仿微信6.0主界面,很是佩服。
不过我发现,真正微信6.0的切换图标变色的效果应该还不是鸿洋大神的那种方法,我们先看一下我做的效果图。
在这个Discover发现图标这里,那个指针部分是从灰色变成透明,而不是从灰色变成绿色。
所以从这里我可以判断微信6.0的这种切换图标效果应该不是用Paint的Xfermodes实现的,
Paint的Xfermodes是首先绘制一个绿色矩形的src,然后再在上面绘制dst图标,
设置Xfermodes为DST_IN,这样就会把src和dst相交的部分一起绘制出来,
也就是说上层的dst的图标被绘制出来了,同时底层的绿色矩形和图标相交的部分被绘制出来,
最后的结果就是图标的非透明部分都会变成绿色。
所以如果按照这种方法,Discover图标的指针部分就应该是从灰色变成绿色,而不是从灰色变成透明。
在这里我们换一个思路,能实现这种效果,其实思路也很简单,我都能写出来,各位看官肯定也不在话下。
就是这种图标转换的效果,其实就是两张形状一样的图片,但是颜色风格不同,叠在一起,
上层的图标设置自己的alpha透明度属性,下层的图标对应的把透明度设置成1 - alpha,
就可以做到两张图片渐变切换的效果。
话不多说,开始码代码:
先定义自定义View的属性,
<?xml version="1.0" encoding="utf-8"?><resources> <attr name="top_icon" format="reference" /> <attr name="bottom_icon" format="reference" /> <declare-styleable name="GradientIconView"> <attr name="top_icon" /> <attr name="bottom_icon" /> </declare-styleable> <attr name="text" format="string" /> <attr name="text_size" format="dimension" /> <attr name="top_text_color" format="color" /> <attr name="bottom_text_color" format="color" /> <declare-styleable name="GradientTextView"> <attr name="text" /> <attr name="text_size" /> <attr name="top_text_color" /> <attr name="bottom_text_color" /> </declare-styleable></resources>然后根据自定义属性,写代码实现它。
package com.david.wechatsample.gradientuilibrary;import android.content.Context;import android.content.res.TypedArray;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;import android.os.Bundle;import android.os.Parcelable;import android.util.AttributeSet;import android.view.LayoutInflater;import android.widget.FrameLayout;import android.widget.ImageView;/** * Created by David Wong on 2015/10/20. */public class GradientIconView extends FrameLayout { private ImageView mTopIconView; private ImageView mBottomIconView; private static final String INSTANCE_STATE = "instance_state"; private static final String STATE_ALPHA = "state_alpha"; private float mAlpha = 0f; public GradientIconView(Context context) { this(context, null, 0); } public GradientIconView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public GradientIconView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initView(context); // 获取设置的图标 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GradientIconView); BitmapDrawable drawable; int n = a.getIndexCount(); for (int i = 0; i < n; i++) { int attr = a.getIndex(i); if (attr == R.styleable.GradientIconView_top_icon) { drawable = (BitmapDrawable) a.getDrawable(attr); setTopIconView(drawable); } else if (attr == R.styleable.GradientIconView_bottom_icon) { drawable = (BitmapDrawable) a.getDrawable(attr); setBottomIconView(drawable); } } a.recycle(); setIconAlpha(mAlpha); } private void initView(Context context) { LayoutInflater.from(context).inflate(R.layout.gradient_icon_layout, this, true); mTopIconView = (ImageView) findViewById(R.id.top_icon_view); mBottomIconView = (ImageView) findViewById(R.id.bottom_icon_view); } public void setIconAlpha(float alpha) { mTopIconView.setAlpha(alpha); mBottomIconView.setAlpha(1 - alpha); this.mAlpha = alpha; } public void setTopIconView(Drawable drawable) { mTopIconView.setBackgroundDrawable(drawable); } public void setBottomIconView(Drawable drawable) { mBottomIconView.setBackgroundDrawable(drawable); } @Override protected Parcelable onSaveInstanceState() { Bundle bundle = new Bundle(); bundle.putParcelable(INSTANCE_STATE, super.onSaveInstanceState()); bundle.putFloat(STATE_ALPHA, mAlpha); return bundle; } @Override protected void onRestoreInstanceState(Parcelable state) { if (state instanceof Bundle) { Bundle bundle = (Bundle) state; mAlpha = bundle.getFloat(STATE_ALPHA); super.onRestoreInstanceState(bundle.getParcelable(INSTANCE_STATE)); } else { super.onRestoreInstanceState(state); } }}
代码中对应的layout文件如下,
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/bottom_icon_view" android:layout_width="match_parent" android:layout_height="match_parent" /> <ImageView android:id="@+id/top_icon_view" android:layout_width="match_parent" android:layout_height="match_parent" /></FrameLayout>在这里GradientIconView就写完了,代码没有多少行,很简单。
其实这里渐变效果的TextView也是同样的原理,实现代码和GradientIconView几乎差不多,这里就不贴代码了。
最后应该在主界面来测试代码效果了,激动人心啊!
package com.david.wechatsample.wechatsample;import android.net.Uri;import android.os.Bundle;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentActivity;import android.support.v4.app.FragmentPagerAdapter;import android.support.v4.view.ViewPager;import android.view.View;import com.david.wechatsample.fragment.AboutMeFragment;import com.david.wechatsample.fragment.ChatsFragment;import com.david.wechatsample.fragment.ContactsFragment;import com.david.wechatsample.fragment.DiscoverFragment;import com.david.wechatsample.fragment.OnFragmentInteractionListener;import com.david.wechatsample.gradientuilibrary.GradientIconView;import com.david.wechatsample.gradientuilibrary.GradientTextView;import java.util.ArrayList;import java.util.List;public class MainActivity extends FragmentActivity implements View.OnClickListener, ViewPager.OnPageChangeListener, OnFragmentInteractionListener { private ViewPager mViewPager; private List<Fragment> mTabs = new ArrayList<Fragment>(); private FragmentPagerAdapter mAdapter; private List<GradientIconView> mTabIconIndicator = new ArrayList<GradientIconView>(); private List<GradientTextView> mTabTextIndicator = new ArrayList<GradientTextView>(); private GradientIconView mChatsIconView; private GradientIconView mContactsIconView; private GradientIconView mDiscoverIconView; private GradientIconView mAboutMeIconView; private GradientTextView mTvChats; private GradientTextView mTvContacts; private GradientTextView mTvDiscover; private GradientTextView mTvAboutMe; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { mViewPager = (ViewPager) findViewById(R.id.id_viewpager); mChatsIconView = (GradientIconView) findViewById(R.id.id_iconfont_chat); mChatsIconView.setOnClickListener(this); mTabIconIndicator.add(mChatsIconView); mChatsIconView.setIconAlpha(1.0f); mContactsIconView = (GradientIconView) findViewById(R.id.id_iconfont_friend); mContactsIconView.setOnClickListener(this); mTabIconIndicator.add(mContactsIconView); mDiscoverIconView = (GradientIconView) findViewById(R.id.id_iconfont_faxian); mDiscoverIconView.setOnClickListener(this); mTabIconIndicator.add(mDiscoverIconView); mAboutMeIconView = (GradientIconView) findViewById(R.id.id_iconfont_me); mAboutMeIconView.setOnClickListener(this); mTabIconIndicator.add(mAboutMeIconView); mTvChats = (GradientTextView) findViewById(R.id.id_chats_tv); mTvChats.setOnClickListener(this); mTabTextIndicator.add(mTvChats); mTvChats.setTextViewAlpha(1.0f); mTvContacts = (GradientTextView) findViewById(R.id.id_contacts_tv); mTvContacts.setOnClickListener(this); mTabTextIndicator.add(mTvContacts); mTvDiscover = (GradientTextView) findViewById(R.id.id_discover_tv); mTvDiscover.setOnClickListener(this); mTabTextIndicator.add(mTvDiscover); mTvAboutMe = (GradientTextView) findViewById(R.id.id_about_me_tv); mTvAboutMe.setOnClickListener(this); mTabTextIndicator.add(mTvAboutMe); initFragments(); } private void initFragments() { mTabs.add(ChatsFragment.newInstance("", "")); mTabs.add(ContactsFragment.newInstance("", "")); mTabs.add(DiscoverFragment.newInstance("", "")); mTabs.add(AboutMeFragment.newInstance("", "")); mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) { @Override public int getCount() { return mTabs.size(); } @Override public Fragment getItem(int arg0) { return mTabs.get(arg0); } }; mViewPager.setAdapter(mAdapter); mViewPager.setOnPageChangeListener(this); } /** * 重置其他的Tab */ private void resetOtherTabs() { resetOtherTabIcons(); resetOtherTabText(); } /** * 重置其他的Tab icon */ private void resetOtherTabIcons() { for (int i = 0; i < mTabIconIndicator.size(); i++) { mTabIconIndicator.get(i).setIconAlpha(0); } } /** * 重置其他的Tab text */ private void resetOtherTabText() { for (int i = 0; i < mTabTextIndicator.size(); i++) { mTabTextIndicator.get(i).setTextViewAlpha(0); } } @Override public void onClick(View v) { resetOtherTabs(); switch (v.getId()) { case R.id.id_iconfont_chat: case R.id.id_chats_tv: mTabIconIndicator.get(0).setIconAlpha(1.0f); mTabTextIndicator.get(0).setTextViewAlpha(1.0f); mViewPager.setCurrentItem(0, false); break; case R.id.id_iconfont_friend: case R.id.id_contacts_tv: mTabIconIndicator.get(1).setIconAlpha(1.0f); mTabTextIndicator.get(1).setTextViewAlpha(1.0f); mViewPager.setCurrentItem(1, false); break; case R.id.id_iconfont_faxian: case R.id.id_discover_tv: mTabIconIndicator.get(2).setIconAlpha(1.0f); mTabTextIndicator.get(2).setTextViewAlpha(1.0f); mViewPager.setCurrentItem(2, false); break; case R.id.id_iconfont_me: case R.id.id_about_me_tv: mTabIconIndicator.get(3).setIconAlpha(1.0f); mTabTextIndicator.get(3).setTextViewAlpha(1.0f); mViewPager.setCurrentItem(3, false); break; } } @Override public void onFragmentInteraction(Uri uri) { } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { if (positionOffset > 0) { GradientIconView iconLeft = mTabIconIndicator.get(position); GradientIconView iconRight = mTabIconIndicator.get(position + 1); GradientTextView textLeft = mTabTextIndicator.get(position); GradientTextView textRight = mTabTextIndicator.get(position + 1); iconLeft.setIconAlpha(1 - positionOffset); textLeft.setTextViewAlpha(1 - positionOffset); iconRight.setIconAlpha(positionOffset); textRight.setTextViewAlpha(positionOffset); } } @Override public void onPageSelected(int position) { } @Override public void onPageScrollStateChanged(int state) { }}
写在最后,控件已上传至jcenter,在AndroidStudio引用如下:
dependencies { compile 'com.david.gradientuilib:gradientuilibrary:1.0.1'}
开源地址
https://github.com/wangdong20/AndroidGradientUI
- 高仿微信6.0Tab bar
- botoom tab + title bar
- Simple Tab-bar Controller
- 自定义tab bar控件
- Tab Bar Controllers
- navigation+tab bar
- UI-tab bar
- iOS之tab bar
- Tab Bar Item
- Navigation Bar Toolbal 和 Tab Bar区别
- 如何隐藏Tab Bar Controller的Tab Bar
- 自定义bottom tab + title bar
- 使用Tab Bar切换视图
- 使用Tab Bar切换视图
- 使用Tab Bar切换视图
- UITabBarController 隐藏 Bootom Tab Bar
- 使用Tab Bar切换视图
- 使用Tab Bar切换视图
- 字典排序法
- ng-repeat 在angularJS中用法
- 微信企业号开发相关问题
- OPenCV相机标定函数
- ART运行时垃圾收集(GC)过程分析
- 高仿微信6.0Tab bar
- Python 最大公约数
- setColorFilter滤镜效果
- 如何解决布局太长导致部分不显示,且解决键盘覆盖文本框的问题。
- hdu acm 1251 统计难题
- Linux 系统挂载数据盘
- LINUX 搭建sftp 服务器
- [并发并行]_[线程同步]_[C/C++实现单例模式分析]
- setting bundle的配置