2015-08-11 18 views
11

Về cơ bản, tôi đang yêu cầu lại this question nhưng để triển khai trên Android.Vuốt giữa các hình ảnh được lọc cho android

Tôi đang cố gắng cho phép người dùng vuốt giữa các bộ lọc trên hình ảnh tĩnh. Ý tưởng là hình ảnh được giữ nguyên trong khi bộ lọc cuộn phía trên nó. Snapchat gần đây đã phát hành một phiên bản thực hiện tính năng này. This video shows exactly what I'm trying to accomplish at 1:05.

Tôi đã thử điền một danh sách có lớp phủ và phân trang qua danh sách với onFling và vẽ bằng onDraw, nhưng tôi sẽ mất hoạt ảnh. Có cách nào điều này có thể được thực hiện với ViewPager?

EDIT: Theo yêu cầu, tôi đã cung cấp triển khai cho phân trang chế độ xem lớp phủ. Nó lấp đầy viewpager với hình ảnh png trong suốt nằm trên đỉnh của một khung nhìn hình ảnh. Ngoài ra, mã này là trong C#, như tôi đang sử dụng Xamarin Android. Đó là khá tương tự như Java cho những người không quen với C#

... 
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; 
    } 
} 

Hoạt động Giao diện 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> 

Fragment Overlay 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" /> 

Để tóm tắt ngắn gọn: các ViewPager ngồi trên đỉnh đầu tiên imageview, hoạt động như một nền tảng. Phương thức OnCreateView tạo một lớp phủ lớp phủ và một lớp phủ hình ảnh từ một tài nguyên mà nó đặt bên trong bố cục overlay_container. Lưu hình ảnh (mà tôi chưa đăng vì nằm ngoài phạm vi của câu hỏi này) đơn giản, tất cả những gì nó tạo ra là bitmap nền, bitmap lớp phủ và sử dụng canvas để vẽ lớp phủ lên nền, sau đó ghi vào tập tin.

+1

Xin chào, điều này không thể thực hiện được bằng cách đơn giản bằng cách làm cho nền của máy nhắn tin xem trong suốt và đặt một hình ảnh phía sau nó? Nó có 100 tiền thưởng, vì vậy tôi đã không cảm thấy như thế này là đủ hoàn chỉnh của một câu trả lời, nhưng đó là cách tôi muốn làm điều đó và tôi không thể thấy tại sao nó sẽ không hoạt động. – Ben

+0

@Ben Hey, Đó là cách tôi triển khai lớp phủ. Tôi đã có một hình ảnh phía sau và máy nhắn tin xem có một số lớp phủ. Tuy nhiên, tôi không nghĩ rằng sẽ làm việc cho các bộ lọc hình ảnh (đen/trắng, nâu đỏ vv) –

+0

ahh đúng, tôi chỉ xem cho một vài giây của nó và thấy các văn bản bay trên đầu trang. P – Ben

Trả lời

1

Tôi đã tự làm một việc tương tự.

Đối với trường hợp sử dụng cụ thể của bạn, tôi sẽ chỉ sử dụng canvas và alpha pha trộn các bộ lọc trên, khi trượt, làm hình ảnh trên cùng.

Để làm sự pha trộn alpha, thiết lập sơn alpha của hình ảnh đầu tiên (bản gốc) đến 255 và alpha của một giây (bộ lọc) để một cái gì đó giống như 128.

Bạn chỉ cần một bộ lọc với kích thước của hình ảnh và sau đó bạn thay đổi vị trí của hình ảnh thứ hai khi bạn vẽ nó. Đó là nó.

Rất nhanh và hoạt động trên các thiết bị rất, rất cũ.

Dưới đây là một việc thực hiện mẫu:

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)); 
    } 

Và đây là cơ bản onFlingonScroll triển khai.

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 
     } 
    } 
} 

Lưu ý: Các OnScroll/onFling triển khai có mã giả cho những điều chỉnh x, như những chức năng cần phải được kiểm tra.Một người nào đó sẽ thực hiện điều này trong tương lai, có thể cảm thấy tự do để chỉnh sửa câu trả lời và cung cấp các chức năng đó.

+0

Đó là một ý tưởng thông minh. Tôi sẽ cố gắng thực hiện nó vào trường hợp sử dụng của tôi. Về chủ đề của mã mẫu, cá nhân, tôi nghĩ rằng kể từ khi câu hỏi này có một tiền thưởng tương đối cao, một số mã mẫu nên được cung cấp cho đầy đủ. Ngoài ra nó đẹp hơn cho người đọc trong tương lai :) –

+0

Tôi đồng ý. Tôi đặt cùng một triển khai mẫu để tham khảo. – Sipty

+1

Cảm ơn! Tôi sẽ trao cho bạn tiền thưởng. Tôi sẽ chơi xung quanh với điều này và xem liệu tôi có thể có được các điều chỉnh x thích hợp hay không. –

-1

Đối với ứng dụng này, tôi cảm thấy nó sẽ dễ dàng nhất để sử dụng các tính năng hoạt hình android và đặt giá trị hoạt ảnh cho bộ lọc bạn muốn. Vì vậy, bạn sẽ làm cho hình ảnh động của riêng bạn các bộ lọc thay đổi lặp qua mảng của bạn.

+0

Bạn có thể cung cấp triển khai ví dụ không? –

0

Hãy xem xét việc triển khai phương pháp onDraw cho ứng dụng Lịch mặc định: DayView. Có onFling triển khai và vẽ lại nội dung (ví dụ: lưới lịch) theo các thay đổi chuyển động, bắt chước quá trình thoát.

Sau đó, bạn có thể sử dụng ColorFilter trong onDraw theo các thay đổi chuyển động. Nó rất nhanh.

Hoặc, bạn có thể sử dụng ViewSwitcher với danh sách hình ảnh được lọc (hoặc bằng cách nào đó đã tạo bộ nhớ cache hình ảnh được lọc). Để đạt được khả năng "vẽ lên hình ảnh", bạn có thể sử dụng ImageViewViewSwitcherRelativeLayout cái khác và đặt hình ảnh được lọc mới trong ImageView sau khi kết thúc cuộn.

Các vấn đề liên quan