2016-04-11 30 views
10

Sono riuscito a creare un'animazione all'inizio del mio CustomViewPager che si comporta come un carosello. Quindi qui, i miei oggetti sono venuti da sinistra e vanno a destra in 3 secondi. Il fatto è che è solo una traduzione che mi stavo chiedendo se è possibile solo far scorrere il mio viewpager da lontano alla sua posizione finale.Avvia un'animazione all'avvio di CustomViewPager

Vedete un modo per farlo? Saluti.

Modifica: Così provo qualcos'altro e ho creato il mio Custom ScrollToAnimation. Riusco a creare ciò che voglio ma il movimento non è fluido, puoi aiutarmi. Il mio nuovo codice:

import android.support.v4.view.ViewPager; 
import android.view.animation.Animation; 
import android.view.animation.Transformation; 

import java.util.Calendar; 

public class ScrollToAnimation extends Animation { 
    private int currentIndex = 0, nbChilds = -1, deltaT = 0; 
    private float fromX, toX; 
    private long animationStart; 
    private ViewPager viewpager; 

    public ScrollToAnimation(ViewPager viewpager, float fromX, float toX, int duration) { 
     this.viewpager = viewpager; 
     this.fromX = fromX; 
     this.toX = toX; 

     nbChilds = viewpager.getChildCount(); 
     deltaT = duration/nbChilds; 

     setDuration(duration); 
     animationStart = Calendar.getInstance().getTimeInMillis(); 
    } 

    @Override 
    protected void applyTransformation(float interpolatedTime, Transformation t) { 
     super.applyTransformation(interpolatedTime, t); 
     int offset = (int) (-fromX * interpolatedTime + fromX); 
     viewpager.scrollTo(offset, 0); 

     long animationProgression = Calendar.getInstance().getTimeInMillis() - animationStart; 
     currentIndex = (int) (animationProgression/deltaT); 
     if(viewpager.getCurrentItem() != currentIndex) { 
      viewpager.setCurrentItem(nbChilds-currentIndex, false); 
     } 
    } 
} 

Il ViewPager:

import android.content.Context; 
import android.graphics.Canvas; 
import android.support.v4.view.ViewPager; 
import android.util.AttributeSet; 
import android.util.DisplayMetrics; 
import android.util.Log; 
import android.view.animation.Animation; 
import android.view.animation.Interpolator; 

import java.lang.reflect.Field; 
import java.lang.reflect.Method; 

public class CarouselViewPager extends ViewPager { 
    private DisplayMetrics metrics; 
    private Animation animation; 
    private SpeedScroller mScroller = null; 
    private boolean animationNotStarted = true, leftToRight; 

    public CarouselViewPager(Context context) { 
     super(context); 
     postInitViewPager(); 
     metrics = getContext().getResources().getDisplayMetrics(); 
    } 

    public CarouselViewPager(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     postInitViewPager(); 
     metrics = getContext().getResources().getDisplayMetrics(); 
    } 

    private void postInitViewPager() { 
     try { 
      Class<?> viewpager = ViewPager.class; 
      Field scroller = viewpager.getDeclaredField("mScroller"); 
      scroller.setAccessible(true); 
      Field interpolator = viewpager.getDeclaredField("sInterpolator"); 
      interpolator.setAccessible(true); 

      mScroller = new SpeedScroller(getContext(), (Interpolator) interpolator.get(null)); 
      scroller.set(this, mScroller); 
     } catch (Exception e) { 
      Log.e("postInitViewPager", e.getMessage()); 
     } 
    } 

    public void setScrollDurationFactor(double scrollFactor) { 
     mScroller.setScrollDurationFactor(scrollFactor); 
    } 

    @Override 
    public void setCurrentItem(int item, boolean smoothScroll) { 
     try { 
      Method method = ViewPager.class.getDeclaredMethod("setCurrentItemInternal", int.class, boolean.class, boolean.class, int.class); 
      method.setAccessible(true); 
      method.invoke(this, item, true, false, 1500); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      super.setCurrentItem(item, smoothScroll); 
     } 
    } 

    public void startAnimation(boolean leftToRight) { 
     animation = new ScrollToAnimation(this, ((metrics.widthPixels/2)+200)*2, 0, 2000); 
     animationNotStarted = false; 
     this.leftToRight = leftToRight; 
    } 

    private Canvas enterAnimation(final Canvas c) { 
     animationNotStarted = true; 
     startAnimation(animation); 
     scrollTo(0, 0); 
     return c; 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     if (!animationNotStarted) { 
      canvas = enterAnimation(canvas); 
     } 
     super.onDraw(canvas); 
    } 
} 

Edit2:

Ecco uno screenshot per aiutare a capire quello che voglio. In realtà ho un viewpager personalizzato come questo:

enter image description here

L'animazione che voglio è il seguente:

  • Quando lancio l'animazione della voce sono lontani.
  • Dopo, vengono da sinistra a destra (o il contrario) e si fermano all'elemento selezionato, ma voglio avere l'effetto di scala quando gli elementi stanno scorrendo.
  • riesco a creare l'effetto di scala grazie ad un adattatore personalizzato

Il mio problema, qui è quando ho impostato l'elemento corrente non è liscia, hai qualche idea? Ecco l'adattatore codice

import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentManager; 
import android.support.v4.app.FragmentPagerAdapter; 
import android.support.v4.view.ViewPager; 
import android.util.Log; 
import android.view.View; 
import android.widget.Button; 
import android.widget.ImageButton; 
import android.widget.ImageView; 
import android.widget.TextView; 

import java.util.ArrayList; 

public class CarouselAdapter extends FragmentPagerAdapter implements ViewPager.OnPageChangeListener { 
    private float scale; 
    private MainActivity context; 

    private FragmentManager fragmentManager; 
    private ArrayList<Entity> entities = new ArrayList<>(); 
    private ScaledFrameLayout cur = null, next = null; 

    public CarouselAdapter(MainActivity context, FragmentManager fragmentManager, ArrayList<Entity> mData) { 
     super(fragmentManager); 
     this.fragmentManager = fragmentManager; 
     this.context = context; 
     this.entities = mData; 
    } 

    @Override 
    public Fragment getItem(int position) { 
     if (position == MainActivity.FIRST_PAGE) { 
      scale = MainActivity.BIG_SCALE; 
     } else { 
      scale = MainActivity.SMALL_SCALE; 
     } 
     Fragment fragment = CarouselFragment.newInstance(context, entities.get(position), position, scale); 
     return fragment; 
    } 

    @Override 
    public int getItemPosition(Object object) { 
     return super.getItemPosition(object); 
    } 

    @Override 
    public int getCount() { 
     return entities.size(); 
    } 

    @Override 
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 
     if (positionOffset >= 0f && positionOffset <= 1f) { 
      cur = getRootView(position); 
      cur.setScaleBoth(MainActivity.BIG_SCALE - MainActivity.DIFF_SCALE * positionOffset); 

      if (position < entities.size()-1) { 
       next = getRootView(position + 1); 
       next.setScaleBoth(MainActivity.SMALL_SCALE + MainActivity.DIFF_SCALE * positionOffset); 
      } 
     } 
    } 

    @Override 
    public void onPageSelected(int position) { } 

    @Override 
    public void onPageScrollStateChanged(int state) {} 

    private ScaledFrameLayout getRootView(int position) { 
     return (ScaledFrameLayout) fragmentManager.findFragmentByTag(this.getFragmentTag(position)).getView().findViewById(R.id.rootItem); 
    } 

    private String getFragmentTag(int position) { 
     return "android:switcher:" + context.carousel.getId() + ":" + position; 
    } 
} 

Un modo più semplicemente, sarebbe quello di cambiare la posizione corrente della voce corrente senza aggiornare tutto, è possibile? Voglio dire senza fare alcuna transizione perché come puoi vedere ho già la traduzione e quando imposto l'elemento corrente è risultato con un conflitto con il mio scrollto con l'offset.

+1

Compilare la domanda. È difficile capire dove sei davvero bloccato –

+1

Voglio migliorare la mia animazione corrente. Qui la mia animazione è solo una traduzione da destra a sinistra. Voglio avere una scroll scorrevole come se stessi scorrendo il viewpager grazie al mio dito. Ad esempio, voglio essere in grado di utilizzare lo stesso risultato che se stavo usando il metodo scollTo dalla classe ViewPager, scusa se non è ancora chiaro. – zed13

+1

@ zed13: "Mi chiedevo se fosse possibile far scorrere il mio viewpager da lontano fino alla sua posizione finale." anche questo sembra una traduzione. di solito scrollTo rende solo la traduzione. ma se puoi pubblicare video di ciò che stai cercando di ottenere sarà più facile (per quanto ho visto ViewPager rende solo l'animazione di traduzione). –

risposta

1

Prova ad usare Visualizza Pager, puoi configurarne la velocità. Tutto ciò che serve è impostarlo su 0, quindi renderlo visibile, quindi spostarlo nella posizione target, scorrerà agevolmente verso il bersaglio, è possibile applicare qualsiasi animazione come nel cercapersone di vista comune, se lo si desidera. Inoltre è possibile setPagingEnable-false e l'utente non sarà scorrere dal tocco

public class SmoothScrollViewPager extends ViewPager { 
    private boolean enabled = true; 
    public SmoothScrollViewPager(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     setMyScroller(); 
    } 

    private void setMyScroller() { 
     try { 
      Class<?> viewpager = ViewPager.class; 
      Field scroller = viewpager.getDeclaredField("mScroller"); 
      scroller.setAccessible(true); 
      scroller.set(this, new MyScroller(getContext())); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     if (this.enabled) { 
      return super.onTouchEvent(event); 
     } 

     return false; 
    } 

    public class MyScroller extends Scroller { 
     public MyScroller(Context context) { 
      super(context, new DecelerateInterpolator()); 
     } 

     @Override 
     public void startScroll(int startX, int startY, int dx, int dy, int duration) { 
      super.startScroll(startX, startY, dx, dy, 1000 /*1 secs*/); 
     } 

    } 

    public void setPagingEnabled(boolean enabled) { 
     this.enabled = enabled; 
    } 
} 
+1

Ho già uno scroller liscio (SpeedScroller), il problema appare perché provo a cambiare l'elemento selezionato corrente grazie al metodo setCurrentItem() ma allo stesso tempo utilizzo il metodo scrollTo. Allora perché uso setCurrentItem()? Perché voglio che ViewPager abbia chiamato il metodo onPageScrolled() dal mio adattatore nello stesso momento in cui il viewpager sta scorrendo. – zed13

3

io penso che si debba fare uno dei ImageSlider con sooth di scorrimento e il cambiamento di immagine con animazione.

La libreria Android Image Slider disponibile in github ora mostra il passaggio seguente per utilizzarla.

  • passaggio 1: Gradle in compilare sotto lib.

    dependencies { 
    compile "com.android.support:support-v4:+" 
    compile 'com.squareup.picasso:picasso:2.3.2' 
    compile 'com.nineoldandroids:library:2.4.0' 
    compile 'com.daimajia.slider:library:[email protected]' 
    } 
    
  • Fase 2: Aggiungere i permessi (se necessario) per il vostro AndroidManifest.xml

    <!-- if you want to load images from the internet --> 
    <uses-permission android:name="android.permission.INTERNET" /> 
    
    <!-- if you want to load images from a file OR from the internet --> 
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 
    
  • Fase 3: Aggiungere il cursore al layout:

    <com.daimajia.slider.library.SliderLayout 
    android:id="@+id/slider" 
    android:layout_width="match_parent" 
    android:layout_height="200dp" 
    /> 
    

    ora fare codice nel tuo Activity Qui SlideShow.class a gestire codice.

    public class SlideShow extends Activity { 
        ImageView mIVmenu; 
        SliderLayout sliderLayout; 
        ListView menu_list; 
        ArrayList<String> imgList = new ArrayList<String>(); 
        int position; 
        Button btnBack; 
        static int adapter_position = 0; 
        String animation_name; 
    
        @Override 
        protected void onCreate(Bundle savedInstanceState) { 
         super.onCreate(savedInstanceState); 
         setContentView(R.layout.slideshow); 
         sliderLayout = (SliderLayout) findViewById(R.id.sliderlayout); 
         menu_list = (ListView) findViewById(R.id.menu_list); 
         btnBack = (Button) findViewById(R.id.btn_back_slideshow); 
         menu_list.setAdapter(adapter); 
         // get Data from Intent array list and set on array list 
         imgList = getIntent().getStringArrayListExtra("arrayList"); 
         position = getIntent().getExtras().getInt("position"); 
         animation_name = SliderLayout.Transformer.Default.toString(); 
        } 
    
        // call method for set images in slideshow and configure slideshow.. 
        addImagesToSlider(); 
    
        btnBack.setOnClickListener(new View.OnClickListener() { 
        @Override 
        public void onClick(View v) { 
         Intent i = new Intent(SlideShow.this, MainActivity.class); 
         startActivity(i); 
         finish(); 
        } 
    }); 
    
    } 
    
    private void addImagesToSlider() { 
        for (int i = 0; i < imgList.size(); i++) { 
        TextSliderView textSliderView = new TextSliderView(this); 
        textSliderView.description("").image(new File(imgList.get(i))).setScaleType(BaseSliderView.ScaleType.CenterInside).setOnSliderClickListener(new BaseSliderView.OnSliderClickListener() { 
         @Override 
         public void onSliderClick(BaseSliderView slider) { 
         } 
        }); 
        sliderLayout.addSlider(textSliderView); 
        } 
    
    sliderLayout.setPresetTransformer(animation_name); 
    sliderLayout.setCustomAnimation(new DescriptionAnimation()); 
    sliderLayout.stopAutoCycle(); 
    sliderLayout.setCurrentPosition(position); 
    } 
    
    BaseAdapter adapter = new BaseAdapter() { 
    @Override 
    public int getCount() { 
        return SliderLayout.Transformer.values().length; 
    } 
    
    @Override 
    public Object getItem(int position) { 
        return null; 
    } 
    
    @Override 
    public long getItemId(int position) { 
        return 0; 
    } 
    
    @Override 
    public View getView(final int position, View convertView, ViewGroup parent) { 
    
        View view; 
        view = LayoutInflater.from(parent.getContext()).inflate(R.layout.slidemenu_item, parent, false); 
        TextView tv = (TextView) view.findViewById(R.id.txtslideTitle); 
        final String str = SliderLayout.Transformer.values()[position].toString(); 
        tv.setText(str); 
    
        view.setOnClickListener(new View.OnClickListener() { 
         @Override 
         public void onClick(View v) { 
    
          sliderLayout.setPresetTransformer(str); 
          animation_name = str; 
          notifyDataSetChanged(); 
    
         } 
        }); 
        if (str.equals(animation_name)) { 
         adapter_position = position;       
    tv.setBackgroundColor(getResources().getColor(R.color.colorAccent)); 
        } else { tv.setBackgroundColor(getResources().getColor(R.color.colorPrimaryDark)); 
        } 
        return view; 
    } 
        }; 
    } 
    

E ulteriori informazioni, consultare this

0

riesco a progredire grazie a una certa introspezione. Ho chiamato il metodo pageScrolled della classe ViewPager.