美文网首页Android工程师Android待集成
Android引导页根据滑动渐变背景色(一)

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

作者: centerzx | 来源:发表于2016-07-13 11:41 被阅读6122次

    下面的知识点呢,是自己第一次做这个效果,记录下知识,不知道有没有更好的实现方法。
    文章二------改进版
    在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以上运行效果!

    相关文章

      网友评论

      • centerzx:修正个问题:
        int colorBg[] = getResources().getIntArray(R.array.splash_bg);
        ColorShades shades = new ColorShades();
        把viewpager监听里面的这两个东西提出去,进行优化下,避免重复获取和new。
      • centerzx:遗漏了主题的代码:
        API为19及以上设置为:
        (1)已贴出的acyivity代码那样,配置的是大于等于19
        (2) style里面配置主题的话:
        API为19:
        <item name="android:windowTranslucentStatus">true</item>
        <!--透明导航栏-->
        <item name="android:windowTranslucentNavigation">true</item>
        API为21及以上:
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:statusBarColor">@android:color/transparent</item>

        其他,如果要API更低的情况下好看些:
        <!--无导航栏 -->
        <item name="windowActionBar">false</item>
        <!--无标题栏 -->
        <item name="windowNoTitle">true</item>
        <!--全屏-->
        <item name="android:windowFullscreen">true</item>

        以上这样设置了后,比如在API为17的时候,就是全屏的,整个也是一个颜色,就比较好看了。

        感谢大家指出!
      • soaringEveryday:你的代码会导致stackOverFlow,Adapter的instantiateItem方法中,你已经执行了container.addView(itemLayout),所以你创建这个itemLayout的时候,不应该再靠在container上了。
        View itemLayout = getLayoutInflater().inflate(R.layout.layout_app_intro, container, false);这句应该改成
        View itemLayout = getLayoutInflater().inflate(R.layout.layout_app_intro, null, false);
        centerzx:@soaringEveryday 源码是这样的:
        if (root != null && attachToRoot) {
        root.addView(temp, params);
        }
        if (root == null || !attachToRoot) {
        result = temp;
        }
        attachToRoot就是那个boolean值。
        :clap: 感谢指出
        centerzx:@r17171709 恩,对的!
        皮球二二:@soaringEveryday 最后一个参数是false表示没有靠在上面
      • NKming:状态栏的话,
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
        设置为透明色就可以自适应颜色的变化就可以了吧?
        centerzx:@NKming 对了,多谢哥们提醒,你不支持主题我都忘了,还有这个代码没贴出来。 :smiley: :clap:
      • 23375930c51d:好看, :smile:
        centerzx:@whiyc :smiley: 谢谢
      • 洋葱cy:不错 挺好看 给个Demo把 :smile:
        centerzx:@洋葱cy 不好意思,这个是我写在我的一个专门写demo的例子里面的,没分出来。不过代码很详细了。 :smiley:
      • 狸小华:博主可以考虑下使用 ArgbEvaluator 这样子比较优雅 :stuck_out_tongue_closed_eyes:
        centerzx:@狸小华 :clap: :clap: 恩~好!欢迎提建议!
      • 捡淑:mark
        centerzx:@捡淑 :relaxed:
      • 薄炳鑫:不错啊
        centerzx:@薄炳鑫 谢谢支持! :smiley:

      本文标题:Android引导页根据滑动渐变背景色(一)

      本文链接:https://www.haomeiwen.com/subject/irmsjttx.html