我正在使用ViewPager
,其扩展名为PagerAdapter
。没有涉及Fragments
。我正在使用ViewPager
和常规Views
。我注意到,当浏览视图时,视图不会保持端到端的连接/连接。这就像一个无限的边缘。 (开始或结束情况没有问题,只有刷卡时的动态情况。)
如何在下一页中立即滑动?
要明确:我正在看
而我希望看到:
我注意到使用带有标签的操作栏和FragmentPagerAdapter,然后使用ViewPager和Fragments,确实有这种正确的行为。虽然它有时也会留下空白。
这是我的代码:
HelloTabWidget.java :
package com.example.hellotabwidget;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.TabHost;
import android.widget.TabWidget;
import android.widget.TextView;
public class HelloTabWidget extends Activity {
private TabHost mTabHost;
TabsAdapter mTabsAdapter;
ViewPager mViewPager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hello_tab_widget);
findViews();
}
/**
*
*/
protected void findViews() {
mViewPager = (ViewPager) findViewById(R.id.realtabcontent);
mTabHost = (TabHost) findViewById(android.R.id.tabhost);
mTabHost.setup();
HorizontalScrollView mScrollView = (HorizontalScrollView) findViewById(R.id.sv);
TabWidget mTabWidget = (TabWidget) findViewById(android.R.id.tabs);
mTabsAdapter = new TabsAdapter(this, mViewPager, mTabHost, mTabWidget, mScrollView);
TabHost.TabSpec tab;
tab = mTabHost.newTabSpec("tab_test1")
.setIndicator("TABLATURE_1_IT_IS").setContent(R.id.textview1);
mTabsAdapter.addTab(tab, R.id.textview1, "tab_test1", null);
tab = mTabHost.newTabSpec("tab_test2")
.setIndicator("TABLATURE_2_IT_IS").setContent(R.id.textview2);
mTabsAdapter.addTab(tab, R.id.textview2, "tab_test2", null);
tab = mTabHost.newTabSpec("tab_test3")
.setIndicator("TABLATURE_3_IT_IS").setContent(R.id.textview3);
mTabsAdapter.addTab(tab, R.id.textview3, "tab_test3", null);
tab = mTabHost.newTabSpec("tab_test4")
.setIndicator("TABLATURE_4_IT_IS").setContent(R.id.textview4);
mTabsAdapter.addTab(tab, R.id.textview4, "tab_test4", null);
tab = mTabHost.newTabSpec("tab_test5")
.setIndicator("TABLATURE_5_IT_IS").setContent(R.id.textview5);
mTabsAdapter.addTab(tab, R.id.textview5, "tab_test5", null);
mTabsAdapter.finalizeTabs();
mTabHost.setCurrentTab(0);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_hello_tab_widget, menu);
return true;
}
/**
* This is a helper class that implements the management of tabs and all
* details of connecting a ViewPager with associated TabHost. It relies on a
* trick. Normally a tab host has a simple API for supplying a View or
* Intent that each tab will show. This is not sufficient for switching
* between pages. So instead we make the content part of the tab host 0dp
* high (it is not shown) and the TabsAdapter supplies its own dummy view to
* show as the tab content. It listens to changes in tabs, and takes care of
* switch to the correct paged in the ViewPager whenever the selected tab
* changes.
*/
public static class TabsAdapter extends PagerAdapter implements
ViewPager.OnPageChangeListener, TabHost.OnTabChangeListener {
public static final class TabInfo {
private final Bundle args;
private final String tag;
private final int tabContentViewId;
TabInfo(Bundle args, String tag, int tabContentViewId) {
this.args = args;
this.tag = tag;
this.tabContentViewId = tabContentViewId;
}
public String getTag() {
return tag;
}
public int getTabContentViewId() {
return tabContentViewId;
}
}
private Activity mContext;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
private final ViewPager mViewPager;
private final TabHost mTabHost;
private final TabWidget mTabWidget;
private final HorizontalScrollView mScrollView;
private Runnable mTabSelector;
public TabsAdapter(Activity context, ViewPager pager, TabHost tabHost, TabWidget tabWidget, HorizontalScrollView scrollView) {
super();
mContext = context;
mTabHost = tabHost;
mTabHost.setOnTabChangedListener(this);
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
mTabWidget = tabWidget;
mScrollView = scrollView;
}
public void finalizeTabs() {
for (int i = 0; i < getCount(); i++) {
//mTabWidget.getChildAt(i).setFocusableInTouchMode(true);//TODO
}
//Keep everything in memory.
mViewPager.setOffscreenPageLimit(getCount());
}
public void addTab(TabHost.TabSpec tab, int tabContentViewId,
String tag, Bundle args) {
TabInfo info = new TabInfo(args, tag, tabContentViewId);
mTabs.add(info);
mTabHost.addTab(tab);
notifyDataSetChanged();
}
/**
* Determines whether a page View is associated with a specific key
* object as returned by instantiateItem(ViewGroup, int). This method is
* required for a PagerAdapter to function properly.
*
* @param view
* Page View to check for association with object
* @param object
* Object to check for association with view
* @return
*/
@Override
public boolean isViewFromObject(View view, Object object) {
return ((object instanceof View) && (view.getId() == ((View)object).getId()))
|| (view == object);
}
@Override
public int getCount() {
return mTabs.size();
}
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
@Override
public void onPageSelected(int position) {
mTabHost.setCurrentTab(position);
animateToTab(position);
}
@Override
public void onTabChanged(String tabId) {
for (int i = 0; i < mTabs.size(); i++) {
if (mTabs.get(i).getTag().equals(tabId)) {
mViewPager.setCurrentItem(i);
animateToTab(i);
}
}
}
public void destruct() {
mContext = null;
}
/**
* 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(android.view.ViewGroup)}.
*
* @param collection
* The containing View from which the page will be removed.
* @param position
* The page position to be removed.
* @param view
* The same object that was returned by
* {@link #instantiateItem(android.view.View, int)}.
*/
@Override
public void destroyItem(ViewGroup container, int position, Object view) {
container.removeView((TextView) view);
}
/**
* 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(android.view.ViewGroup)}.
*
* @param collection
* 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.
*/
@Override
public Object instantiateItem(ViewGroup container, int position) {
View view = mContext.findViewById(mTabs.get(position)
.getTabContentViewId());
if(view==null) return null;//Might happen if ViewPager.setOffscreenPageLimit() is not big enough
ViewGroup formerParent = (ViewGroup)view.getParent();
if(formerParent!=null && formerParent.getId()==container.getId()){
return view;
}
if(formerParent!=null){
formerParent.removeView(view);
}
container.addView(view, 0, new ViewPager.LayoutParams());
return view;
}
/**
* Called when the a change in the shown pages has been completed. At
* this point you must ensure that all of the pages have actually been
* added or removed from the container as appropriate.
*
* @param arg0
* The containing View which is displaying this adapter's
* page views.
*/
@Override
public void finishUpdate(ViewGroup container) {
super.finishUpdate(container);
}
private void animateToTab(final int position) {
final View tabView = mTabWidget.getChildAt(position);
if (mTabSelector != null) {
mScrollView.removeCallbacks(mTabSelector);
}
mTabSelector = new Runnable() {
public void run() {
final int scrollPos = tabView.getLeft()
- (mScrollView.getWidth() - tabView.getWidth()) / 2;
mScrollView.smoothScrollTo(scrollPos, 0);
mTabSelector = null;
}
};
mScrollView.post(mTabSelector);
}
}
}
activity_hello_tab_widget.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/textview50"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="some text" />
<TextView
android:id="@+id/textview60"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="some text" />
<TextView
android:id="@+id/textview70"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="some text" />
<TabHost
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="left|fill_vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_vertical"
android:orientation="vertical" >
<HorizontalScrollView
android:id="@+id/sv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:fadingEdge="horizontal"
android:fillViewport="true"
android:scrollbars="none" >
<TabWidget
android:id="@android:id/tabs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" />
</HorizontalScrollView>
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="0" >
<TextView
android:id="@+id/textview1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="this is a tab" />
<TextView
android:id="@+id/textview2"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="this is another tab" />
<TextView
android:id="@+id/textview3"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="this is a third tab" />
<TextView
android:id="@+id/textview4"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="this is a fourth tab" />
<TextView
android:id="@+id/textview5"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="this is a fifth tab" />
</FrameLayout>
<android.support.v4.view.ViewPager
android:id="@+id/realtabcontent"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1" >
</android.support.v4.view.ViewPager>
</LinearLayout>
</TabHost>
</LinearLayout>
答案 0 :(得分:1)
这是如何使用布局实现ViewPager:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MyPagerAdapter adapter = new MyPagerAdapter();
ViewPager myPager = (ViewPager) findViewById(R.id.myfivepanelpager);
myPager.setAdapter(adapter);
myPager.setCurrentItem(2);
}
将PagerAdapter定义为:
private class MyPagerAdapter extends PagerAdapter {
public int getCount() {
return 5;
}
public Object instantiateItem(View collection, int position) {
LayoutInflater inflater = (LayoutInflater) collection.getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
int resId = 0;
switch (position) {
case 0:
resId = R.layout.farleft;
break;
case 1:
resId = R.layout.left;
break;
case 2:
resId = R.layout.middle;
break;
case 3:
resId = R.layout.right;
break;
case 4:
resId = R.layout.farright;
break;
}
View view = inflater.inflate(resId, null);
((ViewPager) collection).addView(view, 0);
return view;
}
@Override
public void destroyItem(View arg0, int arg1, Object arg2) {
((ViewPager) arg0).removeView((View) arg2);
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == ((View) arg1);
}
@Override
public Parcelable saveState() {
return null;
}
}
当我忘记我的心灵感应头盔,并且无法阅读你的代码时,那里一定有些错误!
从这个简单的例子开始,尝试找出实施中的错误。
答案 1 :(得分:0)
问题是我在instantiateItem()
重新审视了观点。我的猜测是我在错误的时刻从父母那里删除它们,因此白色无限边缘(没有下一个视图)。我需要将TextViews
作为ViewPager
的子项进行静态定义,将其从FrameLayout
中移除,但留在虚拟TextView
中。然后不再需要从父项中删除。
这是我的固定代码:
<强> HelloTabWidget.java 强>:
package com.example.hellotabwidget;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.TabHost;
import android.widget.TabWidget;
import android.widget.TextView;
public class HelloTabWidget extends Activity {
private TabHost mTabHost;
TabsAdapter mTabsAdapter;
ViewPager mViewPager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hello_tab_widget);
findViews();
}
/**
*
*/
protected void findViews() {
mViewPager = (ViewPager) findViewById(R.id.realtabcontent);
mTabHost = (TabHost) findViewById(android.R.id.tabhost);
mTabHost.setup();
HorizontalScrollView mScrollView = (HorizontalScrollView) findViewById(R.id.sv);
TabWidget mTabWidget = (TabWidget) findViewById(android.R.id.tabs);
mTabsAdapter = new TabsAdapter(this, mViewPager, mTabHost, mTabWidget, mScrollView);
TabHost.TabSpec tab;
tab = mTabHost.newTabSpec("tab_test1")
.setIndicator("TABLATURE_1_IT_IS").setContent(R.id.dummy_textview);
mTabsAdapter.addTab(tab, R.id.textview1, "tab_test1", null);
tab = mTabHost.newTabSpec("tab_test2")
.setIndicator("TABLATURE_2_IT_IS").setContent(R.id.textview2);
mTabsAdapter.addTab(tab, R.id.textview2, "tab_test2", null);
tab = mTabHost.newTabSpec("tab_test3")
.setIndicator("TABLATURE_3_IT_IS").setContent(R.id.textview3);
mTabsAdapter.addTab(tab, R.id.textview3, "tab_test3", null);
tab = mTabHost.newTabSpec("tab_test4")
.setIndicator("TABLATURE_4_IT_IS").setContent(R.id.textview4);
mTabsAdapter.addTab(tab, R.id.textview4, "tab_test4", null);
tab = mTabHost.newTabSpec("tab_test5")
.setIndicator("TABLATURE_5_IT_IS").setContent(R.id.textview5);
mTabsAdapter.addTab(tab, R.id.textview5, "tab_test5", null);
mTabsAdapter.finalizeTabs();
mTabHost.setCurrentTab(0);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_hello_tab_widget, menu);
return true;
}
/**
* This is a helper class that implements the management of tabs and all
* details of connecting a ViewPager with associated TabHost. It relies on a
* trick. Normally a tab host has a simple API for supplying a View or
* Intent that each tab will show. This is not sufficient for switching
* between pages. So instead we make the content part of the tab host 0dp
* high (it is not shown) and the TabsAdapter supplies its own dummy view to
* show as the tab content. It listens to changes in tabs, and takes care of
* switch to the correct paged in the ViewPager whenever the selected tab
* changes.
*/
public static class TabsAdapter extends PagerAdapter implements
ViewPager.OnPageChangeListener, TabHost.OnTabChangeListener {
public static final class TabInfo {
private final Bundle args;
private final String tag;
private final int tabContentViewId;
TabInfo(Bundle args, String tag, int tabContentViewId) {
this.args = args;
this.tag = tag;
this.tabContentViewId = tabContentViewId;
}
public String getTag() {
return tag;
}
public int getTabContentViewId() {
return tabContentViewId;
}
}
private Activity mContext;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
private final ViewPager mViewPager;
private final TabHost mTabHost;
private final TabWidget mTabWidget;
private final HorizontalScrollView mScrollView;
private Runnable mTabSelector;
public TabsAdapter(Activity context, ViewPager pager, TabHost tabHost, TabWidget tabWidget, HorizontalScrollView scrollView) {
super();
mContext = context;
mTabHost = tabHost;
mTabHost.setOnTabChangedListener(this);
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
mTabWidget = tabWidget;
mScrollView = scrollView;
}
public void finalizeTabs() {
for (int i = 0; i < getCount(); i++) {
//mTabWidget.getChildAt(i).setFocusableInTouchMode(true);//TODO
}
//Keep everything in memory.
mViewPager.setOffscreenPageLimit(getCount());
}
public void addTab(TabHost.TabSpec tab, int tabContentViewId,
String tag, Bundle args) {
TabInfo info = new TabInfo(args, tag, tabContentViewId);
mTabs.add(info);
mTabHost.addTab(tab);
notifyDataSetChanged();
}
/**
* Determines whether a page View is associated with a specific key
* object as returned by instantiateItem(ViewGroup, int). This method is
* required for a PagerAdapter to function properly.
*
* @param view
* Page View to check for association with object
* @param object
* Object to check for association with view
* @return
*/
@Override
public boolean isViewFromObject(View view, Object object) {
return ((object instanceof View) && (view.getId() == ((View)object).getId()))
|| (view == object);
}
@Override
public int getCount() {
return mTabs.size();
}
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
@Override
public void onPageSelected(int position) {
mTabHost.setCurrentTab(position);
animateToTab(position);
}
@Override
public void onTabChanged(String tabId) {
for (int i = 0; i < mTabs.size(); i++) {
if (mTabs.get(i).getTag().equals(tabId)) {
mViewPager.setCurrentItem(i);
animateToTab(i);
}
}
}
public void destruct() {
mContext = null;
}
/**
* 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(android.view.ViewGroup)}.
*
* @param collection
* The containing View from which the page will be removed.
* @param position
* The page position to be removed.
* @param view
* The same object that was returned by
* {@link #instantiateItem(android.view.View, int)}.
*/
@Override
public void destroyItem(ViewGroup container, int position, Object view) {
container.removeView((TextView) view);
}
/**
* 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(android.view.ViewGroup)}.
*
* @param collection
* 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.
*/
@Override
public Object instantiateItem(ViewGroup container, int position) {
View view = mContext.findViewById(mTabs.get(position)
.getTabContentViewId());
container.addView(view, 0, new ViewPager.LayoutParams());
return view;
}
/**
* Called when the a change in the shown pages has been completed. At
* this point you must ensure that all of the pages have actually been
* added or removed from the container as appropriate.
*
* @param arg0
* The containing View which is displaying this adapter's
* page views.
*/
@Override
public void finishUpdate(ViewGroup container) {
super.finishUpdate(container);
}
private void animateToTab(final int position) {
final View tabView = mTabWidget.getChildAt(position);
if (mTabSelector != null) {
mScrollView.removeCallbacks(mTabSelector);
}
mTabSelector = new Runnable() {
public void run() {
final int scrollPos = tabView.getLeft()
- (mScrollView.getWidth() - tabView.getWidth()) / 2;
mScrollView.smoothScrollTo(scrollPos, 0);
mTabSelector = null;
}
};
mScrollView.post(mTabSelector);
}
}
}
<强> activity_hello_tab_widget.xml 强>:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/textview50"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="some text" />
<TextView
android:id="@+id/textview60"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="some text" />
<TextView
android:id="@+id/textview70"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="some text" />
<TabHost
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="left|fill_vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_vertical"
android:orientation="vertical" >
<HorizontalScrollView
android:id="@+id/sv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:fadingEdge="horizontal"
android:fillViewport="true"
android:scrollbars="none" >
<TabWidget
android:id="@android:id/tabs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" />
</HorizontalScrollView>
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="0" >
<TextView
android:id="@+id/dummy_textview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="dummy" />
</FrameLayout>
<android.support.v4.view.ViewPager
android:id="@+id/realtabcontent"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1" >
<TextView
android:id="@+id/textview1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="this is a tab" />
<TextView
android:id="@+id/textview2"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="this is another tab" />
<TextView
android:id="@+id/textview3"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="this is a third tab" />
<TextView
android:id="@+id/textview4"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="this is a fourth tab" />
<TextView
android:id="@+id/textview5"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="this is a fifth tab" />
</android.support.v4.view.ViewPager>
</LinearLayout>
</TabHost>
</LinearLayout>
请注意,此代码可以进一步美化,并且可能包含一些小的过量。另外,最后,我没有使用静态视图,而是整合了Waza_Be的布局膨胀概念,因为它更接近Fragments
而实际上没有Fragments
,并且分离长布局似乎是好主意。功能与之相同。