I succeed to create an animation at the start of my CustomViewPager which act like a Carousel. So here, my items came from the left and goes to the right in 3 seconds. The thing is it's just a translation I was wondering if it's possible to just make my viewpager scroll from far away to his final position.
Do you see a way to do this ? Regards.
Edit : So I try something else and I have created my custom ScrollToAnimation. I succeed to create what I want but the movement is not smooth can you help me. My new code :
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); } } }
The 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 :
Here a screenshot to help you to understand what I want. Actually I have a custom viewpager like this :
The animation I want is the follow :
- When I launch the animation the item are far away.
- After, they come from the left to te right (or the opposite) and stop to the selected item, but I want to have the scale effect when the items are scrolling.
- I succeed to create the scaling effect thanks to an custom adapter
My issue, here is when I set the current item it's not smooth, do you have any idea ? Here is the code adapter
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; } }
A more simply way, would be to change the current position of the current item without refresh everything, is it possible ? I mean without making any transition because as you can see I already have the translation and when I set the current item it's result with a conflict with my scrollto with the offset.
2 Answers
Answers 1
I think you have to make one of imageSlider with sooth scroll and image change with animation.
Android Image Slider library available in github now see below step to use it.
step 1: Gradle in compile below 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:1.1.5@aar' }
Step 2: Add permissions (if necessary) to your 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" />
Step 3:Add the Slider to your layout:
<com.daimajia.slider.library.SliderLayout android:id="@+id/slider" android:layout_width="match_parent" android:layout_height="200dp" />
Now Make code in your
Activity
HereSlideShow.class
in manage Code.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(); mDrawer.closeMenu(); } }); 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; } }; }
And more information refer this
Answers 2
Try to use smooth view pager, you can configure it's speed. All you need is to set it to 0 position, then make it visible, and then move it to target position, he will scroll smoothly to the target, you may apply any animation as in common view pager if you want. Also you may setPagingEnable to false and user wiil not scroll it by touch
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; } }
0 comments:
Post a Comment