Android 引导页根据滑动切换逐渐改变背景色

6,167 阅读6分钟
原文链接: www.jianshu.com

下面的知识点呢,是自己第一次做这个效果,记录下知识,不知道有没有更好的实现方法。

在Android项目中有些引导页上面是一些小图组合成的,背景颜色是纯色的,每一张颜色不同,这种情况呢,导致在滑动展示引导页的时候,切换效果的颜色变化感觉很生硬。本文讲解实现根据滑动逐渐改变背景颜色的一个效果。
先看看效果图,如下:


效果展示图


1、主要依赖:
compile'com.android.support:support-v4:23.4.0'
compile'com.readystatesoftware.systembartint:systembartint:1.0.4'
第一个呢大家比较熟悉,就不多说了(确实不知道的呢,俺也莫法了,找度娘或者姑姑吧,哈哈);第二个呢,主要是沉浸式状态栏的一个运用依赖,是状态栏颜色也跟着变化,看着就更舒服了,对吧!版本号的话就只有大家根据官方的自己更新了。下面贴出这个状态栏依赖的官方地址与介绍,大家可以看看:
Maven中央仓库
github代码地址

2、代码部分
代码实现呢,用的东西很简单。

1、布局文件,也就是ViewPager的使用。xml代码如下:

 

   

    
    
    
    
    
    
    

其中注释部分是自定义添加的指示器,可以是数字、小圆圈。

2、资源文件代码,我是写在数组文件arrays.xml:
    
       
          
                第一次写博客
                觉得行,来个肯定吧
                有不好的地方欢迎大神指点 
                记得分享哟
          
          
                  @mipmap/splash_iv_first
                  @mipmap/splash_iv_second
                  @mipmap/splash_iv_third 
                  @mipmap/splash_iv_forth
        
         
                @color/light_green_500
                @color/amber_500
                @color/red_400
                @color/blue_500
          
      

第一个是每一个页面的一些文字;第二个是一些图片、图标;第三个是背景颜色。这些呢都是ViewPager每页所需要的内容,大家可以根据自己的需求修改。(当然demo的话也可以不要这些内容,只需要纯色的背景只是为了好看些,哈哈)。

3、ViewPager的布局,xml如下:
      
                  
                  
                           
                          
                
        

立即开启按钮可以先进行隐藏,最后一页的时候在显示。

4、主要实现代码:

怎么创建页面、mainfest怎么引用activity、怎么引用控件等基础操作在这就不说了。(后贴出全部代码)
1、首先得到要设置背景颜色的根布局控件:

 mRootLayout = (RelativeLayout)findViewById(R.id.rl_root);

2、然后就是ViewPager的使用,得给它设置PagerAdapter:

 private class IntroPager extends PagerAdapter
  {
    private String[] mDescs;
    private TypedArray mIcons;
    public IntroPager(int icoImage, int des)
    {
        mDescs = getResources().getStringArray(des);
        mIcons = getResources().obtainTypedArray(icoImage);
    }

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

    @Override
    public boolean isViewFromObject(View view, Object object)
    {
        return view == object;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position)
    {
        View itemLayout = getLayoutInflater().inflate(R.layout.layout_app_intro, container, false);
        ImageView mImage = (ImageView)itemLayout.findViewById(R.id.iv_img);
        TextView mTextView = (TextView)itemLayout.findViewById(R.id.tv_desc);
        Button mButton = (Button)itemLayout.findViewById(R.id.btn_launch);
        mImage.setImageResource(mIcons.getResourceId(position, 0));
        mTextView.setText(mDescs[position]);
        if (position == getCount() - 1)
        {
            mButton.setVisibility(View.VISIBLE);
        }
        else
        {
            mButton.setVisibility(View.GONE);
        }
        container.addView(itemLayout);
        return itemLayout;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object)
    {
        container.removeView((View)object);
    }
}

代码嘛,就不多说,比较简单。重点就是构造方法,的一个资源文件的引用。
3、ViewPager添加滑动监听:
滑动监听的代码是这次的重点,以前用的setOnPageChangeListener,不过已经废除了,得用addOnPageChangeListener,然后实现里面的onPageScrolled方法。如下:

mViewPager.addOnPageChangeListener(new     ViewPager.OnPageChangeListener()
    {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
        {
            int colorBg[] = getResources().getIntArray(R.array.splash_bg);
            ColorShades shades = new ColorShades();
            shades.setFromColor(colorBg[position % colorBg.length])
                .setToColor(colorBg[(position + 1) % colorBg.length])
                .setShade(positionOffset);
            mRootLayout.setBackgroundColor(shades.generate());
            applySelectedColor(shades.generate());
        }
        @Override
        public void onPageSelected(int position)
        {   
        }
        @Override
        public void onPageScrollStateChanged(int state)
        {
        }
    });

大家都看到了,重点就是ColorShades 和onPageScrolled里面的一个参数结合使用。
(1)先看看onPageScrolled的参数:
position:在非第一页与最后一页时,滑动到下一页,position为当前页位置;滑动到上一页,position为当前页-1。
positionOffset :滑动到下一页,[0,1)区间上变化;滑动到上一页:(1,0]区间上变化。
positionOffsetPixels:这个和positionOffset很像,滑动到下一页,[0,宽度)区间上变化;滑动到上一页:(宽度,0]区间上变化。
第一页时:滑动到上一页position=0 ,其他基本为0 ;最后一页滑动到下一页 position为当前页位置,其他两个参数为0。
由此发现,positionOffset很适合作为,渐变,缩放的控制参数;positionOffsetPixels则可以作为平移等的控制参数。
那么positionOffset就能用来实现滑动切换时背景颜色进行渐变切换。
(2)ColorShades :
主要实现了从哪个颜色变化到哪个颜色,以及引用positionOffset进行控制颜色的渐变,返回RGB组合成的一个新颜色值,我们设置这个颜色值就可以了。代码如下:

    /**
     * Source from :
     https://gist.github.com/cooltechworks/4f37021b1216f773daf8
     * Color shades will provide all the intermediate colors between two colors. It just requires a decimal value between
     * 0.0 to 1.0
     * and it provides the exact shade combination of the two color with this shade value.
     * Textual explanation :
     * 
     * White          LtGray          Gray            DkGray           Black
     * 0               0.25            0.5             0.75            1
     * Given two colors as White and Black,and shade
     * as 0    gives White
     * as 0.25 gives Light gray
     * as 0.5  gives Gray
     * as 0.75 gives Dark gray
     * as 1    gives Black.
     */
    public class ColorShades
    {

        private int mFromColor;
        private int mToColor;
        private float mShade;
        public ColorShades setFromColor(int fromColor)
        {
            this.mFromColor = fromColor;
            return this;
        }

public ColorShades setToColor(int toColor)
{
    this.mToColor = toColor;
    return this;
}

public ColorShades setFromColor(String fromColor)
{

    this.mFromColor = Color.parseColor(fromColor);
    return this;
}

public ColorShades setToColor(String toColor)
{
    this.mToColor = Color.parseColor(toColor);
    return this;
}

public ColorShades forLightShade(int color)
{
    setFromColor(Color.WHITE);
    setToColor(color);
    return this;
}

public ColorShades forDarkShare(int color)
{
    setFromColor(color);
    setToColor(Color.BLACK);
    return this;
}

public ColorShades setShade(float shade)
{
    this.mShade = shade;
    return this;
}

/**
 * Generates the shade for the given color.
 *
 * @return the int value of the shade.
 */
public int generate()
{
    int fromR = Color.red(mFromColor);
    int fromG = Color.green(mFromColor);
    int fromB = Color.blue(mFromColor);

    int toR = Color.red(mToColor);
    int toG = Color.green(mToColor);
    int toB = Color.blue(mToColor);

    int diffR = toR - fromR;
    int diffG = toG - fromG;
    int diffB = toB - fromB;

    int red = fromR + (int)((diffR * mShade));
    int green = fromG + (int)((diffG * mShade));
    int blue = fromB + (int)((diffB * mShade));

    return Color.rgb(red, green, blue);
}

/**
 * Assumes the from and to color are inverted before generating the shade.
 * @return the int value of the inverted shade.
 */
public int generateInverted()
{
    int fromR = Color.red(mFromColor);
    int fromG = Color.green(mFromColor);
    int fromB = Color.blue(mFromColor);

    int toR = Color.red(mToColor);
    int toG = Color.green(mToColor);
    int toB = Color.blue(mToColor);

    int diffR = toR - fromR;
    int diffG = toG - fromG;
    int diffB = toB - fromB;

    int red = toR - (int)((diffR * mShade));
    int green = toG - (int)((diffG * mShade));
    int blue = toB - (int)((diffB * mShade));
    return Color.rgb(red, green, blue);
}

/**
 * Gets the String equivalent of the generated shade
 * @return String value of the shade
 */
public String generateInvertedString()
{
    return String.format("#%06X", 0xFFFFFF & generateInverted());
}

/**
 * Gets the inverted String equivalent of the generated shade
 * @return String value of the shade
 */
public String generateString()
{
    return String.format("#%06X", 0xFFFFFF & generate());
}
    }

这个是人家造的轮子,源码地址呢也在注释里面。小伙伴可以去看看大牛写的。然后给设置背景颜色:

mRootLayout.setBackgroundColor(shades.generate());

这样呢也就基本完成了滑动渐变背景色的功能,但是这个看起不爽,状态栏的颜色要是也跟着变化,整个屏幕都是一个颜色,更好看了。然后我们就运用到了前面说的第二个依赖包来设置状态栏颜色。怎么使用呢,可以参考前面给出的作者代码地址,然后我也贴出我实现的代码。主要是onCreate方法里面:

   @Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
    {
        //透明状态栏
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        //透明导航栏
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
    }
    setContentView(R.layout.activity_app_intro);
    mTintManager = new SystemBarTintManager(this);
    mTintManager.setStatusBarTintEnabled(true);
    mTintManager.setNavigationBarTintEnabled(true);
    applySelectedColor(R.color.light_green_500);//这里给他设置第一个页面的颜色值
    init();
}

//设置状态栏颜色,在onPageScrolled里进行背景颜色一样的设置值。
private void applySelectedColor(int color)
{
    mTintManager.setTintColor(color);
}

好了代码基本大概就是这样,然后出来的效果呢,就是展示图那样。
第一次写文章,望大家给出宝贵建议,以及不当之处请斧正,有更好的实现方法,大家也可以联系呀,嘿嘿,大家共同学习。感谢大家!么么哒!
哦,对了,5.0以上运行效果!