子ビューをViewPagerの中心として設定する必要があります。また、次および前のビューの一部を現在のビュー側に表示したいと思います(1の下の現在の画面など)。ただし、現在、現在のビューはViewPagerの左側から開始しています(2の下の予想画面のように)。どうすればそれを達成できますか?
これが私のコードです。
MyViewPagerAdapter
public class MyViewPagerAdapter extends PagerAdapter {
private Activity mActivity;
private int mPageCount;
public MyViewPagerAdapter(Activity activity,int pageCount) {
mActivity = activity;
mPageCount = pageCount;
}
@Override
public int getCount() {
return mPageCount;
}
@Override
public boolean isViewFromObject(View view, Object obj) {
return (view ==(View)obj);
}
@Override
public Object instantiateItem(ViewGroup container,final int position) {
ViewGroup viewGroup = (ViewGroup)mActivity.getLayoutInflater().inflate(
R.layout.item_view, null);
viewGroup.setBackgroundColor(randomColor());
TextView textView = (TextView)viewGroup.findViewById(R.id.textView1);
textView.setText("Page: "+(position+1));
Button button = (Button) viewGroup.findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mActivity, "Hey, Its clicked!!! at page "+(position+1), Toast.LENGTH_LONG).show();
}
});
container.addView(viewGroup);
return viewGroup;
}
Random rnd = new Random();
private int randomColor(){
return Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
}
@Override
public void destroyItem(ViewGroup collection, int position, Object view) {
//must be overridden else throws exception as not overridden.
Log.d("Tag", collection.getChildCount()+"");
collection.removeView((View) view);
}
@Override
public float getPageWidth(int position) {
return 0.8f;
}
}
MainActivity
public class MainActivity extends Activity {
private ViewPager viewPager;
LinearLayout linearLayout;
private int ID = 100;
private final int count = 8;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.viewPager);
linearLayout = (LinearLayout) findViewById(R.id.indicator_layout);
generateIndicators(count);
MyViewPagerAdapter adapter = new MyViewPagerAdapter(this, count);
viewPager.setAdapter(adapter);
viewPager.setOnPageChangeListener(new OnPageChangeListener() {
int oldPosition = 0;
@Override
public void onPageSelected(int position) {
//this changes the old position's view state image
((TextView)linearLayout.getChildAt(oldPosition)).setText("");
oldPosition = position;
//this changes the current position's view state image
((TextView)linearLayout.getChildAt(position)).setText((position+1)+"");
}
//this method will be called repeatedly upto another item comes as front one(active one)
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
//this will be called as per scroll state
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
viewPager.setOffscreenPageLimit(4);
}
private void generateIndicators(int count) {
/// Converts 14 dip into its equivalent px
int padd = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3, getResources().getDisplayMetrics());
for(int i=0;i<count;i++){
TextView textView = new TextView(this);
textView.setId(ID+i);
final int currentItem = i;
textView.setBackgroundResource(R.drawable.white_cell);
textView.setPadding(padd,padd,padd,padd);
/// Converts 14 dip into its equivalent px
int size = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, getResources().getDisplayMetrics());
textView.setTextSize(size);
textView.setGravity(Gravity.CENTER);
/// Converts 14 dip into its equivalent px
int px = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 30, getResources().getDisplayMetrics());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(px, px);
linearLayout.addView(textView,params);
}
((TextView)linearLayout.getChildAt(0)).setText("1");
}
}
activity_main.xml
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:tools="http://schemas.Android.com/tools"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
tools:context=".MainActivity" >
<Android.support.v4.view.ViewPager
Android:id="@+id/viewPager"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
Android:layout_alignParentLeft="true"
Android:layout_alignParentTop="true" >
</Android.support.v4.view.ViewPager>
<LinearLayout
Android:id="@+id/indicator_layout"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_alignParentBottom="true"
Android:layout_centerHorizontal="true"
Android:layout_marginBottom="19dp" >
</LinearLayout>
</RelativeLayout>
item_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="100dp"
Android:layout_height="match_parent"
Android:id="@+id/root_view"
Android:orientation="vertical" >
<TextView
Android:id="@+id/textView1"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:gravity="center"
Android:text="Text"
Android:textAppearance="?android:attr/textAppearanceLarge" />
<Button
Android:id="@+id/button1"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:text="click me" />
</LinearLayout>
現在の画面
期待される画面
最後に、この質問に対する解決策をGitHubに追加しました。私は回避策を得るためにいくつかのかなりのトリックをしました。以下のリンクからプロジェクトを入手できます(実際、説明付きのブログを作成する予定ですが、時間があります)。
これが リンク ( https://github.com/noundla/Sunny_Projects/tree/master/CenterLockViewPager )
ファイルをcom.noundla.centerviewpagersample.comps
パッケージからプロジェクトにコピーする必要があります。そして、MainActivity
クラスでそのViewpagerの使用法を見ることができます。
誰かがこれに問題があるかどうか私に知らせてください。
1つのアプリについて、標準のViewPager
を使用して、同様の方法で実装しました。
内部レイアウトの実際のコンテンツでページを全画面表示にします。たとえば、フルスクリーンレイアウトを背景が透明なRelativeLayout
にし、実際のコンテンツを親の中央に別のRelativeLayout
にします。私の記憶が正しければ、この理由は、ページとしての内部レイアウトだけでは、GalaxyNexusなどの一部のデバイスではViewPager
がすべての画面幅を占めるわけではなかったためです。
ViewPager.setPageMargin()
を使用して、負のページマージン、つまり次/前のページをどれだけ表示するかを設定します。親のフルスクリーンレイアウトの透明な領域とのみ重なるようにしてください。
ViewPager.setOffscreenPageLimit()
を呼び出して、画面外のページ数をデフォルトの2
から少なくとも1
に調整し、実際に画面外にページを作成してスムーズなページングを確保します。それ以外の場合は、すでに部分的に画面に表示されている間に、次/前のページが描画されます。
OPが解決策で質問を更新しなかったことに腹を立てている人のために、最小限の労力でこれをXMLで実行する方法を説明するリンクがあります: http://blog.neteril.org/blog/ 2013/10/14/Android-tip-viewpager-with-protruding-children /
基本的に、ビューページャーをXMLで宣言するときは、左右に同じパディングを付けて、Android:clipToPadding = "false"を設定します。 (clipToPaddingは彼のxmlサンプルになく、この効果を達成するために必要です)
私はこれで解決策を見つけました post 、私が使用したコードの下:
// Offset between sibling pages in dp
int pageOffset = 20;
// Visible part of sibling pages at the edges in dp
int sidePageVisibleWidth = 10;
// Horizontal padding will be
int horPadding = pageOffset + sidePageVisibleWidth;
// Apply parameters
viewPager.setClipToPadding(false);
viewPager.setPageMargin(UIUtil.dpToPx(pageOffset, getContext()));
viewPager.setPadding(UIUtil.dpToPx(horPadding, getContext()), 0, UIUtil.dpToPx(horPadding, getContext()), 0);
dpToPxコード:
public static int dpToPx(int dp, Context context) {
float density = context.getResources().getDisplayMetrics().density;
return Math.round((float) dp * density);
}
必要なのはこれだけです
ViewPagerにパディングを使用して、clipToPadding falseを設定できます。
Java
viewPager.setClipToPadding(false);
viewPager.setPadding(50, 0, 50, 0);
Kotlin
viewPager.clipToPadding = false
viewPager.setPadding(50, 0, 50, 0)
現在のページの中央ビューページャーで異なるページ幅にする必要があったため、パディングを使用したソリューションは適していませんでした。また、ユーザーのスクロールが無効になりました(タブバーのビューページャーで、別のビューページャーによってスクロールされました)。これを行うための非常に簡単な解決策は次のとおりです-このようにViewPager.ScrollToメソッドをオーバーライドするだけです(C#コード、Xamarin):
public override void ScrollTo(int x, int y)
{
x -= (int) (MeasuredWidth * (1 - Adapter.GetPageWidth(CurrentItem)) / 2);
base.ScrollTo(x, y);
}
また、各フラグメントのページ幅を計算する場合は、それらを配列にキャッシュすることを忘れないでください。