我可以使用视图分页器与视图(而不是片段)
我正在使用ViewPager
b / w Fragments
,但我可以使用ViewPager
轻扫b / w Views
简单的xml布局?
这是我的页面Adapter
用于在片段之间滑动的ViewPager:
import java.util.List; import com.app.name.fragments.TipsFragment; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.app.FragmentTransaction; import android.view.ViewGroup; public class PageAdapter extends FragmentPagerAdapter { /** * */ List<Fragment> fragments; public PageAdapter(FragmentManager fm,List<Fragment> frags) { super(fm); fragments = frags; } @Override public Fragment getItem(int arg0) { // TODO Auto-generated method stub return TipsFragment.newInstance(0, 0); } @Override public int getCount() { // TODO Auto-generated method stub return 4; } @Override public void destroyItem(ViewGroup container, int position, Object object) { FragmentManager manager = ((Fragment) object).getFragmentManager(); FragmentTransaction trans = manager.beginTransaction(); trans.remove((Fragment) object); trans.commit(); super.destroyItem(container, position, object); } }
这是我的小费片段:
public class TipsFragment extends Fragment { public static TipsFragment newInstance(int image,int content) { TipsFragment fragment = new TipsFragment(); return fragment; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.tip_layout, null); return view; } }
我怎样才能修改我的代码来使用视图而不是片段?
你需要重写这两个方法,而不是getItem()
@Override public Object instantiateItem(ViewGroup collection, int position) { View v = layoutInflater.inflate(...); ... collection.addView(v,0); return v; } @Override public void destroyItem(ViewGroup collection, int position, Object view) { collection.removeView((View) view); }
使用这个例子
您可以使用嵌套子视图的单个XML布局。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:id="@+id/page_one" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:text="PAGE ONE IN" android:layout_width="match_parent" android:layout_height="match_parent" android:textColor="#fff" android:textSize="24dp"/> </LinearLayout> <LinearLayout android:id="@+id/page_two" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:text="PAGE TWO IN" android:layout_width="match_parent" android:layout_height="match_parent" android:textColor="#fff" android:textSize="24dp"/> </LinearLayout> </android.support.v4.view.ViewPager> </LinearLayout>
但是…你需要用适配器来处理这个。 在这里,我们返回finded视图ID而不用膨胀任何其他布局。
class WizardPagerAdapter extends PagerAdapter { public Object instantiateItem(ViewGroup collection, int position) { int resId = 0; switch (position) { case 0: resId = R.id.page_one; break; case 1: resId = R.id.page_two; break; } return findViewById(resId); } @Override public int getCount() { return 2; } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == ((View) arg1); } }
//设置ViewPager适配器
WizardPagerAdapter adapter = new WizardPagerAdapter(); ViewPager pager = (ViewPager) findViewById(R.id.pager); pager.setAdapter(adapter);
根据以前的答案,我做了下面这个class,以正确,清晰的方式达到这个目的(我希望):
public class MyViewPagerAdapter extends PagerAdapter { ArrayList<ViewGroup> views; LayoutInflater inflater; public MyViewPagerAdapter(ActionBarActivity ctx){ inflater=LayoutInflater.from(ctx); //instantiate your views list views=new ArrayList<ViewGroup>(5); } /** * To be called by onStop * Clean the memory */ public void release(){ views.clear(); views=null; } /** * Return the number of views available. */ @Override public int getCount() { return 5; } /** * Create the page for the given position. The adapter is responsible * for adding the view to the container given here, although it only * must ensure this is done by the time it returns from * {@link #finishUpdate(ViewGroup)}. * * @param container The containing View in which the page will be shown. * @param position The page position to be instantiated. * @return Returns an Object representing the new page. This does not * need to be a View, but can be some other container of the page.,container */ public Object instantiateItem(ViewGroup container, int position) { ViewGroup currentView; Log.e("MyViewPagerAdapter","instantiateItem for "+position); if(views.size()>position&&views.get(position)!=null){ Log.e("MyViewPagerAdapter","instantiateItem views.get(position) "+views.get(position)); currentView=views.get(position); }else{ Log.e("MyViewPagerAdapter","instantiateItem need to create the View"); int rootLayout=R.layout.view_screen; currentView= (ViewGroup) inflater.inflate(rootLayout,container,false); ((TextView)currentView.findViewById(R.id.txvTitle)).setText("My Views "+position); ((TextView)currentView.findViewById(R.id.btnButton)).setText("Button"); ((ImageView)currentView.findViewById(R.id.imvPicture)).setBackgroundColor(0xFF00FF00); } container.addView(currentView); return currentView; } /** * Remove a page for the given position. The adapter is responsible * for removing the view from its container, although it only must ensure * this is done by the time it returns from {@link #finishUpdate(ViewGroup)}. * * @param container The containing View from which the page will be removed. * @param position The page position to be removed. * @param object The same object that was returned by * {@link #instantiateItem(View, int)}. */ @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View)object); } /** * Determines whether a page View is associated with a specific key object * as returned by {@link #instantiateItem(ViewGroup, int)}. This method is * required for a PagerAdapter to function properly. * * @param view Page View to check for association with <code>object</code> * @param object Object to check for association with <code>view</code> * @return true if <code>view</code> is associated with the key object <code>object</code> */ @Override public boolean isViewFromObject(View view, Object object) { return view==((View)object); } }
你必须把它放在你的活动中:
public class ActivityWithViewsPaged extends ActionBarActivity { /** * The page Adapter : Manage the list of views (in fact here, it's fragments) * And send them to the ViewPager */ private MyViewPagerAdapter pagerAdapter; /** * The ViewPager is a ViewGroup that manage the swipe from left to right to left * Like a listView with a gesture listener... */ private ViewPager viewPager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_with_views); //Find the viewPager viewPager = (ViewPager) super.findViewById(R.id.viewpager); //instanciate the PageAdapter pagerAdapter=new MyViewPagerAdapter(this); // Affectation de l'adapter au ViewPager viewPager.setAdapter(pagerAdapter); viewPager.setClipToPadding(false); viewPager.setPageMargin(12); //Add animation when the page are swiped //this instanciation only works with honeyComb and more //if you want it all version use AnimatorProxy of the nineoldAndroid lib //@see:http://stackoverflow.com/questions/15767729/backwards-compatible-pagetransformer if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB){ viewPager.setPageTransformer(true, new PageTransformer()); } } @Override protected void onStop() { super.onStop(); pagerAdapter.release(); }
其中的XML文件是显而易见的view_screen.xml:
<xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/screen" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/txvTitle" android:layout_width="wrap_content" android:layout_gravity="center" android:layout_height="wrap_content" android:layout_marginBottom="5dp" android:layout_marginTop="5dp" android:shadowColor="#FF00FF" android:shadowDx="10" android:shadowDy="10" android:shadowRadius="5" android:textSize="32dp" android:textStyle="italic" android:background="#FFFFF000"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#FFFF00F0"> <TextView android:id="@+id/txvLeft" android:layout_width="wrap_content" android:layout_gravity="left" android:layout_height="wrap_content" android:layout_marginBottom="5dp" android:layout_marginTop="5dp"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1"/> <TextView android:id="@+id/txvRight" android:layout_width="wrap_content" android:layout_gravity="right" android:layout_height="wrap_content" android:layout_marginBottom="5dp" android:layout_marginTop="5dp"/> </LinearLayout> <Button android:id="@+id/btnButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center"/> <ImageView android:id="@+id/imvPicture" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center"/> </LinearLayout>
ActivtyMain具有以下布局:
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:paddingLeft="24dp" android:paddingRight="24dp" android:id="@+id/viewpager" android:background="#FF00F0F0"> </android.support.v4.view.ViewPager>
非常感谢Brian和Nicholas的回答,希望我能为这个function添加一些最清晰的信息,并且提供一些很好的实践。
我们已经构build了一个我们有时使用的ViewPager
的非常简单的子类。
/** * View pager used for a finite, low number of pages, where there is no need for * optimization. */ public class StaticViewPager extends ViewPager { /** * Initialize the view. * * @param context * The application context. */ public StaticViewPager(final Context context) { super(context); } /** * Initialize the view. * * @param context * The application context. * @param attrs * The requested attributes. */ public StaticViewPager(final Context context, final AttributeSet attrs) { super(context, attrs); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); // Make sure all are loaded at once final int childrenCount = getChildCount(); setOffscreenPageLimit(childrenCount - 1); // Attach the adapter setAdapter(new PagerAdapter() { @Override public Object instantiateItem(final ViewGroup container, final int position) { return container.getChildAt(position); } @Override public boolean isViewFromObject(final View arg0, final Object arg1) { return arg0 == arg1; } @Override public int getCount() { return childrenCount; } @Override public void destroyItem(final View container, final int position, final Object object) {} }); } }
该类不需要适配器,因为它将从布局加载视图。 为了使用它你的项目,只需使用它,而不是android.support.v4.view.ViewPager
。
所有的花哨的东西仍然可以工作,但是你不需要被适配器困扰。
我想阐述一下@Nicholas的答案,你可以通过id获得视图,或者如果它们是dynamic添加的,只需直接给定它的位置
class WizardPagerAdapter extends PagerAdapter { public Object instantiateItem(View collection, int position) { View v = pager.getChildAt(position); return v; } @Override public int getCount() { return 3; } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == ((View) arg1); } }
我想在这里添加我的解决scheme。 鉴于你不需要使用片段,你仍然可以创build一个PagerAdapter
,它将views
而不是fragments
附加到ViewPager
。
扩展PagerAdapter
而不是FragmentPagerAdapter
public class CustomPagerAdapter extends PagerAdapter { private Context context; public CustomPagerAdapter(Context context) { super(); this.context = context; } @Override public Object instantiateItem(ViewGroup collection, int position) { LayoutInflater inflater = LayoutInflater.from(context); View view = null; switch (position){ case 0: view = MemoryView.getView(context, collection); break; case 1: view = NetworkView.getView(context, collection); break; case 2: view = CpuView.getView(context, collection); break; } collection.addView(view); return view; } @Override public int getCount() { return 3; } @Override public boolean isViewFromObject(View view, Object object) { return view==object; } @Override public void destroyItem(ViewGroup collection, int position, Object view) { collection.removeView((View) view); } }
现在你需要定义三个类,它们将返回viewpager
膨胀views
。 与CpuView
类似,您将拥有MemoryView
和NetworkView
类。 他们每个人将膨胀他们各自的布局。
public class CpuView { public static View getView(Context context, ViewGroup collection) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context .LAYOUT_INFLATER_SERVICE); return inflater.inflate(R.layout.debugger_cpu_layout, collection, false); } }
最后在每个视图中都会有一个膨胀的布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#000000" android:text="CPU"/> </LinearLayout>
PS:我写这个答案的原因是因为在这里提供的所有解决scheme似乎工作正常,但他们正在膨胀PagerAdapter类本身的布局。 对于大型项目来说,如果他们有很多与膨胀的布局相关的代码,就很难维护。 现在在这个例子中,所有的视图都有独立的类和独立的布局。 所以这个项目很容易维护。