gpt4 book ai didi

Android:替换 View 寻呼机中的 fragment

转载 作者:行者123 更新时间:2023-11-30 02:49:46 25 4
gpt4 key购买 nike

我在名为 TicketManagementActivity 的 Activity 内的 View 寻呼机中有两个 fragment SearchFragmentCreateFragment。现在,当用户按下 SearchFragment 中的搜索按钮时,我希望将 SearchFragment 替换为 SearchResultFragment。然后我应该能够在 ViewPager 中的 SeachResultFragmentCreateFragment 之间滑动。此外,当我从 SearchResultFragment 返回时,我应该返回到 SearchFragment

现在,当我按下按钮时,我得到一个空白屏幕,而不是 SearchResultFragment 的布局。当我按回键时,我到达了 SearchFragment,但现在我必须单击该按钮两次才能出现空白屏幕。现在,在双击后出现空白屏幕后,每当我滑动到 CreateFragment 选项卡时,我都会看到一个空白屏幕,而不是 CreateFragment 布局。

我看了很多关于 SO 的问题,但似乎没有一个对我有用。最有用的似乎是 this question 中的前两个答案。 ,但第一个答案不能处理后压,我也无法实现它。第二个答案似乎非常可行,但我遇到了下面提到的错误。

我的主要TicketManagemementActivity:

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) {


}

}

我的 activity_ticket_management.xml 是在工单管理 Activity 的 onCreate 中设置的布局,只包含 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>

我的 TabsPagerAdapter 类扩展了 FragmentPagerAdapter:

public class TabsPagerAdapter extends FragmentPagerAdapter {

public TabsPagerAdapter(android.support.v4.app.FragmentManager fm) {
super(fm);
}

@Override
public Fragment getItem(int index) {

switch (index) {
case 0:
// Top Rated fragment activity
return new SearchFragment();
case 1:
// Games fragment activity
return new CreateFragment();

}

return null;
}

@Override
public int getCount() {
// get item count - equal to number of tabs
return 2;
}

}

我的 SearchFragment 的相关部分:

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();
}

}

}

如果我使用 getChildFragmentManager 而不是第二个答案中提到的 getFragmentManager 我会得到

06-25 06:55:32.045: E/AndroidRuntime(2797): java.lang.IllegalArgumentException: No view found for id 0x7f06003c (com.amberroad.sigmaticket:id/pager) for fragment SearchResultFragment{b2fed358 #0 id=0x7f06003c}

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

最佳答案

Kartik,准备好对你冗长的问题进行冗长的回答。在 viewpager 中替换 fragment 非常复杂,但很有可能,而且看起来非常巧妙。首先,您需要让 viewpager 本身处理 fragment 的删除和添加。发生的事情是当您替换 SearchFragment 内的 fragment 时,您的 viewpager 保留其 fragment View 。所以你最终得到一个空白页面,因为当你尝试替换它时 SearchFragment 被删除了。

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

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

}

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

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 是一个“灵活”的 fragment 。它可以采用您提供的任何 fragment 类型。这使它成为您最好的 friend ,可以将位置 0 的 fragment 更改为您想要的 fragment 。 2) 注意放置在 'newInstance(listener) 构造函数中的监听器。这些是您调用fragment0Changed(String newFragmentIdentification)` 的方式。以下代码显示了如何在 fragment 内创建监听器。

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 中的代码将您的 fragment 切换到位置零 fragAt0 以成为新的 searchResultFragment。在 viewpager 发挥作用之前,您还需要添加两个小部分。

一个是在 viewpager 的 getItem 覆盖方法中。

@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();

}

现在如果没有这最后一 block ,您仍然会得到一个空白页。有点蹩脚,但它是 viewPager 的重要组成部分。您必须覆盖 viewpager 的 getItemPosition 方法。通常此方法将返回 POSITION_UNCHANGED,它告诉 viewpager 保持所有内容不变,因此永远不会调用 getItem 将新 fragment 放置在页面上。这是您可以做的事情的示例

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

}

正如我所说,代码非常复杂,但您基本上必须根据自己的情况创建自定义适配器。我提到的事情将使更改 fragment 成为可能。吸收所有内容可能需要很长时间,所以我会耐心等待,但这一切都是有道理的。花时间是完全值得的,因为它可以制作一个非常漂亮的应用程序。

这是处理后退按钮的关键部分。你把它放在你的 MainActivity 中

 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();
}
}



}

您需要在 FragmentSearchResults 中创建一个名为 backPressed() 的方法来调用 fragment0changed。这与我之前展示的代码一起将处理按下后退按钮。祝您使用更改 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

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

关于Android:替换 View 寻呼机中的 fragment ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24407768/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com