在安卓设备上滑动筛选后的图片

11

本质上,我正在重新提出这个问题,但是要在Android上实现。

我试图允许用户在静态图像之间滑动筛选器。 这个想法是,图像保持不变,而过滤器在其上滚动。 Snapchat最近发布了一个实现此功能的版本。这个视频显示了我想在1:05实现的内容

我尝试使用onFling填充覆盖层列表并进行分页,然后使用onDraw进行绘制, 但是我失去了动画效果。是否有一种方法可以使用ViewPager完成此操作?

编辑:按要求,我提供了我的叠加视图分页实现方式。它使用透明的png图像填充viewpager,并位于image view的顶部。此外,此代码采用C#编写,因为我正在使用Xamarin Android。对于不熟悉C#的人来说,它与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位于第一个imageview之上,作为背景。OnCreateView方法从资源中创建覆盖片段和覆盖图像视图,并将它们放置在overlay_container布局中。保存图像(我没有发布它,因为它超出了这个问题的范围)很简单,它只是创建一个背景位图、一个覆盖位图,并使用画布将覆盖绘制到背景上,然后写入文件。


1
嗨,这不是通过将视图页面的背景设置为透明并在其后面放置一个图像视图就可以实现吗?它有100赏金,所以我觉得这不是一个完整的答案,但这就是我会做的,我看不出为什么它不起作用。 - Ben
1
你可以尝试使用ViewPager来实现,但是你需要通过额外的动画来“补偿”ViewPager的滑动动画:从右侧滑入时,图像的右侧部分必须首先显示出来,然后逐渐展示其余部分。我的建议是在旧ImageView上放置一个新的ImageView,并编写一个效果,通过滑动进度条以正确的方式显示图像。然后,您可以使用fling自动化效果并处理所有边缘情况。 - Jeroen Mols
@jmols 这是个有趣的想法。如果我成功了,我会尝试并将其发布为答案。谢谢! - RN_
1
如果您能上传您尝试过的代码,那就太好了。在您最后一句话中,似乎您已经实现了。而您只是失去了动画部分。 - Swan
@SH。添加了代码 :) - RN_
显示剩余2条评论
3个回答

1

我自己也做过类似的东西。

对于您特定的用例,我会只使用画布并在快速滑动时,将滤镜与顶部图像进行透明混合。

要执行Alpha混合,将第一幅图像(原始图像)的Alpha绘制设置为255,第二幅图像(滤镜)的Alpha设置为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));
    }

这里是基本的onFlingonScroll实现。

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调整,因为这些函数需要进行测试。将来实现此功能的人可以随意编辑答案并提供这些函数。


那是个聪明的想法。我会尝试将其应用到我的使用场景中。关于示例代码,个人认为由于这个问题有相对较高的赏金,应该提供一些示例代码以便完整性。而且对于未来的读者更友好 :) - RN_
我同意。我已经准备了一个样例实现供参考。 - Sipty
1
谢谢!我会授予你奖励。我会尝试调整一下,看看能否得到正确的x调整。 - RN_
谢谢!当您找到适当的设置时,如果您能进行编辑,那将非常好。祝您有一个美好的一天! - Sipty

0

看一下默认日历应用程序的onDraw方法的实现:DayView。 有onFling的实现和内容(例如,日历网格)根据运动变化重新绘制,模拟fling。

然后,您可以根据运动变化在onDraw中使用ColorFilter。它非常快速。

或者,您可以使用ViewSwitcher与过滤图像列表(或以某种方式创建过滤图像缓存)。为了实现“在图像上绘制”的可能性,您可以在RelativeLayout中使用ImageViewViewSwitcher相互叠放,并在滚动结束后在ImageView中设置新的过滤图像。


-1
对于这个应用程序,我觉得最容易使用Android的动画功能,并将动画值设置为所需的过滤器。因此,您可以创建自己的动画,通过迭代数组来更改过滤器。

1
你能提供一个实现的例子吗? - RN_

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接