启动一个动画onstart CustomViewPager。

10
我成功创建了一个动画,它在我的CustomViewPager开始时像旋转木马一样运作。所以,在这里,我的项目从左边来到右边需要3秒钟。问题是这只是一个平移,我想知道是否有可能让我的viewpager从远处滚动到最终位置。
你看到有什么办法可以做到这一点吗? 谢谢。
编辑:所以我尝试了其他方法,并创建了我的自定义ScrollToAnimation。我成功地创建了我想要的东西,但是移动不流畅,你能帮我吗?我的新代码如下:
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);
    }
}

编辑2 :

这里有一张截图,以帮助您了解我的需求。 实际上,我拥有一个类似于此的自定义视图:

enter image description here

我想要的动画效果如下:

  • 当我启动动画时,项目距离很远。
  • 之后,它们从左到右(或相反)移动并停止在选择的项目处,但我想在滚动时具有缩放效果。
  • 我通过自定义适配器成功创建了缩放效果

我的问题是,当我设置当前项目时,它并不平滑,您有任何想法吗? 这是适配器代码

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

有一个更简单的方法,可以在不刷新整个页面的情况下改变当前项目的位置,这是否可能?我的意思是不进行任何过渡,因为您可以看到我已经有了翻译,当我设置当前项目时,它的结果与我的带偏移的scrollto发生冲突。


1
请详细说明您的问题。很难理解您真正遇到了什么困难。 - shaktiman_droid
1
我想改进我的当前动画。目前我的动画只是从右到左的简单平移。我希望能够实现平滑滚动,就像使用手指滚动视图一样。例如,我希望能够使用与ViewPager类中的scrollTo方法相同的效果,如果还不清楚,请见谅。 - zed13
1
@zed13: "我在想是否可能让我的ViewPager从远处滚动到最终位置。" 这也听起来像是一种翻译。通常scrollTo只能进行平移。但如果您可以发布您尝试实现的视频,那将更容易(就我所看到的,ViewPager只能进行平移动画)。 - A-_-S
1
你想让你的视图页面自动滚动吗?带有动画效果吗?@zed13 - Janki Gadhiya
1
我已经更新了我的帖子。 - zed13
3个回答

3

我认为你需要制作一个具有平滑滚动和图像动画效果的图像滑块。

现在在Github上可以找到Android Image Slider库,请按照以下步骤使用它。

  • 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 Here SlideShow.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();
    
            }
        });
        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;
    }
        };
    }
    

更多信息请参考此链接


1
尝试使用平滑的View Pager,您可以配置其速度。您只需要将它设置为0位置,然后使其可见,然后将其移动到目标位置,它就会平稳地滚动到目标位置,如果需要,您可以应用与常规视图页相同的任何动画。此外,您可以将setPagingEnable设置为false,用户将无法通过触摸来滚动它。
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
我已经有一个流畅的滚动器(SpeedScroller),问题出现在我尝试通过setCurrentItem()方法更改当前所选项目,但同时我又使用了scrollTo方法。那么为什么我要使用setCurrentItem()呢?因为我希望ViewPager在滚动时调用我的适配器中的onPageScrolled()方法。 - zed13

0

我通过一些内省成功地进展了。我调用了ViewPager类的pageScrolled方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接