I'm having some problems when I try to replace one Fragment
with another one in a ViewPager
.
当我试图用ViewPager中的另一个片段替换一个片段时,我遇到了一些问题。
Current situation
现状
I have a ViewPager
with 3 pages, each one is a Fragment
. In first page, I have a ListView
inside a ListFragment
("FacturasFragment"). When I click on an item of that list, I use onListItemClick
method for handle that event.
我有一个3页的视图寻呼机,每个都是一个片段。在第一页中,我在一个ListFragment(“FacturasFragment”)中有一个ListView。当我单击该列表的一个项目时,我使用onListItemClick方法来处理该事件。
What I want
我想要的
- When list item is clicked, I want to replace
ListFragment
(contains a list of invoices) with anotherFragment
("DetallesFacturaFragment", contains details of invoice). - 当列表项被单击时,我想用另一个片段替换ListFragment(包含发票清单)(DetallesFacturaFragment,包含发票明细)。
- When I'm in "DetallesFacturaFragment" and press Back
Button
, should return toListFragment
. - 当我在“DetallesFacturaFragment”并按下Back按钮时,应该返回到ListFragment。
- Scrolling between pages should not change
Fragment
displayed in first one. It is, if I'm in first page with "DetallesFacturaFragment" and scroll to second page, when return to first one should continue displaying "DetallesFacturaFragment". - 在页面之间滚动不应该改变第一个页面中显示的片段。如果我在第一页写“DetallesFacturaFragment”并滚动到第二页,当返回到第一页时,应该继续显示“detallesfacturagment”。
Code
代码
FragmentActivity
FragmentActivity
public class TabsFacturasActivity extends SherlockFragmentActivity {
private MyAdapter mAdapter;
private ViewPager mPager;
private PageIndicator mIndicator;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_pager);
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = (ViewPager)findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mIndicator = (TitlePageIndicator)findViewById(R.id.indicator);
mIndicator.setViewPager(mPager);
}
private static class MyAdapter extends FragmentPagerAdapter {
private String[] titles = { "VER FACTURAS", "VER CONSUMO", "INTRODUCIR LECTURA" };
private final FragmentManager mFragmentManager;
private Fragment mFragmentAtPos0;
private Context context;
public MyAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
mFragmentManager = fragmentManager;
}
@Override
public CharSequence getPageTitle(int position) {
return titles[position];
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0: // Fragment # 0
return new FacturasFragment();
case 1: // Fragment # 1
return new ConsumoFragment();
case 2:// Fragment # 2
return new LecturaFragment();
}
return null;
}
@Override
public int getCount() {
return titles.length;
}
@Override
public int getItemPosition(Object object)
{
if (object instanceof FacturasFragment && mFragmentAtPos0 instanceof DetallesFacturaFragment)
return POSITION_NONE;
return POSITION_UNCHANGED;
}
}
}
ListFragment
ListFragment
public class FacturasFragment extends ListFragment {
private ListView lista;
private ArrayList<TuplaFacturaWS> facturas;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.activity_facturas, container, false);
facturas = myApplication.getFacturas();
lista = (ListView) view.findViewById(id.list);
MyAdapter myAdaptador = new MyAdapter(this, facturas);
setListAdapter(myAdaptador);
return view;
}
public void onListItemClick (ListView l, View v, int position, long id) {
myApplication.setFacturaActual(position);
mostrarDatosFactura();
}
private void mostrarDatosFactura() {
final DetallesFacturaFragment fragment = new DetallesFacturaFragment();
FragmentTransaction transaction = null;
transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.pager, fragment); //id of ViewPager
transaction.addToBackStack(null);
transaction.commit();
}
private class MyAdapter extends BaseAdapter {
private final FacturasFragment actividad;
private final ArrayList<TuplaFacturaWS> facturas;
public MyAdapter(FacturasFragment facturasActivity, ArrayList<TuplaFacturaWS> facturas) {
super();
this.actividad = facturasActivity;
this.facturas = facturas;
}
@Override
public View getView(int position, View convertView,
ViewGroup parent) {
LayoutInflater inflater = actividad.getLayoutInflater(null);
View view = inflater.inflate(R.layout.list_row, null, true);
//Set data to view
return view;
}
@Override
public int getCount() {
return facturas.size();
}
@Override
public Object getItem(int pos) {
return facturas.get(pos);
}
@Override
public long getItemId(int position) {
return position;
}
private OnClickListener checkListener = new OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
};
}
}
Fragment
片段
public class DetallesFacturaFragment extends SherlockFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.activity_factura, container, false);
//Set data to view
return view;
}
}
At the moment, when I click on list item, white view appears in first page. I've verified and onCreateView
method of "DetallesFacturaFragment" is executed, but nothing appears on that page.
此时,当我点击列表项时,白色视图出现在第一页。我已经验证了“DetallesFacturaFragment”的onCreateView方法,但该页面上没有显示任何内容。
And first time I click on list item, it shows that white screen. But after coming back to list, I have to click twice to a list item for showing white screen.
我第一次点击列表项时,它会显示那个白色的屏幕。但是回到列表后,我必须点击两次到一个显示白色屏幕的列表项。
I've been googling and looking at some many questions but couldn't find anyone solved with completed code.
我在谷歌上搜索并查看了许多问题,但找不到任何用完成的代码解决的问题。
2 个解决方案
#1
46
After so many hours spent, I've found correct solution modifying code in that answer.
在花了这么多时间之后,我在那个答案中找到了修改代码的正确解决方案。
It replaces Fragment
in first page of ViewPager
with another one, and if you return back from second Fragment
, first Fragment
is correctly displayed. Doesn't matter Fragment
displayed in first page, if you swipe from one page to another, it doesn't change its Fragment
.
它将ViewPager第一页中的片段替换为另一页,如果您从第二个片段返回,第一个片段将被正确显示。如果你从一个页面滑动到另一个页面,它不会改变它的片段。
Here is my code:
这是我的代码:
FragmentActivity
FragmentActivity
public class TabsFacturasActivity extends SherlockFragmentActivity {
public void onBackPressed() {
if(mPager.getCurrentItem() == 0) {
if (mAdapter.getItem(0) instanceof DetallesFacturaFragment) {
((DetallesFacturaFragment) mAdapter.getItem(0)).backPressed();
}
else if (mAdapter.getItem(0) instanceof FacturasFragment) {
finish();
}
}
}
private static class MyAdapter extends FragmentPagerAdapter {
private final class FirstPageListener implements
FirstPageFragmentListener {
public void onSwitchToNextFragment() {
mFragmentManager.beginTransaction().remove(mFragmentAtPos0)
.commit();
if (mFragmentAtPos0 instanceof FacturasFragment){
mFragmentAtPos0 = new DetallesFacturaFragment(listener);
}else{ // Instance of NextFragment
mFragmentAtPos0 = new FacturasFragment(listener);
}
notifyDataSetChanged();
}
}
private String[] titles = { "VER FACTURAS", "VER CONSUMO", "INTRODUCIR LECTURA" };
private final FragmentManager mFragmentManager;
public Fragment mFragmentAtPos0;
private Context context;
FirstPageListener listener = new FirstPageListener();
public MyAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
mFragmentManager = fragmentManager;
}
@Override
public CharSequence getPageTitle(int position) {
return titles[position];
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0: // Fragment # 0
if (mFragmentAtPos0 == null)
{
mFragmentAtPos0 = new FacturasFragment(listener);
}
return mFragmentAtPos0;
case 1: // Fragment # 1
return new ConsumoFragment();
case 2:// Fragment # 2
return new LecturaFragment();
}
return null;
}
@Override
public int getCount() {
return titles.length;
}
@Override
public int getItemPosition(Object object)
{
if (object instanceof FacturasFragment &&
mFragmentAtPos0 instanceof DetallesFacturaFragment) {
return POSITION_NONE;
}
if (object instanceof DetallesFacturaFragment &&
mFragmentAtPos0 instanceof FacturasFragment) {
return POSITION_NONE;
}
return POSITION_UNCHANGED;
}
}
}
FirstPageFragmentListener
FirstPageFragmentListener
public interface FirstPageFragmentListener {
void onSwitchToNextFragment();
}
FacturasFragment (FirstFragment)
FacturasFragment(FirstFragment)
public class FacturasFragment extends ListFragment implements FirstPageFragmentListener {
static FirstPageFragmentListener firstPageListener;
public FacturasFragment() {
}
public FacturasFragment(FirstPageFragmentListener listener) {
firstPageListener = listener;
}
public void onListItemClick (ListView l, View v, int position, long id) {
firstPageListener.onSwitchToNextFragment();
}
}
DetallesFacturaFragment (SecondFragment)
DetallesFacturaFragment(SecondFragment)
public class DetallesFacturaFragment extends SherlockFragment {
static FirstPageFragmentListener firstPageListener;
public DetallesFacturaFragment() {
}
public DetallesFacturaFragment(FirstPageFragmentListener listener) {
firstPageListener = listener;
}
public void backPressed() {
firstPageListener.onSwitchToNextFragment();
}
}
#2
0
To solve minor issue that Android suggest not using non-default constructor for fragment. You should change the constructor to something like this:
为了解决小问题,Android建议不要使用非默认构造函数进行分段。您应该将构造函数更改为以下内容:
in FacturasFragment :
在FacturasFragment:
public static FacturasFragment createInstance(FirstPageFragmentListener listener) {
FacturasFragment facturasFragment = new FacturasFragment();
facturasFragment.firstPageListener = listener;
return facturasFragment;
}
Then you can call it from getItem function like this :
然后你可以从getItem函数中调用它
mFragmentAtPos0 = FacturasFragment.createInstance(listener);
in DetallesFacturaFragment :
在DetallesFacturaFragment:
public static DetallesFacturaFragment createInstance(FirstPageFragmentListener listener) {
DetallesFacturaFragment detallesFacturaFragment= new DetallesFacturaFragment();
detallesFacturaFragment.firstPageListener = listener;
return detallesFacturaFragment;
}
Then you can call it from FirstPageListener.onSwitchToNextFragment() function like this :
然后可以从FirstPageListener.onSwitchToNextFragment()函数中调用:
mFragmentAtPos0 = DetallesFacturaFragment.createInstance(listener);
#1
46
After so many hours spent, I've found correct solution modifying code in that answer.
在花了这么多时间之后,我在那个答案中找到了修改代码的正确解决方案。
It replaces Fragment
in first page of ViewPager
with another one, and if you return back from second Fragment
, first Fragment
is correctly displayed. Doesn't matter Fragment
displayed in first page, if you swipe from one page to another, it doesn't change its Fragment
.
它将ViewPager第一页中的片段替换为另一页,如果您从第二个片段返回,第一个片段将被正确显示。如果你从一个页面滑动到另一个页面,它不会改变它的片段。
Here is my code:
这是我的代码:
FragmentActivity
FragmentActivity
public class TabsFacturasActivity extends SherlockFragmentActivity {
public void onBackPressed() {
if(mPager.getCurrentItem() == 0) {
if (mAdapter.getItem(0) instanceof DetallesFacturaFragment) {
((DetallesFacturaFragment) mAdapter.getItem(0)).backPressed();
}
else if (mAdapter.getItem(0) instanceof FacturasFragment) {
finish();
}
}
}
private static class MyAdapter extends FragmentPagerAdapter {
private final class FirstPageListener implements
FirstPageFragmentListener {
public void onSwitchToNextFragment() {
mFragmentManager.beginTransaction().remove(mFragmentAtPos0)
.commit();
if (mFragmentAtPos0 instanceof FacturasFragment){
mFragmentAtPos0 = new DetallesFacturaFragment(listener);
}else{ // Instance of NextFragment
mFragmentAtPos0 = new FacturasFragment(listener);
}
notifyDataSetChanged();
}
}
private String[] titles = { "VER FACTURAS", "VER CONSUMO", "INTRODUCIR LECTURA" };
private final FragmentManager mFragmentManager;
public Fragment mFragmentAtPos0;
private Context context;
FirstPageListener listener = new FirstPageListener();
public MyAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
mFragmentManager = fragmentManager;
}
@Override
public CharSequence getPageTitle(int position) {
return titles[position];
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0: // Fragment # 0
if (mFragmentAtPos0 == null)
{
mFragmentAtPos0 = new FacturasFragment(listener);
}
return mFragmentAtPos0;
case 1: // Fragment # 1
return new ConsumoFragment();
case 2:// Fragment # 2
return new LecturaFragment();
}
return null;
}
@Override
public int getCount() {
return titles.length;
}
@Override
public int getItemPosition(Object object)
{
if (object instanceof FacturasFragment &&
mFragmentAtPos0 instanceof DetallesFacturaFragment) {
return POSITION_NONE;
}
if (object instanceof DetallesFacturaFragment &&
mFragmentAtPos0 instanceof FacturasFragment) {
return POSITION_NONE;
}
return POSITION_UNCHANGED;
}
}
}
FirstPageFragmentListener
FirstPageFragmentListener
public interface FirstPageFragmentListener {
void onSwitchToNextFragment();
}
FacturasFragment (FirstFragment)
FacturasFragment(FirstFragment)
public class FacturasFragment extends ListFragment implements FirstPageFragmentListener {
static FirstPageFragmentListener firstPageListener;
public FacturasFragment() {
}
public FacturasFragment(FirstPageFragmentListener listener) {
firstPageListener = listener;
}
public void onListItemClick (ListView l, View v, int position, long id) {
firstPageListener.onSwitchToNextFragment();
}
}
DetallesFacturaFragment (SecondFragment)
DetallesFacturaFragment(SecondFragment)
public class DetallesFacturaFragment extends SherlockFragment {
static FirstPageFragmentListener firstPageListener;
public DetallesFacturaFragment() {
}
public DetallesFacturaFragment(FirstPageFragmentListener listener) {
firstPageListener = listener;
}
public void backPressed() {
firstPageListener.onSwitchToNextFragment();
}
}
#2
0
To solve minor issue that Android suggest not using non-default constructor for fragment. You should change the constructor to something like this:
为了解决小问题,Android建议不要使用非默认构造函数进行分段。您应该将构造函数更改为以下内容:
in FacturasFragment :
在FacturasFragment:
public static FacturasFragment createInstance(FirstPageFragmentListener listener) {
FacturasFragment facturasFragment = new FacturasFragment();
facturasFragment.firstPageListener = listener;
return facturasFragment;
}
Then you can call it from getItem function like this :
然后你可以从getItem函数中调用它
mFragmentAtPos0 = FacturasFragment.createInstance(listener);
in DetallesFacturaFragment :
在DetallesFacturaFragment:
public static DetallesFacturaFragment createInstance(FirstPageFragmentListener listener) {
DetallesFacturaFragment detallesFacturaFragment= new DetallesFacturaFragment();
detallesFacturaFragment.firstPageListener = listener;
return detallesFacturaFragment;
}
Then you can call it from FirstPageListener.onSwitchToNextFragment() function like this :
然后可以从FirstPageListener.onSwitchToNextFragment()函数中调用:
mFragmentAtPos0 = DetallesFacturaFragment.createInstance(listener);