2014-01-28 1 views
9

Я хочу анимировать центр линейного градиента, так что вначале весь drawable является цветом1, а в конце весь drawable color2 и между центром градиента перемещается слева направо.LinearGradient Center Animation

GradientDrawable gd = new GradientDrawable(
           GradientDrawable.Orientation.LEFT_RIGHT, 
           new int[] {color1, color2}); 
gd.setCornerRadius(0f); 
gd.setGradientCenter(x, 0); 
view.setBackgroundDrawable(gd); 

Проблема в том, что setGradientCenter не имеет никакого значения. В соответствии с этим ответом https://stackoverflow.com/a/14383974/1395697 есть проблема с setGradientCenter(), но решение в этом ответе не работает для меня, потому что я изменяю градиент в onTouch(), когда пользователь пальцем перебирает вид, поэтому он должен быть действительно быстро.

Есть ли способ сделать это?

Я хочу сделать что-то вроде этого (все сенсорный материал отлично работает, но не анимированный градиент):

enter image description here

+0

Как анимация экрана блокировки cyanogenmod http://svij.org/graphics/android-lockscreen_cyanogenmod.png? Пожалуйста, не префикс заголовков вашего вопроса в Android, достаточно тега внизу. – Luksprog

+0

Я добавил скриншот, чтобы показать, что я имею в виду. – DominicM

ответ

3

Что вы просите не чистый линейный градиент - линейный градиент между два цвета на фиксированной ширине имеют только одну математическую функцию, определяющую его, и именно поэтому вы не можете изменить центр. Я думаю, что вы ищете, это фиксированное начало и конец цвета, а также область линейного градиента между ними.

Попробуйте это решение:

sf = new ShapeDrawable.ShaderFactory() { 
    @Override 
    public Shader resize(int width, int height) { 
     LinearGradient lg = new LinearGradient(0, 0, view.getWidth(), 0, new int[] {Color.WHITE, Color.BLACK}, //substitute the correct colors for these 
       new float[] {center - 0.3f, center + 0.3f}, Shader.TileMode.REPEAT); 
     return lg; 
    } 
    }; 
    p = new PaintDrawable(); 
    rectShape = new RectShape(); 
    p.setShape(rectShape); 
    p.setShaderFactory(sf); 
    view.setBackgroundDrawable((Drawable) p); 
    view.setOnTouchListener(new View.OnTouchListener() { 

    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     center = event.getX()/view.getWidth(); // calculate the center 
     p.setShape(rectShape); // this makes the shader recreate the lineargradient 
     return true; 
    } 
    }); 

Этот код, кажется, реагирует достаточно быстро на ощупь, но создать несколько экземпляров LinearGradient.

0

Вы можете сделать что-то подобное с помощью стрелки.

Вам нужно будет установить настраиваемый атрибут progressDrawable и удалить маркер позиции (большой палец) примерно так.

<SeekBar 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:progressDrawable="@drawable/gradient_progress" 
    android:thumb="@null"/> 

gradient_progress.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:id="@android:id/background" 
      android:drawable="@drawable/right_colour" /> 
    <item android:id="@android:id/secondaryProgress"> 
     <scale android:scaleWidth="100%" 
       android:drawable="@drawable/left_colour" /> 
    </item> 
    <item android:id="@android:id/progress"> 
     <scale android:scaleWidth="100%" 
       android:drawable="@drawable/left_colour" /> 
    </item> 
</layer-list> 

, где right_colour является вытяжкой или цветным ресурсом цвета правого (синим) и left_colour представляет собой 9-патч Drawable цвета левого (зеленый), исчезающий до прозрачного, который будет растягивать только крайний левый край. Шахта выглядит следующим образом

left_colour.9.png (Это белое выцветания прозрачных так трудно увидеть здесь)

Это дает решение, которое быстро и не требует какого-либо сенсорного кодирования с вашей стороны, но у него есть недостаток , он не совсем подходит к дальнему концу, поэтому часть «линейного градиента» изображения все еще видна даже тогда, когда пользователь перемещается полностью. Если это не большая проблема, тогда это будет хорошо работать.