Подтвердить что ты не робот

Пролистать отфильтрованные изображения для Android

По сути, я перепрошу этот вопрос, но для его реализации на android.

Я пытаюсь разрешить пользователям прокручивать между фильтрами статическое изображение. Идея заключается в том, что изображение остается на месте, пока прокрутки фильтра над ним. Недавно Snapchat выпустил версию, которая реализует эту особенность. Это видео показывает, что именно я пытаюсь выполнить на 1:05.

Я попытался заполнить список оверлеями и прорисовывать его через onFling и рисовать с помощью onDraw, но я теряю анимацию. Есть ли способ сделать это с помощью ViewPager?

ИЗМЕНИТЬ: В соответствии с просьбой я предоставил свою реализацию для подкачки наложения. Он заполняет viewpager прозрачными изображениями png, которые располагаются поверх изображения. Кроме того, этот код находится в С#, поскольку я использую Xamarin Android. Это довольно похоже на Java для тех, кто не знаком с С#

...
static List<ImageView> overlayList = new List<ImageView>();
...

public class OverlayFragmentAdapter : FragmentPagerAdapter
{
    public OverlayFragmentAdapter(Android.Support.V4.App.FragmentManager fm) : base(fm)
    {

    }



    public override int Count
    {
        get { return 5; } //hardcoded temporarily 
    }

    public override Android.Support.V4.App.Fragment GetItem(int position)
    {
        return new OverlayFragment ();
    }
}
public class OverlayFragment : Android.Support.V4.App.Fragment
{
    public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {


        View view = inflater.Inflate (Resource.Layout.fragment_overlay, container, false);

        LinearLayout l1 = view.FindViewById<LinearLayout> (Resource.Id.overlay_container);

        ImageView im = new ImageView (Activity);

        im.SetImageResource (Resource.Drawable.Overlay); //Resource.Drawable.Overlay is a simple png transparency I created. R

        l1.AddView (im);
        overlayList.AddElement (im);
        return view;
    }
}

Макет деятельности XML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="bottom">
    <ImageView
        android:id="@+id/background_image"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <RelativeLayout <!-- This second layout is for buttons which I have omitted from this code -->
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:id="@+id/edit_layout">
        <android.support.v4.view.ViewPager
            android:id="@+id/overlay_pager"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </RelativeLayout>
</RelativeLayout>

Фрагмент наложения XML

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/overlay_container"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center" />

Чтобы кратко суммировать: viewpager находится поверх первого изображения, которое выступает в качестве фона. Метод OnCreateView создает оверлейный фрагмент и оверлейное изображение из ресурса, который он помещает внутри макета overlay_container. Сохранение изображения (которое я еще не опубликовал, поскольку оно выходит за рамки этого вопроса) прост, все, что он делает, это создать фоновое растровое изображение, наложение растрового изображения и использовать холст, чтобы нарисовать оверлей на фоне, а затем записать в файл.

4b9b3361

Ответ 1

Я работал над чем-то подобным.

В вашем конкретном случае использования я просто использовал бы холст и альфа-смесь фильтров, расположенных в потоке, в качестве верхнего изображения.

Чтобы выполнить альфа-смешение, установите альфа-краску первого изображения (оригинал) на 255 и альфа второго (фильтр) на что-то вроде 128.

Вам нужен фильтр с размером изображения, а затем вы перемещаете положение второго изображения по мере его рисования. Что это.

Это очень быстро и работает на очень, очень старых устройствах.

Здесь пример реализации:

    Bitmap filter,  // the filter
        original, // our original
        tempBitmap; // the bitmap which holds the canvas results 
                    // and is then drawn to the imageView
    Canvas mCanvas; // our canvas

    int x = 0;   // The x coordinate of the filter. This variable will be manipulated
                        // in either onFling or onScroll.
    void draw() {
        // clear canvas
        mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);    

        // setup paint
        paint0.setAlpha(255);   // the original needs to be fully visible
        paint1.setAlpha(128);   // the filter should be alpha blended into the original.

        // enable AA for paint
        // filter image
        paint1.setAntiAlias(true);
        paint1.setFlags(Paint.ANTI_ALIAS_FLAG);     // Apply AA to the image. Optional.
        paint1.setFlags(Paint.FILTER_BITMAP_FLAG);  // In case you scale your image, apple
                                                    // bilinear filtering. Optional.
        // original image
        paint0.setAntiAlias(true);
        paint0.setFlags(Paint.ANTI_ALIAS_FLAG);
        paint0.setFlags(Paint.FILTER_BITMAP_FLAG);

        // draw onto the canvas    
        mCanvas.save();                

        mCanvas.drawBitmap(original, 0,0,paint0);
        mCanvas.drawBitmap(filter, x,0,paint1);    

        mCanvas.restore();

        // set the new image
        imageView.setImageDrawable(new BitmapDrawable(getResources(), tempBitmap));
    }

И вот основные onFling и onScroll реализации.

private static final int SWIPE_DISTANCE_THRESHOLD = 125;
private static final int SWIPE_VELOCITY_THRESHOLD = 75;

// make sure to have implemented GestureDetector.OnGestureListener for these to work.
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
        float velocityY) {
    float distanceX = e2.getX() - e1.getX();
    float distanceY = e2.getY() - e1.getY();
    if (Math.abs(distanceX) > Math.abs(distanceY) && Math.abs(distanceX) > 
            SWIPE_DISTANCE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {

        // change picture to
        if (distanceX > 0) {
            // start left increment
        }
        else {  // the left
            // start right increment
        }
    }
}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {

    // checks if we're touching for more than 2f. I like to have this implemented, to prevent
    // jerky image motion, when not really moving my finger, but still touching. Optional.
    if (Math.abs(distanceY) > 2 || Math.abs(distanceX) > 2) {  
        if(Math.abs(distanceX) > Math.abs(distanceY)) {
            // move the filter left or right
        }
    }
}

Примечание. В реализациях onScroll/onFling есть псевдокод для корректировок x, поскольку эти функции необходимо протестировать. Кто-то, кто в конечном итоге реализует это в будущем, может свободно отредактировать ответ и предоставить эти функции.

Ответ 2

Взгляните на реализацию метода onDraw для приложения Calendar по умолчанию: DayView, Существует реализация onFling и перерисовка содержимого (например, сетка календаря) в соответствии с изменениями движения, которые имитируют fling.

Затем вы можете использовать ColorFilter в onDraw в соответствии с изменениями движения. Это очень быстро.

В качестве альтернативы вы можете использовать ViewSwitcher со списком отфильтрованных изображений (или каким-то образом создали отфильтрованные изображения кэш). Чтобы достичь возможности "рисования изображения", вы можете использовать ImageView и ViewSwitcher в RelativeLayout один над другим и установить новое отфильтрованное изображение в ImageView после окончания прокрутки.

Ответ 3

Для этого приложения я считаю, что наиболее легко использовать анимационные функции androids и установить значение анимации для фильтра, который вы хотите. Таким образом, вы сделали бы свою собственную анимацию измененными фильтрами, итерациями по вашему массиву.