【问题标题】:Swipe between filtered images for android在 Android 的过滤图像之间滑动
【发布时间】:2015-08-11 15:18:37
【问题描述】:

基本上,我是在重新询问this question,但要在 android 上实现它。

我正在尝试允许用户在静态图像上的过滤器之间滑动。 这个想法是在过滤器滚动时图像保持在原位 它上面。 Snapchat 最近发布了一个实现此功能的版本 特征。 This video shows exactly what I'm trying to accomplish at 1:05.

我尝试使用叠加层填充列表并使用 onFling 对其进行分页并使用 onDraw 进行绘图,但我丢失了动画。有没有办法用 ViewPager 来做到这一点?

编辑:根据要求,我提供了覆盖视图分页的实现。它用位于图像视图顶部的透明 png 图像填充 viewpager。此外,此代码使用 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 布局中。保存图像(我没有发布,因为它超出了这个问题的范围)很简单,它所做的只是创建一个背景位图,一个叠加位图,并使用画布将叠加层绘制到背景上,然后写入文件。

【问题讨论】:

  • 嗨,伙计,这不是通过简单地使视图寻呼机背景透明并在其后面放置图像视图来实现的吗?它有 100 个赏金,所以我觉得这还不够完整,但我就是这样做的,我不明白为什么它不起作用。
  • @Ben 嘿,这就是我实现覆盖的方式。我后面有一张图片,视图寻呼机有一些叠加层。但是,我认为这不适用于图像过滤器(黑白、棕褐色等)
  • 啊对,我只看了几秒钟,就看到上面的文字飞过。祝你好运;P
  • 您可以尝试使用 ViewPager 执行此操作,但是您必须使用额外的动画“补偿” ViewPager 幻灯片动画:从右侧滑入,图像的 RIGHT 部分必须首先出现,然后逐渐暴露图像的其余部分。我的建议是在旧的 ImageView 上放置一个具有效果的新 ImageView,并编写一个效果,通过滑动进度条以正确的方式显示图像。您可以使用 fling 自动化效果并处理所有边缘情况。
  • 如果您能上传您尝试过的代码,那就太好了。在您的最后一句话中,您似乎已经实现了。而你只丢失了动画部分。

标签: java android android-viewpager imagefilter snapchat


【解决方案1】:

我自己也做过类似的事情。

对于您的特定用例,我将只使用画布和 alpha 混合过滤器,作为顶部图像。

要进行 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));
    }

这里是基本的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 调整的伪代码,因为这些功能需要测试。将来最终实现此功能的人可以随意编辑答案并提供这些功能。

【讨论】:

  • 这是一个聪明的主意。我将尝试将它实现到我的用例中。关于示例代码,我个人认为,由于这道题的赏金比较高,为了完整起见,应该提供一些示例代码。对未来的读者来说也更好:)
  • 我同意。我整理了一个示例实现以供参考。
  • 谢谢!我会给你赏金。我会玩这个,看看我是否能得到适当的 x 调整。
  • 谢谢!当您找到合适的设置时,如果您可以对其进行编辑,那就太好了。祝您度过愉快的一天!
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

    对于这个应用程序,我觉得使用 androids 动画功能并将动画值设置为您想要的过滤器是最容易的。因此,您可以制作自己的动画,使更改后的过滤器在您的数组上进行迭代。

    【讨论】:

    • 您能提供一个示例实现吗?
    猜你喜欢
    • 2014-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-03
    • 1970-01-01
    相关资源
    最近更新 更多