Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/192.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android:替换视图寻呼机中的片段_Android_Android Fragments_Android Viewpager - Fatal编程技术网

Android:替换视图寻呼机中的片段

Android:替换视图寻呼机中的片段,android,android-fragments,android-viewpager,Android,Android Fragments,Android Viewpager,在名为TicketManagementActivity的活动内的视图页面中,我有两个片段SearchFragment和CreateFragment。现在,当用户按下SearchFragment中的搜索按钮时,我希望将SearchFragment替换为SearchResultFragment。然后,我应该能够在ViewPager中的SeachResultFragment和CreateFragment之间滑动。另外,当我从SearchResultFragment按back键时,我应该返回到Searc

在名为
TicketManagementActivity
的活动内的视图页面中,我有两个片段
SearchFragment
CreateFragment
。现在,当用户按下
SearchFragment
中的搜索按钮时,我希望将
SearchFragment
替换为
SearchResultFragment
。然后,我应该能够在
ViewPager
中的
SeachResultFragment
CreateFragment
之间滑动。另外,当我从
SearchResultFragment
按back键时,我应该返回到
SearchFragment

现在,当我按下按钮时,会看到一个空白屏幕,而不是
SearchResultFragment
的布局。当我回过头去看<代码>搜索片段,但现在我不得不点击按钮两次,空白屏幕就会出现。现在,在双击后的空白屏幕之后,每当我点击“代码> >创建片段>代码>标签时,就会得到一个空白屏幕,而不是<代码>创建片段版式。

我看了很多问题,但似乎没有一个对我有用。最有用的似乎是中的前两个答案,但第一个答案无法处理背压,我也无法实现它。第二个答案似乎很容易实现,但我在下面提到了一些错误

我的主要
票证管理活动

public class TicketManagementActivity extends FragmentActivity implements
ActionBar.TabListener {

    ViewPager viewPager;
    TabsPagerAdapter adapter;
    ActionBar actionBar;

    String[] tabs={"Search", "Create"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ticket_management);

        viewPager=(ViewPager)findViewById(R.id.pager);
        actionBar=getActionBar();
        adapter=new TabsPagerAdapter(getSupportFragmentManager());

        viewPager.setAdapter(adapter);
        actionBar.setHomeButtonEnabled(false);
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        for(String tab_name : tabs){
            actionBar.addTab(actionBar.newTab().setText(tab_name).setTabListener(this));
        }
        viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

            @Override
            public void onPageSelected(int position) {
                // on changing the page
                // make respected tab selected
                actionBar.setSelectedNavigationItem(position);
            }

            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) {
            }

            @Override
            public void onPageScrollStateChanged(int arg0) {
            }
        });

    }
  //removed methods for menu creation and filling and placeholder fragment for brevity on SO
    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {

        viewPager.setCurrentItem(tab.getPosition());
    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {


    }

    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) {


    }

}
My
activity\u ticket\u management.xml
是在onCreate of ticket management活动中设置的布局,它只包含viewpager

<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
我的
搜索片段的相关部分

public class SearchFragment extends Fragment implements View.OnClickListener    {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.fragment_search, container, false);
        .
        .//some widget initializations
        .
        return rootView;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.ticket_search_btn: searchSigmaTickets();
                                     break;
        }
    }

    public void searchSigmaTickets(){
        .
        .
        .
        .//some operations
        .

        new SearchAsyncTask().execute();

        }
    }

    private class SearchAsyncTask extends AsyncTask<Void, Void, Void>{

        protected Void doInBackground(Void... params){
            .
            .//some more operation
            .
        }
        protected void onPostExecute(Void param){
            Fragment newFragment = new SearchResultFragment();
            //Here I use getFragmentManager and not getChildFragmentManager
            FragmentTransaction transaction = getFragmentManager().beginTransaction();
            //HERE I try to replace the fragment. I'm not sure what id to pass, I pass the id of the main veiwpager in ticketmanagement activity
            transaction.replace(R.id.pager, newFragment);
            transaction.addToBackStack(null);
            transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);

            transaction.commit();
        }

    }

}

很抱歉问了这么长的问题,我该如何解决这个问题呢?

Kartik,准备好回答你的长问题。更换viewpager中的片段非常复杂,但很有可能,而且看起来非常光滑。首先,您需要让viewpager本身处理片段的删除和添加。当您替换SearchFragment内部的片段时,viewpager将保留其片段视图。因此,您将得到一个空白页面,因为当您尝试替换它时,SearchFragment将被删除

解决方案是在viewpager内部创建一个监听器,该监听器将处理在其外部所做的更改,因此首先将此代码添加到适配器的底部

public interface nextFragmentListener {
    public void fragment0Changed(String newFragmentIdentification);

}
然后,您需要在viewpager中创建一个私有类,当您想要更改片段时,该类将成为
侦听器。例如,您可以添加如下内容。请注意,它实现了刚刚创建的接口。因此,无论何时调用此方法,它都将在下面的类中运行代码

private final class fragmentChangeListener implements nextFragmentListener {


    @Override
    public void fragment0Changed(String fragment) {
        //I will explain the purpose of fragment0 in a moment
                    fragment0 = fragment;
                    manager.beginTransaction().remove(fragAt0).commit();

        switch (fragment){
            case "searchFragment":
                fragAt0 = SearchFragment.newInstance(listener);
                break;
            case "searchResultFragment":
                fragAt0 = Fragment_Table.newInstance(listener);
                break;
                    }            

        notifyDataSetChanged();
    }
这里需要指出两件主要的事情:1)fragAt0是一个“灵活”的片段。它可以接受你给它的任何片段类型。这允许它成为您最好的朋友,将位置0处的碎片更改为您想要的碎片。2) 请注意放置在“newInstance(listener)
构造函数中的侦听器。以下是如何调用
fragment0Changed(String newFragmentIdentification)`。下面的代码显示了如何在片段内部创建侦听器

static nextFragmentListener listenerSearch;

    public static Fragment_Journals newInstance(nextFragmentListener listener){
        listenerSearch = listener;
        return new Fragment_Journals();

    }
然后,您可以在onPostExecute中调用更改

private class SearchAsyncTask extends AsyncTask<Void, Void, Void>{

    protected Void doInBackground(Void... params){
        .
        .//some more operation
        .
    }
    protected void onPostExecute(Void param){

        listenerSearch.fragment0Changed("searchResultFragment");
    }

}
现在如果没有这最后一块,你仍然会得到一个空白页。有点蹩脚,但它是viewPager的一个重要部分。您必须覆盖viewpager的
getItemPosition
方法。通常,此方法将返回
POSITION\u UNCHANGED
,告知viewpager保持所有内容不变,因此永远不会调用
getItem
将新片段放置在页面上。这里有一个你可以做的例子

public int getItemPosition(Object object)
    {
        //object is the current fragment displayed at position 0.  
        if(object instanceof SearchFragment && fragAt0 instanceof SearchResultFragment){
            return POSITION_NONE;
        //this condition is for when you press back
         }else if{(object instanceof SearchResultFragment && fragAt0 instanceof SearchFragment){
              return POSITION_NONE;
         }
            return POSITION_UNCHANGED

}
正如我所说,代码非常复杂,但基本上您必须为您的情况创建一个自定义适配器。我提到的事情将使改变片段成为可能。这可能需要很长时间才能把所有的东西都泡进去,所以我会有耐心,但这一切都是有意义的。花点时间是完全值得的,因为它可以生成一个看起来非常光滑的应用程序

这是处理后退按钮的金块。你把这个放在你的主要活动里

 public void onBackPressed() {
    if(mViewPager.getCurrentItem() == 0) {
        if(pagerAdapter.getItem(0) instanceof FragmentSearchResults){
            ((FragmentSearchResults) pagerAdapter.getItem(0)).backPressed();
        }else if (pagerAdapter.getItem(0) instanceof FragmentSearch) {
            finish();
        }
    }



}
您需要在调用fragment0changed的FragmentSearchResults内部创建一个名为
backPressed()
的方法。这与我之前显示的代码相结合,将处理按下后退按钮的问题。祝您更改viewpager的代码好运。这需要大量的工作,而且据我所知,没有任何快速的适应。正如我所说,您基本上是在创建一个自定义的viewpager适配器,并让它使用侦听器处理所有必要的更改

下面是TabsPagerAdapter的全部代码

public class TabsPagerAdapter extends FragmentPagerAdapter{

Fragment fragAt0;
fragmentChangeListener listener = new fragmentChangeListener();
FragmentManager manager;

static String fragment0 = "SearchFragment";

//when you declare the viewpager in your adapter, pass it the fragment manager.
public viewPager(FragmentManager fm) {
    super(fm);
    manager = fm;

}

private final class fragmentChangeListener implements nextFragmentListener {


@Override
public void fragment0Changed(String fragment) {
    //I will explain the purpose of fragment0 in a moment
                fragment0 = fragment;
                manager.beginTransaction().remove(fragAt0).commit();

    switch (fragment){
        case "searchFragment":
            fragAt0 = SearchFragment.newInstance(listener);
            break;
        case "searchResultFragment":
            fragAt0 = Fragment_Table.newInstance(listener);
            break;
                }





    notifyDataSetChanged();
}
}

   @Override
public Fragment getItem(int index) {

switch (index) {
case 0:
    //this is where it will "remember" which fragment you have just selected. the key is to set a static String fragment at the top of your page that will hold the position that you had just selected.  

    if(fragAt0 == null){

        switch(fragment0){
        case "searchFragment":
            fragAt0 = FragmentSearch.newInstance(listener);
            break;
        case "searchResultsFragment":
            fragAt0 = FragmentSearchResults.newInstance(listener);
            break;
        }
    }
    return fragAt0;
case 1:
    // Games fragment activity
    return new CreateFragment();

}

@Override
public int getCount() {
    // Show 3 total pages.
    return 3;
}

@Override
public CharSequence getPageTitle(int position) {
    Locale l = Locale.getDefault();
    String[] tab = {"Journals", "Charts", "Website"};
    switch (position) {
        case 0:
            return tab[0].toUpperCase(l);
        case 1:
            return tab[1].toUpperCase(l);
        case 2:
            return tab[2].toUpperCase(l);
    }
    return null;
}

public int getItemPosition(Object object)
{
    //object is the current fragment displayed at position 0.  
    if(object instanceof SearchFragment && fragAt0 instanceof SearchResultFragment){
        return POSITION_NONE;
    //this condition is for when you press back
     }else if{(object instanceof SearchResultFragment && fragAt0 instanceof SearchFragment){
          return POSITION_NONE;
     }
        return POSITION_UNCHANGED
}


}

@Hardik我想在寻呼机中将SearchFragment替换为SearchResultFragment,当我按back时,SearchResultFragment应该替换为SearchFragment。您还可以查看此链接以了解更多详细信息。我发现,我将在一段时间内尝试它,它只是将一个带有framelayout的伪根片段作为第一个选项卡中的片段放在布局中,然后在它的onCreateView本身中执行一个事务,用searchFragment替换伪根片段的框架布局。然后按下按钮,再次用searchResultFragment替换虚拟对象的框架布局。当我尝试此操作时,searchFragment确实出现了,它立即替换了虚拟片段,但按下按钮后,我看到了黑屏。我会看看这是否是可修复的,如果不是,我会尝试你的方法。我会尝试实现这一点,但我有一些疑问,当你说把这段代码放在fragmentChangeListener类和getItem和getItemPosition方法的视图分页器中时,你的意思是放在扩展FragmentPagerAdapter的TabsPageAdapter中?此外,在这个方法中,我们不在任何地方使用片段事务?所有的片段更改都是由侦听器完成的?在私有侦听器类中,fragment0和fragAt0是未声明的。我想他们是
public int getItemPosition(Object object)
    {
        //object is the current fragment displayed at position 0.  
        if(object instanceof SearchFragment && fragAt0 instanceof SearchResultFragment){
            return POSITION_NONE;
        //this condition is for when you press back
         }else if{(object instanceof SearchResultFragment && fragAt0 instanceof SearchFragment){
              return POSITION_NONE;
         }
            return POSITION_UNCHANGED

}
 public void onBackPressed() {
    if(mViewPager.getCurrentItem() == 0) {
        if(pagerAdapter.getItem(0) instanceof FragmentSearchResults){
            ((FragmentSearchResults) pagerAdapter.getItem(0)).backPressed();
        }else if (pagerAdapter.getItem(0) instanceof FragmentSearch) {
            finish();
        }
    }



}
public class TabsPagerAdapter extends FragmentPagerAdapter{

Fragment fragAt0;
fragmentChangeListener listener = new fragmentChangeListener();
FragmentManager manager;

static String fragment0 = "SearchFragment";

//when you declare the viewpager in your adapter, pass it the fragment manager.
public viewPager(FragmentManager fm) {
    super(fm);
    manager = fm;

}

private final class fragmentChangeListener implements nextFragmentListener {


@Override
public void fragment0Changed(String fragment) {
    //I will explain the purpose of fragment0 in a moment
                fragment0 = fragment;
                manager.beginTransaction().remove(fragAt0).commit();

    switch (fragment){
        case "searchFragment":
            fragAt0 = SearchFragment.newInstance(listener);
            break;
        case "searchResultFragment":
            fragAt0 = Fragment_Table.newInstance(listener);
            break;
                }





    notifyDataSetChanged();
}
}

   @Override
public Fragment getItem(int index) {

switch (index) {
case 0:
    //this is where it will "remember" which fragment you have just selected. the key is to set a static String fragment at the top of your page that will hold the position that you had just selected.  

    if(fragAt0 == null){

        switch(fragment0){
        case "searchFragment":
            fragAt0 = FragmentSearch.newInstance(listener);
            break;
        case "searchResultsFragment":
            fragAt0 = FragmentSearchResults.newInstance(listener);
            break;
        }
    }
    return fragAt0;
case 1:
    // Games fragment activity
    return new CreateFragment();

}

@Override
public int getCount() {
    // Show 3 total pages.
    return 3;
}

@Override
public CharSequence getPageTitle(int position) {
    Locale l = Locale.getDefault();
    String[] tab = {"Journals", "Charts", "Website"};
    switch (position) {
        case 0:
            return tab[0].toUpperCase(l);
        case 1:
            return tab[1].toUpperCase(l);
        case 2:
            return tab[2].toUpperCase(l);
    }
    return null;
}

public int getItemPosition(Object object)
{
    //object is the current fragment displayed at position 0.  
    if(object instanceof SearchFragment && fragAt0 instanceof SearchResultFragment){
        return POSITION_NONE;
    //this condition is for when you press back
     }else if{(object instanceof SearchResultFragment && fragAt0 instanceof SearchFragment){
          return POSITION_NONE;
     }
        return POSITION_UNCHANGED
public interface nextFragmentListener {
    public void fragment0Changed(String fragment);