android 微信布局 字体,【Android】底部Tab+ViewPager(仿微信界面)
感谢 github的作者:wuyexiong
效果图(图片和文字都有渐变效果)
实现
主要用到自定义一个LinearLayout和ImageView
1.BottomIconView继承自ImageView
BottomIconView的作用是现在Tab中的图标,有根据滑动的偏移值显示渐变的图标。
package jfsl.view.view;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.ImageView;
/**
* 底部Tab图标类,
* 分正常的状态和选中的状态
* 根据滑动的偏移量改变alpha值
* 然后显示出来
*
* 感谢 wuyexiong
* Created by wuyexiong on 4/25/15.
* Modify by JFSL on 2016-11-20 20:05
*/
public class BottomIconView extends ImageView
{
public static final int START_POSITION = 0;
public static final int ALPHA_MAX = 255;
//画笔
private Paint mPaint;
//选中时的图标
private Bitmap mIconSelected;
//未选中时的图标
private Bitmap mIconNormal;
//选中时的矩形(限制绘制范围)
private Rect mRectSelected;
//未选中时的矩形(限制绘制范围)
private Rect mRectNormal;
//当前的alpha值
private int mAlphaCurrent = 0;
public BottomIconView(Context context)
{
super(context);
}
public BottomIconView(Context context,AttributeSet attrs)
{
super(context,attrs);
}
public BottomIconView(Context context,AttributeSet attrs,int defStyleAttr)
{
super(context,attrs,defStyleAttr);
}
/**
* 初始化
*
* @param normal 正常图标的id
* @param selected 选中的图标的id
*/
public final void init(int normal,int selected) throws Exception
{
mIconNormal = createBitmap(normal);
mIconSelected = createBitmap(selected);
//创建不了图片
if(mIconNormal == null || mIconSelected == null)
throw new Exception("icon id can not create1 bitmap");
//根据创建的位图创建对应的矩形
mRectNormal = new Rect(START_POSITION,START_POSITION,mIconNormal.getWidth(),mIconNormal.getHeight());
mRectSelected = new Rect(START_POSITION,START_POSITION,mIconSelected.getWidth(),mIconSelected.getHeight());
//画笔只要实例化就行,没有什么要求
mPaint = new Paint(1);
}
/**
* 根据资源id创建的位图
*
* @param resId 资源id
* @return 创建的位图
*/
private Bitmap createBitmap(int resId)
{
return BitmapFactory.decodeResource(getResources(),resId);
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
//画笔为空,直接返回
if(mPaint == null)
return;
//设置当前选中图标的alpha值(逐渐减少)
mPaint.setAlpha(ALPHA_MAX - mAlphaCurrent);
canvas.drawBitmap(mIconNormal,null,mRectNormal,mPaint);
//设置目标图标的alpha值(逐渐减增大)
mPaint.setAlpha(mAlphaCurrent);
canvas.drawBitmap(mIconSelected,null,mRectSelected,mPaint);
}
/**
* 改变alpha值
*
* @param alpha
*/
public final void changeSelectedAlpha(int alpha)
{
mAlphaCurrent = alpha;
invalidate();
}
/**
* ViewPager切换时用到
*
* @param offset 偏移量
*/
public final void transformPage(float offset)
{
changeSelectedAlpha((int)(ALPHA_MAX * (1 - offset)));
}
}
2.底部Tab(BottomIndicator继承自LinearLayout)
package jfsl.view.view;
import android.animation.ArgbEvaluator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import jfsl.view.R;
/**
* 底部指示器
* Github上的例子,拿来修改了下
* Created by wuyexiong on 4/25/15.
* @version 1.0
* @aduthor JFSL
* @date 2016/11/14
*/
public class BottomIndicator extends LinearLayout
{
public static final int ICON_INDEX_NORMAL = 0;
public static final int ICON_INDEX_SELECTED = 1;
public static final int DEFALUT_SELECTED_ITEM = 0;
public static final String COLOR_TEXT_NORMAL = "#FF999999";
public static final String COLOR_TEXT_SELECTED = "#FF46C01B";
//文字颜色渐变类
private ArgbEvaluator mColorEvaluator;
//正常文本的颜色
private int mTextNormalColor;
//选中时文本的颜色
private int mTextSelectedColor;
//最后的位置
private int mLastPosition;
//选中的位置
private int mSelectedPosition;
//选择的偏移量
private float mSelectionOffset;
//底部tab文本
private String mTitles[] = {"微信","通讯录","发现","我"};
//对应的图标
private int mIconRes[][] = {
{R.drawable.icon_main_home_normal,R.drawable.icon_main_home_selected},
{R.drawable.icon_main_category_normal,R.drawable.icon_main_category_selected},
{R.drawable.icon_main_service_normal,R.drawable.icon_main_service_selected},
{R.drawable.icon_main_mine_normal,R.drawable.icon_main_mine_selected}};
//Item数组
private View[] mItemLayout;
//关联的ViewPager
private ViewPager mViewPager;
public BottomIndicator(Context context)
{
this(context,null);
}
public BottomIndicator(Context context,AttributeSet attrs)
{
this(context,attrs,0);
}
public BottomIndicator(Context context,AttributeSet attrs,int defStyleAttr)
{
super(context,attrs,defStyleAttr);
//初始化
init();
}
/**
* 初始化
*/
private void init()
{
//实例化颜色渐变类
mColorEvaluator = new ArgbEvaluator();
//选中和未选中的文本的颜色
mTextNormalColor = Color.parseColor(COLOR_TEXT_NORMAL);
mTextSelectedColor = Color.parseColor(COLOR_TEXT_SELECTED);
}
public void setViewPager(ViewPager viewPager)
{
//清空所有的view
removeAllViews();
mViewPager = viewPager;
//viewapger数据不为空
if(viewPager != null && viewPager.getAdapter() != null)
{
//设置监听
viewPager.addOnPageChangeListener(new ViewPagerListener());
try
{
populateTabLayout();
}catch(Exception e)
{
e.printStackTrace();
}
}
}
/**
* 生成底部tab
*/
private void populateTabLayout() throws Exception
{
final PagerAdapter adapter = mViewPager.getAdapter();
final OnClickListener tabClickListener = new TabClickListener();
//根据adapter中item 的数量生成数组
mItemLayout = new View[ adapter.getCount() ];
//遍历
for(int i = 0;i < adapter.getCount();i++)
{
final View tabView = LayoutInflater.from(getContext()).inflate(R.layout.item_bottom_tab,this,false);
//找不到对应的布局
if(tabView == null)
throw new IllegalStateException("tabView is null.");
mItemLayout[ i ] = tabView;
//图标
BottomIconView iconView = (BottomIconView)tabView.findViewById(R.id.bottom_tab_icon);
iconView.init(mIconRes[ i ][ ICON_INDEX_NORMAL ],mIconRes[ i ][ ICON_INDEX_SELECTED ]);
//文字
TextView textView = (TextView)tabView.findViewById(R.id.bottom_tab_text);
textView.setText(mTitles[ i ]);
//改变宽度和权重 item平分屏幕
LayoutParams lp = (LayoutParams)tabView.getLayoutParams();
lp.width = 0;
lp.weight = 1;
tabView.setOnClickListener(tabClickListener);
addView(tabView);
if(i == mViewPager.getCurrentItem())
{
iconView.transformPage(DEFALUT_SELECTED_ITEM);
tabView.setSelected(true);
textView.setTextColor(mTextSelectedColor);
}
}
}
/**
* 内部ViewPager监听
* 外面想监听,自定义一个
*/
private class ViewPagerListener implements ViewPager.OnPageChangeListener
{
//状态
private int mScrollState;
@Override
public void onPageScrolled(int position,float positionOffset,int positionOffsetPixels)
{
onViewPagerPageChanged(position,positionOffset);
}
@Override
public void onPageSelected(int position)
{
for(int i = 0;i < getChildCount();i++)
{
//图标
BottomIconView bottomIcon = ((BottomIconView)mItemLayout[ i ].findViewById(R.id.bottom_tab_icon));
bottomIcon.transformPage(position == i ? 0 : 1);
//文本
TextView bottomText = ((TextView)mItemLayout[ i ].findViewById(R.id.bottom_tab_text));
bottomText.setTextColor(position == i ? mTextSelectedColor : mTextNormalColor);
}
if(mScrollState == ViewPager.SCROLL_STATE_IDLE)
{
onViewPagerPageChanged(position,0f);
}
//设置选中项
for(int i = 0, size = getChildCount();i < size;i++)
{
getChildAt(i).setSelected(position == i);
}
}
@Override
public void onPageScrollStateChanged(int state)
{
mScrollState = state;
}
}
/**
* ViewPager的item改变
*
* @param position
* @param positionOffset
*/
private void onViewPagerPageChanged(int position,float positionOffset)
{
mSelectedPosition = position;
mSelectionOffset = positionOffset;
if(positionOffset == 0f && mLastPosition != mSelectedPosition)
{
mLastPosition = mSelectedPosition;
}
invalidate();
}
/**
* 绘制方法
*
* @param canvas
*/
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
final int childCount = getChildCount();
if(childCount > 0)
{
if(mSelectionOffset > 0f && mSelectedPosition < (getChildCount() - 1))
{
View selectedTab = getChildAt(mSelectedPosition);
View nextTab = getChildAt(mSelectedPosition + 1);
View selectedIconView = ((LinearLayout)selectedTab).getChildAt(0);
View nextIconView = ((LinearLayout)nextTab).getChildAt(0);
View selectedTextView = ((LinearLayout)selectedTab).getChildAt(1);
View nextTextView = ((LinearLayout)nextTab).getChildAt(1);
//draw icon alpha
if(selectedIconView instanceof BottomIconView && nextIconView instanceof BottomIconView)
{
((BottomIconView)selectedIconView).transformPage(mSelectionOffset);
((BottomIconView)nextIconView).transformPage(1 - mSelectionOffset);
}
/**
* 使用ArgbEvaluator类来控制文本的颜色渐变
*/
//draw text color
Integer selectedColor = (Integer)mColorEvaluator.evaluate(mSelectionOffset,
mTextSelectedColor,
mTextNormalColor);
Integer nextColor = (Integer)mColorEvaluator.evaluate(1 - mSelectionOffset,
mTextSelectedColor,
mTextNormalColor);
if(selectedTextView instanceof TextView && nextTextView instanceof TextView)
{
((TextView)selectedTextView).setTextColor(selectedColor);
((TextView)nextTextView).setTextColor(nextColor);
}
}
}
}
/**
* Tab的Item点击
*/
private class TabClickListener implements OnClickListener
{
@Override
public void onClick(View v)
{
for(int i = 0;i < getChildCount();i++)
{
if(v == getChildAt(i))
{
mViewPager.setCurrentItem(i,false);
return;
}
}
}
}
}
3.主布局(ViewPager+BottomIndicator)
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:id="@+id/id_viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
android:id="@+id/id_bottom_indicator"
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="@drawable/bg_tab_bottom">
4.tab item的布局(BottomIconView+TextView)
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="@null"
android:orientation="vertical">
android:id="@+id/bottom_tab_icon"
android:layout_width="32dp"
android:layout_height="28dp"
android:layout_gravity="center_horizontal"
android:scaleType="fitCenter" />
android:id="@+id/bottom_tab_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textSize="12sp" />
5.Tab的背景 layer-list可以将多个图片按照顺序层叠起来
背景不能去掉,去掉之后看不到渐变的效果
android:dither="true"
android:shape="rectangle">
android:dither="true"
android:shape="rectangle">
6.测试的Activity
package jfsl.view;
import android.os.Bundle;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import jfsl.view.adapter.TopViewPagerAdapter;
import jfsl.view.fragment.SimpleFragment;
import jfsl.view.view.BottomIndicator;
public class MainActivity extends AppCompatActivity
{
private ViewPager mViewPager;
private List mTitles = Arrays.asList("Fragment-->微信","Fragment-->通讯录","Fragment-->发现","Fragment-->我");
private List mFragments = new ArrayList<>();
private FragmentPagerAdapter mPagerAdapter;
private BottomIndicator mIndicator;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bottom_tab);
initViews();
initDatas();
initEvent();
}
private void initViews()
{
mViewPager = (ViewPager)findViewById(R.id.id_viewPager);
mIndicator = (BottomIndicator)findViewById(R.id.id_bottom_indicator);
}
private void initDatas()
{
for(String title : mTitles)
{
mFragments.add(SimpleFragment.newInstance(title));
}
mPagerAdapter = new TopViewPagerAdapter(getSupportFragmentManager(),this,mFragments);
mViewPager.setAdapter(mPagerAdapter);
mIndicator.setViewPager(mViewPager);
}
private void initEvent()
{
}
}
7.adapter(ViewPager的Adapter)
package jfsl.view.adapter;
import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import java.util.List;
import jfsl.view.fragment.SimpleFragment;
/**
* @version 1.0
* @aduthor JFSL
* @date 2016/11/12 0012
*/
public class TopViewPagerAdapter extends FragmentPagerAdapter
{
private Context mContext;
private List mFragments;
public TopViewPagerAdapter(FragmentManager fm,Context context,List fragments)
{
super(fm);
mContext = context;
mFragments = fragments;
}
@Override
public Fragment getItem(int position)
{
return mFragments.get(position);
}
@Override
public int getCount()
{
return mFragments.size();
}
}
8.创建Fragment(根据String创建一个简单的Fragment)
package jfsl.view.fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
/**测试用的Fragment
* @version 1.0
* @aduthor JFSL
* @date 2016/11/12 0012
*/
public class SimpleFragment extends Fragment
{
public static final String BUNDLE_TITLE = "title";
private String mTitle;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState)
{
Bundle bundle = getArguments();
if(bundle != null)
mTitle = bundle.getString(BUNDLE_TITLE);
TextView textView = new TextView(getActivity());
textView.setText(mTitle);
textView.setGravity(Gravity.CENTER);
return textView;
}
/**
* 获取实例
* @param title
* @return
*/
public static SimpleFragment newInstance(String title)
{
Bundle bundle = new Bundle();
bundle.putString(BUNDLE_TITLE,title);
SimpleFragment fragment = new SimpleFragment();
fragment.setArguments(bundle);
return fragment;
}
}
图标素材( 放在xxhdpi)
android 微信布局 字体,【Android】底部Tab+ViewPager(仿微信界面)相关推荐
- Android显示九宫图(自定义圆角,仿微信九宫格图)
详细解析Android显示九宫图(自定义圆角,仿微信九宫格图) 这是一个自定义九宫格图片框架,里面有设置圆角大小,还有当图片一张的时候控件自定义的大小,图片的间隔,四张图片的时候图片自定义为两行两列等 ...
- android源代码居中字体,Android (布局优化) TextView实现drawable图标大小 位置与第一行文本居中...
先看大众点评的购买须知 大众.png 如上图,需求在每条提示语句前加一个小圆点,我刚看到需求就想到用 android:drawableLeft 来做,可做完发现:当TextView内容为单行的时候是没 ...
- android 模仿微信布局,【Android初学者】框架布局:仿微信页面制作
学习Android有一段时间了,跟大家分享一下经验吧! 如果有错误的地方,有更好的方法,麻烦大家留言指导! 工具:studio2.2,虚拟机版本:4.3,API 18(感觉比5.1的稳定啊!) 例子是 ...
- android ui布局适配,Android适配全面总结(一)----屏幕适配
前言 Android适配是一个老生常谈的问题,很多程序员觉得很恶心,不愿意做适配,但是又不得不做.然后老板说,这位兄弟,做好了,今天晚饭给你加个鸡腿,然后程序员开始找各种资料,忙活起来了,最终在苦逼的 ...
- android相对布局代码,Android基础_3 Activity相对布局(示例代码)
相对布局要比前面讲的线性布局和表格布局要灵活一些,所以平常用得也是比较多的.相对布局控件的位置是与其周围控件的位置相关的,从名字可以看出来,这些位置都是相对的,确定出了其中一个控件的位置就可以确定另一 ...
- android百分比布局失效,Android 百分比布局库【原创】
为了解决android手机适配问题,我们经常想如果可以按照百分比的方式进行界面布局,这样适配各种屏幕就简单多了吧!现在谷歌正式提供百分比布局支持库(android-support-percent-li ...
- android 仿微信选取相册_Android--选择图片(仿微信发朋友圈)第一篇
这篇博客主要写仿微信朋友圈选择图片发朋友圈.整个功能包括加载图片,显示图片.相册文件夹.预览图片,九宫格显示已经选择好的图片等等,大概会有三篇博客. 效果图 看上面的图,加载图片肯定是异步加载,耗时任 ...
- android studio 布局嵌套,Android Studio实战 - 设计布局之嵌套布局
通过布局的嵌套可以创造出复杂的设计.如果想要美化之前的个人信息界面,可以采用 将 LinearLayout嵌入到RelativeLayout中的方法.这个布局包含一个在线状态标签和一 个描述字段. 单 ...
- android app替换字体,Android APP更换字体策略精要
前言 近期项目需要在我们的APP中使用指定的字体库.经过搜集资料,研读源码,和别人探讨请教,最终产出了一些比较好的方案.不敢专享,写成文章分享出来,希望对大家的实际开发工作有所帮助.喜欢探讨Andro ...
最新文章
- 解决IDEA中进行maven install报:系统资源不足的问题
- 支付宝 android 2.3,app被拒记录-2.3-包含支付宝
- 句句真研—每日长难句打卡Day13
- 2021年中国单索运动滑轮市场趋势报告、技术动态创新及2027年市场预测
- vue获取接口数据_c#中HttpWebRequest调用接口获取数据
- 【Tensorflow2.0】关于制作标签遇到的问题小结
- linux 登录直接进入系统,Linux登录和推出系统入门教程
- 《初识Scratch》教学设计
- 关于DNF的多媒体包NPK文件的那些事儿(9) - IMGV6
- Excel——公式与函数基础
- 帆软报表更新到服务器控件展示不出来_如何报表控件FineReport实现自定义附件处理...
- ecshop模板支持php,ecshop模板支持php数据运算的代码实例
- #51CTO学院四周年# 我和51cto的故事
- iOS 10诸如相机、相册、通讯录、麦克风、定位权限设置,防止奔溃或上架被拒
- 解决Android在更新安装包时出现“未安装应用”的情况
- linux TC命令使用总结
- Python:利用高德API获取公交路线并可视化
- k3 审核流程图_K3单据使用解释及流程图明细
- python一对小兔子一年后长大成大兔子;一对大兔子每半年生一对小兔子。大兔子的繁殖期为4年,兔子的寿命是6年。假定第一年年初投放了一对小兔子,试编程计算,第n年末(不考虑死亡情况)总共会有多少对兔子
- 【C进阶】第十篇——数据在内存中的存储