2015-08-11 18 views
11

In sostanza, sto ri-chiedendo this question ma per l'implementazione su Android.Scorri tra le immagini filtrate per Android

Sto cercando di consentire agli utenti di scorrere tra i filtri su un'immagine statica. L'idea è che l'immagine rimanga sul posto mentre il filtro scorre sopra di esso. Snapchat ha recentemente rilasciato una versione che implementa questa funzione . This video shows exactly what I'm trying to accomplish at 1:05.

Ho provato a compilare un elenco con le sovrapposizioni e sfogliarlo con l'onFling e disegnare con onDraw, ma perdo le animazioni. C'è un modo in cui ciò può essere fatto con ViewPager?

MODIFICA: come richiesto, ho fornito la mia implementazione per l'impaginazione della visualizzazione overlay. Riempie il viewpager con immagini png trasparenti che si trovano sopra una vista dell'immagine. Inoltre, questo codice è in C#, poiché sto usando Xamarin Android. E 'abbastanza simile a Java per chi non conosce 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; 
    } 
} 

XML layout di attività:

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

Frammento 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" /> 

Per riassumere brevemente: il viewpager si trova sulla cima della prima imageview, che funge da sfondo. Il metodo OnCreateView crea un frammento di sovrapposizione e una visualizzazione di immagini sovrapposte da una risorsa, che inserisce all'interno del layout di overlay_container. Salvare l'immagine (che non ho postato poiché è al di fuori dello scopo di questa domanda) è semplice, tutto ciò che viene fatto è creare una bitmap di sfondo, una bitmap di sovrapposizione e usa una tela per disegnare la sovrapposizione sullo sfondo, quindi scrive su file.

+1

Ciao uomo, questo non è possibile semplicemente rendendo lo sfondo dei cercapersone trasparenti e mettendo una vista immagine dietro di esso? Ha 100 taglie, quindi non sentivo che fosse abbastanza completo di una risposta, ma è così che lo farei e non riesco a capire perché non funzionerebbe. – Ben

+0

@Ben Ehi, Ecco come ho implementato le sovrapposizioni. Avevo un'immagine dietro e il pager della vista ha alcune sovrapposizioni. Tuttavia, non penso che funzionerebbe per i filtri immagine (nero/bianco, seppia, ecc.) –

+0

ahh, ho solo guardato per alcuni secondi e ho visto il testo volare sopra le righe. buona fortuna; P – Ben

risposta

1

Ho lavorato su qualcosa di simile anch'io.

Per il tuo caso d'uso specifico, utilizzerei solo un canvas e alpha per fondere i filtri attraverso l'immagine in alto.

di fare la fusione alfa, impostare la vernice alpha della prima immagine (l'originale) a 255 e l'alfa del secondo (il filtro) a qualcosa come 128.

Hai solo bisogno di un filtro con la dimensione dell'immagine e quindi si sposta la posizione della seconda immagine mentre la si disegna. Questo è tutto.

È estremamente veloce e funziona a meraviglia su dispositivi molto vecchi.

Ecco un esempio di implementazione:

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

E qui sono essenziali onFling e onScroll implementazioni.

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

Nota: I onscroll/onFling implementazioni hanno pseudo codice per le regolazioni x, come devono essere testati tali funzioni.Qualcuno che finisce per implementarlo in futuro può sentirsi libero di modificare la risposta e fornire tali funzioni.

+0

È un'idea geniale. Proverò a implementarlo nel mio caso d'uso. A proposito del codice di esempio, personalmente, ritengo che dal momento che questa domanda abbia una taglia relativamente elevata, alcuni codici di esempio dovrebbero essere forniti per completezza. Inoltre è più bello per i futuri lettori :) –

+0

Sono d'accordo. Ho messo insieme un esempio di implementazione per riferimento. – Sipty

+1

Grazie! Ti assegnerò la taglia. Giocherò con questo e vedrò se riesco ad ottenere le regolazioni x corrette. –

-1

Per questa applicazione ritengo che sarebbe più semplice utilizzare androide e animare le funzioni di animazione e impostare il valore delle animazioni sul filtro desiderato. In questo modo crei la tua animazione con i filtri modificati che iterano sull'array.

+0

Potresti fornire un'implementazione di esempio? –

0

Dai un'occhiata all'implementazione del metodo onDraw per l'app Calendario predefinita: DayView. C'è l'implementazione onFling e il ridisegno del contenuto (ad esempio, la griglia del calendario) in base alle variazioni di movimento, che imita il lancio.

Quindi è possibile utilizzare ColorFilter in onDraw in base alle modifiche al movimento. È molto veloce

In alternativa, è possibile utilizzare ViewSwitcher con un elenco di immagini filtrate (o in qualche modo creato una cache di immagini filtrate). Per ottenere la possibilità di "disegnare sull'immagine", è possibile utilizzare ImageView e ViewSwitcher in RelativeLayout uno sopra l'altro e impostare la nuova immagine filtrata in ImageView dopo la fine dello scorrimento.

Problemi correlati