zoukankan      html  css  js  c++  java
  • 他们控制的定义--让背景颜色变化ViewPager逐步幻灯片

    转载请注明出处。谢谢~

    今天想说一个简单但很好的效果达到。代码是绝对简单,达到绝对easy,就是你可能想不到而已。

    不多说,上效果图。

    第一个效果是仿最美应用的滑动颜色变化,第二个是我项目中要用的效果,实现后我就贴出来了,开源嘛。

                 

    以下分别说说这两个实现的原理和想法。


    首先我们看纯色的第一张gif,纯色的渐变还是easy一些的。

    1.实现一个ViewPager,由于我们要实现的是,随着手指的移动,viewpager的背景色改变,所以临时的想法是,不须要自己定义viewpager。

    2.给背景设置一个纯色的color。

    3.viewpager的滑动,怎样获取,怎样处理

    4.怎样让颜色渐变,怎么获取渐变值


    以下我们一个一个的解决。

    1.使用viewpager貌似是非常easy的,这里不复述了,代码我贴上:

    <LinearLayout 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"
        android:padding="20dp"
        android:id="@+id/ll"
        android:orientation="vertical" >
    
        <TextView
            android:padding="10dp"
            android:layout_width="match_parent"
            android:gravity="center_horizontal"
            android:layout_height="wrap_content"
            android:textColor="#ff000000"
            android:text="这是title" />
        
        <android.support.v4.view.ViewPager
            android:id="@+id/viewpager"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >
        </android.support.v4.view.ViewPager>
    </LinearLayout>

    @Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		llLayout = (LinearLayout) findViewById(R.id.ll);
    		viewpager = (ViewPager) findViewById(R.id.viewpager);
    		fragment = new ImageFragment();
    		fragment2 = new ImageFragment();
    		fragment3 = new ImageFragment();
    		fragment4 = new ImageFragment();
    		views.add(fragment2);
    		views.add(fragment3);
    		views.add(fragment4);
    		views.add(fragment);
    		viewpager.setAdapter(new MyAdapter(getSupportFragmentManager()));
    		viewpager.setCurrentItem(0);
    		viewpager.setOnPageChangeListener(new PageChangeLisener());
    	}

    private class MyAdapter extends FragmentPagerAdapter{
    
    		private List<Fragment> list_views;
    
    		public MyAdapter(FragmentManager fm) {
    			super(fm);
    			list_views = views;
    		}
    
    		@Override
    		public Fragment getItem(int arg0) {
    			return list_views.get(arg0);
    		}
    
    		@Override
    		public int getCount() {
    			return list_views.size();
    		}
    		
    	}

    以上是关于viewpager的一些代码,没有贴全,像是ImageFragment就特别简单,布局里就是一张图片而已。

    以下第二个问题,背景色我们非常easy搞定,setBackgroundColor就能够。

    然后看第三个问题,并非全部的滑动处理都要在onTouch里进行,像viewpager,我们全然能够看它的listener

    class PageChangeLisener implements OnPageChangeListener {
    
    		@Override
    		public void onPageScrollStateChanged(int arg0) {
    		}
    
    		@SuppressLint("NewApi")
    		@Override
    		public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    			ArgbEvaluator evaluator = new ArgbEvaluator();
    			if (position % 2 == 0) {
    				llLayout.setBackgroundColor(0XFF8080FF);
    				int evaluate = (Integer) evaluator.evaluate(positionOffset, 0XFF8080FF,0XFFFF8080);
    				llLayout.setBackgroundColor(evaluate);
    			}else {
    				llLayout.setBackgroundColor(0XFFFF8080);
    				int evaluate = (Integer) evaluator.evaluate(positionOffset, 0XFFFF8080,0XFF8080FF);
    				llLayout.setBackgroundColor(evaluate);
    			}
    		}
    
    		@Override
    		public void onPageSelected(int arg0) {
    		}
    	}

    这是整个颜色控制的核心。先说第三个问题。这里用onPageChangeListener来处理了viewpager的滑动,这里尽管拿不到坐标。可是能够拿到一些对我们来说,非常实用的东西,看onPageScrolled方法的第二个參数,这里做实验发现,它向右滑动的时候,取值是[0,1),而向左滑动的时候,取值的(1,0],这全然就是为了让开发人员做缩放平移等动画的小助手啊!

    然后。注意了,我们考虑第四个问题,我不知道大家是否熟悉属性动画,我首先是在属性动画里写了一个对backgroundColor属性设置改变的一个动画:

    @SuppressLint("NewApi")
    	private void setBackRepeat(View view,String property,int from , int to){
    		ValueAnimator animator = ObjectAnimator.ofInt(view,property,from,to);
    		animator.setDuration(2000);
    		animator.setRepeatMode(ValueAnimator.REVERSE);
    		animator.setRepeatCount(ValueAnimator.INFINITE);
    		animator.setEvaluator(new ArgbEvaluator());
    		animator.start();
    		
    		
    		animator.addUpdateListener(new AnimatorUpdateListener() {
    			
    			@Override
    			public void onAnimationUpdate(ValueAnimator animation) {
    				// TODO Auto-generated method stub
    				System.out.println("value : "+Integer.toHexString((Integer)animation.getAnimatedValue()));
    			}
    		});
    	}

    然后我打印了动画运行时的颜色的变化,然后我发现他竟然会渐变成为你想要的颜色,而不是刷的一下就变了,这下,开心了。

    把这个属性动画里的颜色估值器拿出来,ArgbEvaluator。就是它!它的实现特别简单,大家能够点进去看看源代码,然后用这个估值器我们来做估值。

    首先说说这几个參数。

    evaluator.evaluate(positionOffset, 0XFF8080FF,0XFFFF8080);
    估值器new出来之后,进行估值。第一个參数是0-1的一个可变參数,0表示開始变化。1表示变化结束,第二个參数是開始的颜色值,第三个參数是结束的颜色值。而这种方法就会一直返回一个在0-1之间过度的颜色值,直到颜色变化完为止。

    这样我们就全然能够试想上述效果了!


    接着,我们来实现第二个效果!就是在背景色渐变的基础上,再加上滑动渐变!

    我们细致看第二个效果,发现viewpager后面的背景色。原本就是从左上角到右下角渐变的,然后滑动过程中,颜色继续随手指渐变。滑动结束后,左上角和右下角的颜色互换了位置,中间还是渐变色。

    是不是比第一个效果瞬间又提升了bigger!

    我们再来实现一下它。


    考虑问题:

    1.背景色渐变的实现方式?

    2.viewpager是否须要自己定义?

    3.滑动事件的获取?

    4.渐变的处理?


    我们逐个解决。

    第一个,背景渐变,大家熟知的shape,对,一開始我也想到了它,并且想到了属性动画,对backgroundResource的设置,可是非常遗憾。背景色没有渐变效果,所以放弃。然后背景色的实现,我简单的自己定义了一个view。让这个view做viewpager的背景,来随手指渐变。

    第二个,viewpager没有自己定义。由于viewpager上没有特别复杂的效果。没有特别绚丽的切换(你全然能够自己加上。github有开源的)。所以我没有自己定义。

    第三个,滑动事件的处理仍然延用了上一个效果的listenr,全然无法舍弃第二个參数offset这个从0-1的小baby啊!

    第四个,单纯的颜色估值器无法满足我们的需求。但结合上我们自己定义的view就能实现双渐变效果了!

    public class MyLinearLayout extends View {
    	
    	private LinearGradient gradinet;
    	private Paint paint;
    	private int width;
    	private int height;
    	private int start = 0XFFFF8080;
    	private int end = 0XFF8080FF;
    	
    	public MyLinearLayout(Context context) {
    		super(context);
    		getDisplay(context);
    	}
    
    	public MyLinearLayout(Context context, AttributeSet attrs) {
    		super(context, attrs);
    		getDisplay(context);
    	}
    	
    	private void getDisplay(Context context) {
    		WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
    		width = wm.getDefaultDisplay().getWidth();
    		height = wm.getDefaultDisplay().getHeight();
    	}
    	
    	public void setGradient(int start,int end){
    		this.start = start;
    		this.end = end;
    		gradinet = new LinearGradient(0, 0, width, height, start, end, Shader.TileMode.MIRROR);
    		invalidate();
    	}
    	
    	@Override
    	protected void onDraw(Canvas canvas) {
    		super.onDraw(canvas);
    		System.out.println("!!!!!!!!!!!!!!!!");
    		if (paint == null) {
    			paint = new Paint();
    		}
    		if (gradinet == null) {
    			gradinet = new LinearGradient(0, 0, width, height, start, end, Shader.TileMode.MIRROR);
    		}
    		paint.setShader(gradinet);
    		canvas.drawRect(0, 0, width	, height, paint);
    	}
    
    }

    核心。。就是这么个简单但重要的自己定义控件,里面用LinearGradient实现了渐变,在加上估值器。一个双渐变效果就这么出来了!

    开源!!

    这个项目的代码我提交到github上,我衷心而且恳切的希望能有人把viewpager的切换效果也增加到这个项目中,向我发出合并申请。谢谢。

    还得提一句。一直想写一系列关于Android动画的博客。可是一直抽不出太多时间(短时间无法写完),demo我已经写完了。所以关于这部分以后博客肯定会有。莫急莫急。

    控制github下载链接

    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    hive数据类型
    hive类型转化错误,会错误提示指定分区参数
    [ORACLE]java.sql.SQLRecoverableException: IO Error: Connection rese
    oracle start with connect by prior 递归查询用法
    redis参数改进建议
    Android Studio教程--从Github 下载一个Repository
    Android Studio教程--Android项目分享到Github
    Android Studio Gradle Build Running 特别慢的问题探讨
    The Genymotion Virtual device could not obtain an IP address解决办法
    Android Studio教程--给Android Studio安装Genymotion插件
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4792191.html
Copyright © 2011-2022 走看看