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) {
}
}
Myactivity\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);