在适配器中使用自定义 getPageWidth 的自定义 ViewPager 居中当前项目
Custom ViewPager center current item with a custom getPageWidth in Adapter
我有一个像旋转木马一样的自定义 ViewPager,问题是我希望能够在一个页面上显示多个页面。为此,我们有 2 个解决方案:
- 使用边距 setPageMargin() 方法
- 或者我们可以使用覆盖我的 ViewPager 适配器的 getPageWidth 方法。
第一个解决方案效果很好,但我希望能够精确地确定我当前页面的百分比。问题在于 getPageWidth 解决方案,我的当前页面向左移动。这是合乎逻辑的,因为她只穿了以前尺寸的 80%。所以我尝试像这样重写自定义 ViewPager 的 scrollTo 函数:
@Override
public void scrollTo(int x, int y) {
x = (int) (x - (getWidth() - getWidth()*getAdapter().getPageWidth(getCurrentItem()))/2);
super.scrollTo(x, y);
}
它工作正常,但我不能像以前那样滚动,它真的很奇怪,不要朝好的方向前进,不要跟随手指...有什么解决方案可以让我有一个工作滚动和居中的当前页面?
这是我的适配器:
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 java.util.ArrayList;
public class CarouselAdapter extends FragmentPagerAdapter implements ViewPager.OnPageChangeListener {
private ArrayList<Entity> mData = new ArrayList<>();
private ScaledRelativeLayout cur = null, next = null;
private float scale;
private MainActivity context;
private FragmentManager fragmentManager;
public CarouselAdapter(MainActivity context, FragmentManager fragmentManager, ArrayList<Entity> mData) {
super(fragmentManager);
this.fragmentManager = fragmentManager;
this.context = context;
this.mData = mData;
}
@Override
public float getPageWidth(int position) {
return (0.85f);
}
@Override
public Fragment getItem(int position) {
if (position == MainActivity.FIRST_PAGE) {
scale = MainActivity.BIG_SCALE;
} else {
scale = MainActivity.SMALL_SCALE;
}
position = position % mData.size();
Fragment fragment = CarouselFragment.newInstance(context, mData.get(position), position, scale);
return fragment;
}
@Override
public int getCount() {
return mData.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 < mData.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 ScaledRelativeLayout getRootView(int position) {
return (ScaledRelativeLayout) fragmentManager.findFragmentByTag(this.getFragmentTag(position)).getView().findViewById(R.id.rootItem);
}
private String getFragmentTag(int position) {
return "android:switcher:" + context.carousel.getId() + ":" + position;
}
}
没用但这是我的 MainActivity :
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import java.util.ArrayList;
public class MainActivity extends FragmentActivity {
public static int FIRST_PAGE;
public final static float BIG_SCALE = 1.0f;
public final static float SMALL_SCALE = 0.85f;
public final static float DIFF_SCALE = BIG_SCALE - SMALL_SCALE;
public CarouselViewPager carousel;
private CarouselAdapter carouselAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FIRST_PAGE = mData.size()/2;
carouselAdapter = new CarouselAdapter(this, this.getSupportFragmentManager(), mData);
carousel = (CarouselViewPager) findViewById(R.id.carousel);
carousel.setAdapter(carouselAdapter);
carousel.addOnPageChangeListener(carouselAdapter);
carousel.setCurrentItem(Math.round(FIRST_PAGE));
carousel.setOffscreenPageLimit(3);
carousel.setClipToPadding(false);
carousel.setScrollDurationFactor(2.5f);
}
}
编辑:
root.post(new Runnable() {
@Override
public void run() {
int width = root.getWidth();
Log.w("Post", "Width : " + width + ", newWidth : " + (width * 0.8));
// root.setPadding((int) (width * 0.125), 0, (int) (width * 0.125), 0);
ViewPager.LayoutParams params = (ViewPager.LayoutParams) root.getLayoutParams();
params.width = (int) (width * 0.8);
root.setLayoutParams(params);
root.requestLayout();
root.forceLayout();
root.invalidate();
}
});
此致
而不是 setPageMargin
或 getPageWidth
您可以只为您的 ViewPager 设置填充。
<android.support.v4.view.ViewPager
android:id="@+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:clipToPadding="false" />
注意 clipToPadding
部分,显示其他页面很重要。
如果您想将宽度显示为屏幕的 x%,可以在 Java
中执行此操作
mRootView.post(new Runnable() {
@Override
public void run() {
int w = mRootView.getWidth();
mViewPager.setPadding(w * 0.25, 0, w * 0.25, 0);
// 25% padding on either side so pages takes exactly 50% space
}
});
我有一个像旋转木马一样的自定义 ViewPager,问题是我希望能够在一个页面上显示多个页面。为此,我们有 2 个解决方案:
- 使用边距 setPageMargin() 方法
- 或者我们可以使用覆盖我的 ViewPager 适配器的 getPageWidth 方法。
第一个解决方案效果很好,但我希望能够精确地确定我当前页面的百分比。问题在于 getPageWidth 解决方案,我的当前页面向左移动。这是合乎逻辑的,因为她只穿了以前尺寸的 80%。所以我尝试像这样重写自定义 ViewPager 的 scrollTo 函数:
@Override
public void scrollTo(int x, int y) {
x = (int) (x - (getWidth() - getWidth()*getAdapter().getPageWidth(getCurrentItem()))/2);
super.scrollTo(x, y);
}
它工作正常,但我不能像以前那样滚动,它真的很奇怪,不要朝好的方向前进,不要跟随手指...有什么解决方案可以让我有一个工作滚动和居中的当前页面?
这是我的适配器:
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 java.util.ArrayList;
public class CarouselAdapter extends FragmentPagerAdapter implements ViewPager.OnPageChangeListener {
private ArrayList<Entity> mData = new ArrayList<>();
private ScaledRelativeLayout cur = null, next = null;
private float scale;
private MainActivity context;
private FragmentManager fragmentManager;
public CarouselAdapter(MainActivity context, FragmentManager fragmentManager, ArrayList<Entity> mData) {
super(fragmentManager);
this.fragmentManager = fragmentManager;
this.context = context;
this.mData = mData;
}
@Override
public float getPageWidth(int position) {
return (0.85f);
}
@Override
public Fragment getItem(int position) {
if (position == MainActivity.FIRST_PAGE) {
scale = MainActivity.BIG_SCALE;
} else {
scale = MainActivity.SMALL_SCALE;
}
position = position % mData.size();
Fragment fragment = CarouselFragment.newInstance(context, mData.get(position), position, scale);
return fragment;
}
@Override
public int getCount() {
return mData.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 < mData.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 ScaledRelativeLayout getRootView(int position) {
return (ScaledRelativeLayout) fragmentManager.findFragmentByTag(this.getFragmentTag(position)).getView().findViewById(R.id.rootItem);
}
private String getFragmentTag(int position) {
return "android:switcher:" + context.carousel.getId() + ":" + position;
}
}
没用但这是我的 MainActivity :
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import java.util.ArrayList;
public class MainActivity extends FragmentActivity {
public static int FIRST_PAGE;
public final static float BIG_SCALE = 1.0f;
public final static float SMALL_SCALE = 0.85f;
public final static float DIFF_SCALE = BIG_SCALE - SMALL_SCALE;
public CarouselViewPager carousel;
private CarouselAdapter carouselAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FIRST_PAGE = mData.size()/2;
carouselAdapter = new CarouselAdapter(this, this.getSupportFragmentManager(), mData);
carousel = (CarouselViewPager) findViewById(R.id.carousel);
carousel.setAdapter(carouselAdapter);
carousel.addOnPageChangeListener(carouselAdapter);
carousel.setCurrentItem(Math.round(FIRST_PAGE));
carousel.setOffscreenPageLimit(3);
carousel.setClipToPadding(false);
carousel.setScrollDurationFactor(2.5f);
}
}
编辑:
root.post(new Runnable() {
@Override
public void run() {
int width = root.getWidth();
Log.w("Post", "Width : " + width + ", newWidth : " + (width * 0.8));
// root.setPadding((int) (width * 0.125), 0, (int) (width * 0.125), 0);
ViewPager.LayoutParams params = (ViewPager.LayoutParams) root.getLayoutParams();
params.width = (int) (width * 0.8);
root.setLayoutParams(params);
root.requestLayout();
root.forceLayout();
root.invalidate();
}
});
此致
而不是 setPageMargin
或 getPageWidth
您可以只为您的 ViewPager 设置填充。
<android.support.v4.view.ViewPager
android:id="@+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:clipToPadding="false" />
注意 clipToPadding
部分,显示其他页面很重要。
如果您想将宽度显示为屏幕的 x%,可以在 Java
中执行此操作mRootView.post(new Runnable() {
@Override
public void run() {
int w = mRootView.getWidth();
mViewPager.setPadding(w * 0.25, 0, w * 0.25, 0);
// 25% padding on either side so pages takes exactly 50% space
}
});