Android引导页根据滑动渐变背景色(一)

下面的知识点呢,是自己第一次做这个效果,记录下知识,不知道有没有更好的实现方法。
文章二------改进版
在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代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 
 android:id="@+id/rl_root"
 xmlns:android="http://schemas.android.com/apk/res/android" 
 xmlns:tools="http://schemas.android.com/tools" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent"  
 tools:context=".activity.AppIntroActivity"> 

   <android.support.v4.view.ViewPager
       android:id="@+id/viewpager"
       android:layout_width="match_parent"
       android:layout_height="match_parent"/>

    <!--<com.center.mycode.view.CirclePageIndicator-->
    <!--android:id="@+id/indicator"-->
    <!--android:layout_width="wrap_content"-->
    <!--android:layout_height="wrap_content"-->
    <!--android:layout_alignParentBottom="true"-->
    <!--android:layout_centerHorizontal="true"-->
    <!--android:layout_marginBottom="15dp"/>-->

</RelativeLayout>

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

2、资源文件代码,我是写在数组文件arrays.xml:
    <?xml version="1.0" encoding="utf-8"?>
       <resources>
          <string-array name="splash_desc">
                <item>第一次写博客</item>
                <item>觉得行,来个肯定吧</item>
                <item>有不好的地方欢迎大神指点</item> 
                <item>记得分享哟</item>
          </string-array>
          <array name="splash_icon">
                  <item>@mipmap/splash_iv_first</item>
                  <item>@mipmap/splash_iv_second</item>
                  <item>@mipmap/splash_iv_third</item> 
                  <item>@mipmap/splash_iv_forth</item>
        </array>
         <array name="splash_bg">
                <item>@color/light_green_500</item>
                <item>@color/amber_500</item>
                <item>@color/red_400</item>
                <item>@color/blue_500</item>
          </array>
      </resources>

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

3、ViewPager的布局,xml如下:
      <LinearLayout 
             xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width="match_parent" 
             android:layout_height="match_parent"
             android:orientation="vertical"    >
                  <ImageView
                      android:id="@+id/iv_img"
                      android:layout_width="wrap_content"
                      android:layout_height="0dp"
                      android:layout_gravity="center_horizontal"
                      android:layout_weight="2"
                      android:scaleType="fitEnd" 
                      android:src="@mipmap/splash_iv_first"/>
                  <RelativeLayout
                      android:layout_width="match_parent"
                      android:layout_height="0dp"
                      android:layout_weight="1">
                           <TextView
                                android:id="@+id/tv_desc" 
                                android:layout_width="wrap_content" 
                                android:layout_height="wrap_content"
                                android:layout_centerHorizontal="true"
                                android:layout_marginTop="10dp"
                                android:gravity="center_horizontal"
                                android:textColor="@color/white"
                                android:textSize="18sp"/>
                          <Button
                                  android:id="@+id/btn_launch"
                                  android:layout_width="wrap_content"
                                  android:layout_height="36dp" 
                                  android:layout_centerInParent="true"
                                  android:background="@color/grey_500"
                                  android:onClick="goToMain"
                                  android:text="立即开启"
                                  android:textColor="@color/white"
                                  android:textSize="18sp"/>
                </RelativeLayout>
        </LinearLayout>

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

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方法。如下:

shades = new ColorShades();
colorBg = getResources().getIntArray(R.array.splash_bg);
mRootLayout = (RelativeLayout)findViewById(R.id.rl_root);
mViewPager = (ViewPager)findViewById(R.id.viewpager);
IntroPager introPager = new IntroPager(R.array.splash_icon, R.array.splash_desc);
mViewPager.setAdapter(introPager);
mViewPager.addOnPageChangeListener(new     ViewPager.OnPageChangeListener()
    {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
        {
            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以上运行效果!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容