草庐IT

android - 查看页面 : If page get removed the next pages content gets the removed pages content

coder 2023-12-05 原文

(如果有人需要更多信息或更好的描述,请告诉我)

您好,我从这里添加了 viewPagerLibrary:http://viewpagerindicator.com/#introduction今天在我的项目中。

不,我遇到了一个非常奇怪的问题: 如果我添加一个网站或页面(让我们在接下来的几行中称它为网站)并再次删除它,一切都很好。但是,如果我尝试添加一个不同的页面(这些页面是实现 BaseFragment 类的不同 Fragements),则会显示第一页的内容。 如果我添加几页并删除这些页面之间的一页,也会发生同样的事情。被删除页面之后的页面现在显示被删除页面的内容。

此错误的示例: 现在的问题是。如果我在 FragmentB 之后添加 FragmentA,然后我删除 FragmentA,FragmentB 获取 FragmentA 的 View /内容。奇怪的是,对象是正确的(因此适配器返回正确的对象)并且标题也是正确的。

在我的 main 中,我以这种方式创建我的寻呼机、指示器和适配器:

    Cfg.mAdapter = new FragmentAdapter(getSupportFragmentManager());

    Cfg.mPager = (ViewPager)findViewById(R.id.pager);
    Cfg.mPager.setAdapter(Cfg.mAdapter);

    Cfg.mIndicator = (TabPageIndicator)findViewById(R.id.indicator);
    Cfg.mIndicator.setViewPager(Cfg.mPager);

    //We set this on the indicator, NOT the pager
    Cfg.mIndicator.setOnPageChangeListener(TabHelper.onPageChangeListener);

(Cfg是一个静态文件,用来存储那些东西以供使用)

我的 BaseFragment 如下所示:

public class BaseFragment extends Fragment{

    public static int FILE_FRAGMENT = 0;
    public static int FTP_FRAGMENT = 1;
    public static int ADDFTP_FRAGMENT = 2;
    public static int PREVIEW_FRAGMENT = 3;
    public static int CSS_FRAGMENT = 4;
    public static int BOOKS_FRAGMENT = 5;
    public static int SNIPPETS_FRAGMENT = 6;

    //private int id;
    private int typ;
    private String title;

    public int getTyp() {
        return typ;
    }

    public void setTyp(int typ) {
        this.typ = typ;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

其中一个 fragment 看起来像这样(我认为其他 fragment 没有区别):

public class FtpFragment extends BaseFragment {
    private static RowLayout rowLayout_view;

    public FtpFragment() {
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        init_data();
    }

    public static void init_data()
    {
        //Remove child for update
        rowLayout_view.removeAllViews();

        List<FtpData> ftps = FtpStorage.getInstance().getFtps();

        if (ftps != null) {
            for (FtpData f : ftps) {
                View inflatedView;
                inflatedView = View.inflate(Cfg.ctx, R.layout.ftp, null);
                inflatedView.setOnClickListener(button_ftp_listener);
                inflatedView.setOnLongClickListener(button_ftp_longClickListener);
                inflatedView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, Converter.convertFromDPtoPixel(160.0f)));
                inflatedView.setTag(f);
                inflatedView.findViewById(R.id.book_imageview).setBackgroundDrawable(
                                Cfg.ctx.getResources().getDrawable(R.drawable.nopreview));


                ((TextView) inflatedView.findViewById(R.id.book_textview)).setText(f.nickname);

                rowLayout_view.addView(inflatedView);
            }
        }
    }

    @Override

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_ftp, container, false);
    rowLayout_view = (RowLayout) v.findViewById(R.id.rowLayout_ftps);
    return v;
}

@Override
public String getTitle() {
    return "FTPs";
}

@Override
public int getTyp() {
    return BaseFragment.FTP_FRAGMENT;
}

@Override
public void setTyp(int typ) {
    super.setTyp(typ);
}

要删除或添加一个页面,我称之为:

public static void addNewTab(BaseFragment fragment)
{
    Cfg.mAdapter.addItem(fragment);
    Cfg.mPager.setCurrentItem(Cfg.mAdapter.getCount());
    Cfg.mIndicator.notifyDataSetChanged();
}

public static void deleteActTab()
{
    Cfg.mAdapter.removeItem(Cfg.mAdapter.getActPage());
    Cfg.mIndicator.notifyDataSetChanged();
}

那是适配器:

public class FragmentAdapter extends FragmentPagerAdapter implements TitleProvider{
    public List<BaseFragment> fragments = new LinkedList<BaseFragment>();

    private int actPage;

    public FragmentAdapter(FragmentManager fm) {
        super(fm);
    }


    public void setActPage(int actPage) {
        Lg.d("setActPage: " + actPage + " : " + fragments.get(actPage).toString());
        this.actPage = actPage; 
    }

    public void addItem(BaseFragment fragment)
    {
        Lg.d("addItem: " + fragment.toString());
        fragments.add(fragment);
    }

    public void removeItem(int index)
    {
        if(index < getCount()){
            Lg.d("RemoveItem: " + index + " : " + fragments.get(index).toString());
            fragments.remove(index);
        }
    }

    public BaseFragment getActFragment()
    {
        return getItem(getActPage());
    }

    public int getActPage() {
        return actPage;
    }

    @Override
    public BaseFragment getItem(int position) {
        if(position < getCount())
        {
            Lg.v("getItem: " + fragments.get(position));
            return fragments.get(position);
        }
        else
            return null;
    }

    @Override
    public int getCount() {
        return fragments.size();
    }

    @Override
    public String getTitle(int position) {
        Lg.v("Get Title: " + fragments.get(position).getTitle());
        return fragments.get(position).getTitle();
    }

}

是的,我希望有人能帮助我。

如果我忘记了什么,请告诉我。

提前致谢, 迈克

最佳答案

好吧,我现在已经以一种骇人听闻的方式解决了我的问题,但是它确实有效 ;)。如果有人可以改进我的解决方案,请告诉我。对于我的新解决方案,我现在使用 CustomFragmentStatePagerAdapter 但它不会像它应该的那样保存状态并将所有 fragment 存储在列表中。如果用户有超过 50 个 fragment ,这可能会导致内存问题,就像普通的 FragmentPagerAdapter 一样。如果有人可以在不删除我的修复程序的情况下将状态事物添加回我的解决方案,那就太好了。谢谢。

这是我的CustomFragmentStatePagerAdapter.java

package com.tundem.webLab.Adapter;

import java.util.ArrayList;

import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.PagerAdapter;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;

public abstract class CustomFragmentStatePagerAdapter extends PagerAdapter {
    private static final String TAG = "FragmentStatePagerAdapter";
    private static final boolean DEBUG = false;

    private final FragmentManager mFragmentManager;
    private FragmentTransaction mCurTransaction = null;

    public ArrayList<Fragment.SavedState> mSavedState = new ArrayList<Fragment.SavedState>();
    public ArrayList<Fragment> mFragments = new ArrayList<Fragment>();
    private Fragment mCurrentPrimaryItem = null;

    public CustomFragmentStatePagerAdapter(FragmentManager fm) {
        mFragmentManager = fm;
    }

    /**
     * Return the Fragment associated with a specified position.
     */
    public abstract Fragment getItem(int position);

    @Override
    public void startUpdate(ViewGroup container) {}

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        // If we already have this item instantiated, there is nothing
        // to do. This can happen when we are restoring the entire pager
        // from its saved state, where the fragment manager has already
        // taken care of restoring the fragments we previously had instantiated.

        // DONE Remove of the add process of the old stuff
        /* if (mFragments.size() > position) { Fragment f = mFragments.get(position); if (f != null) { return f; } } */

        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }

        Fragment fragment = getItem(position);
        if (DEBUG)
            Log.v(TAG, "Adding item #" + position + ": f=" + fragment);
        if (mSavedState.size() > position) {
            Fragment.SavedState fss = mSavedState.get(position);
            if (fss != null) {
                try // DONE: Try Catch
                {
                    fragment.setInitialSavedState(fss);
                } catch (Exception ex) {
                    // Schon aktiv (kA was das heißt xD)
                }
            }
        }
        while (mFragments.size() <= position) {
            mFragments.add(null);
        }
        fragment.setMenuVisibility(false);
        mFragments.set(position, fragment);
        mCurTransaction.add(container.getId(), fragment);

        return fragment;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        Fragment fragment = (Fragment) object;

        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }
        mCurTransaction.remove(fragment);

        /*if (mCurTransaction == null) { mCurTransaction = mFragmentManager.beginTransaction(); } if (DEBUG) Log.v(TAG, "Removing item #" + position + ": f=" + object + " v=" + ((Fragment)
         * object).getView()); while (mSavedState.size() <= position) { mSavedState.add(null); } mSavedState.set(position, mFragmentManager.saveFragmentInstanceState(fragment));
         * mFragments.set(position, null); mCurTransaction.remove(fragment); */
    }

    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        Fragment fragment = (Fragment) object;
        if (fragment != mCurrentPrimaryItem) {
            if (mCurrentPrimaryItem != null) {
                mCurrentPrimaryItem.setMenuVisibility(false);
            }
            if (fragment != null) {
                fragment.setMenuVisibility(true);
            }
            mCurrentPrimaryItem = fragment;
        }
    }

    @Override
    public void finishUpdate(ViewGroup container) {
        if (mCurTransaction != null) {
            mCurTransaction.commitAllowingStateLoss();
            mCurTransaction = null;
            mFragmentManager.executePendingTransactions();
        }
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return ((Fragment) object).getView() == view;
    }

    @Override
    public Parcelable saveState() {
        Bundle state = null;
        if (mSavedState.size() > 0) {
            state = new Bundle();
            Fragment.SavedState[] fss = new Fragment.SavedState[mSavedState.size()];
            mSavedState.toArray(fss);
            state.putParcelableArray("states", fss);
        }
        for (int i = 0; i < mFragments.size(); i++) {
            Fragment f = mFragments.get(i);
            if (f != null) {
                if (state == null) {
                    state = new Bundle();
                }
                String key = "f" + i;
                mFragmentManager.putFragment(state, key, f);
            }
        }
        return state;
    }

    @Override
    public void restoreState(Parcelable state, ClassLoader loader) {
        if (state != null) {
            Bundle bundle = (Bundle) state;
            bundle.setClassLoader(loader);
            Parcelable[] fss = bundle.getParcelableArray("states");
            mSavedState.clear();
            mFragments.clear();
            if (fss != null) {
                for (int i = 0; i < fss.length; i++) {
                    mSavedState.add((Fragment.SavedState) fss[i]);
                }
            }
            Iterable<String> keys = bundle.keySet();
            for (String key : keys) {
                if (key.startsWith("f")) {
                    int index = Integer.parseInt(key.substring(1));
                    Fragment f = mFragmentManager.getFragment(bundle, key);
                    if (f != null) {
                        while (mFragments.size() <= index) {
                            mFragments.add(null);
                        }
                        f.setMenuVisibility(false);
                        mFragments.set(index, f);
                    } else {
                        Log.w(TAG, "Bad fragment at key " + key);
                    }
                }
            }
        }
    }
}

这是我的正常 FragmentAdapter.java

package com.tundem.webLab.Adapter;

import java.util.LinkedList;
import java.util.List;

import android.support.v4.app.FragmentManager;

import com.tundem.webLab.fragments.BaseFragment;
import com.viewpagerindicator.TitleProvider;

public class FragmentAdapter extends CustomFragmentStatePagerAdapter implements TitleProvider {
    public List<BaseFragment> fragments = new LinkedList<BaseFragment>();

    private int actPage;

    public FragmentAdapter(FragmentManager fm) {
        super(fm);
    }

    public void setActPage(int actPage) {
        this.actPage = actPage;
    }

    public void addItem(BaseFragment fragment) {
        // TODO if exists don't open / change to that tab
        fragments.add(fragment);
    }

    public BaseFragment getActFragment() {
        return getItem(getActPage());
    }

    public int getActPage() {
        return actPage;
    }

    @Override
    public BaseFragment getItem(int position) {
        if (position < getCount()) {
            return fragments.get(position);
        } else
            return null;
    }

    @Override
    public int getCount() {
        return fragments.size();
    }

    @Override
    public String getTitle(int position) {
        return fragments.get(position).getTitle();
    }

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }
}

这就是我删除 fragment 的方式。 (我知道它不仅仅是 .remove() )。可以自由地改进我的解决方案,您也可以在适配器中的某处添加此代码,是的。这取决于尝试实现它的用户。我在我的 TabHelper.java(一个处理所有选项卡操作的类,如删除、添加...)中使用它

    int act = Cfg.mPager.getCurrentItem();
    Cfg.mPager.removeAllViews();
    Cfg.mAdapter.mFragments.remove(act);
    try {
        Cfg.mAdapter.mSavedState.remove(act);
    } catch (Exception ex) {/* Already removed */}
    try {
        Cfg.mAdapter.fragments.remove(act);
    } catch (Exception ex) {/* Already removed */}

    Cfg.mAdapter.notifyDataSetChanged();
    Cfg.mIndicator.notifyDataSetChanged();

Cfg 的描述。事物。我将对这些对象的引用保存在 cfg 类中,这样我就可以随时使用它们而无需特殊的 Factory.java ...

是的。我希望我能提供帮助。随时改进它,但让我知道,这样我也可以改进我的代码。

谢谢。

如果我遗漏了任何代码,请告诉我。


我的旧答案也有效,但前提是您有不同的 fragment 。 FileFragment、WebFragment、... 如果您两次使用其中一种 fragment 类型,则不会。

我现在让它伪工作了。这是一个非常肮脏的解决方案,我仍在寻找更好的解决方案。请帮忙。

我更改了代码,删除了这个标签:

   public static void deleteActTab()
        {   
            //We set this on the indicator, NOT the pager
            int act = Cfg.mPager.getCurrentItem();
            Cfg.mAdapter.removeItem(act);
            List<BaseFragment> frags = new LinkedList<BaseFragment>();
            frags = Cfg.mAdapter.fragments;

            Cfg.mPager = (ViewPager)Cfg.act.findViewById(R.id.pager);
            Cfg.mPager.setAdapter(Cfg.mAdapter);
            Cfg.mIndicator.setViewPager(Cfg.mPager);

            Cfg.mAdapter.fragments = frags;

            if(act > 0)
            {
                Cfg.mPager.setCurrentItem(act-1);
                Cfg.mIndicator.setCurrentItem(act-1);
            }

            Cfg.mIndicator.notifyDataSetChanged();
        }

如果有人可以改进此代码,请告诉我。如果有人可以告诉我们该问题的真正答案。请在此处添加。有很多人遇到过这个问题。我为解决它的人增加了 50 的声誉。我也可以为解决问题的人捐款。

谢谢

关于android - 查看页面 : If page get removed the next pages content gets the removed pages content,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9056586/

有关android - 查看页面 : If page get removed the next pages content gets the removed pages content的更多相关文章

  1. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  2. ruby - 在 ASP 页面上 Mechanize 中断 - 2

    require'mechanize'agent=Mechanize.newlogin=agent.get('http://www.schoolnet.ch/DE/HomeDE.htm')agent.clicklogin.link_withtext:/Login/然后我得到Mechanize::UnsupportedSchemeError。 最佳答案 Mechanize不支持javascript但您可以将搜索字段添加到表单并为其分配搜索词并使用mechanize提交表单form=page.forms.firstform.add_fie

  3. ruby-on-rails - prawnto 显示新页面时不会中断的表格 - 2

    我有可变数量的表格和可变数量的行,我想让它们一个接一个地显示,但如果表格不适合当前页面,请将其放在下一页,然后继续。我已将表格放入事务中,以便我可以回滚然后打印它(如果高度适合当前页面),但我如何获得表格高度?我现在有这段代码pdf.transactiondopdf.table@data,:font_size=>12,:border_style=>:grid,:horizontal_padding=>10,:vertical_padding=>3,:border_width=>2,:position=>:left,:row_colors=>["FFFFFF","DDDDDD"]pdf.

  4. ruby - 每个页面上的 Jekyll 分页 - 2

    据我们所知,Jekyll默认分页仅支持index.html,我想创建blog.html并在那里包含分页。有什么解决办法吗? 最佳答案 如果您创建一个名为/blog的目录并在其中放置一个index.html文件,那么您可以向_config.yml表示paginate_path:"blog/page:num"。不是使用根文件夹中的默认index.html作为分页器模板,而是使用/blog/index.html。分页器将根据需要生成类似/blog/page2/和/blog/page3/的页面。这将使您到达yourwebsite.com/b

  5. ruby-on-rails - RoR && "coming soon"页面 - 2

    我正在寻找一种简单的方法来为我在RubyonRails上的项目实现简单的“即将推出”(预启动)页面。用户应该能够留下电子邮件以便在项目启动时收到通知。有没有这样的插件\gem?或者我应该自己做... 最佳答案 LaunchingSoon是一个Rails插件。它还集成了MailChimp或Campaignmonitor. 关于ruby-on-rails-RoR&&"comingsoon"页面,我们在StackOverflow上找到一个类似的问题: https:/

  6. ruby - 如何让 GitHub 页面使用 master 分支? - 2

    我有一个使用Jekyll托管在GitHub上的静态网站。问题是,我真的不需要master分支,因为存储库唯一包含的是网站。这样我就必须gitcheckoutgh-pages,然后gitmergemaster,然后gitpushorigingh-pages。有什么简单的方法可以摆脱gh-pages分支并直接从master推送? 最佳答案 Theproblemis,Idon'treallyneedthemasterbranch,astheonlythingtherepositorycontainsisthewebsite.Isthere

  7. ruby - 如何设置 Mechanize 页面编码? - 2

    我试图通过点击一个链接获得一个带有ISO-8859-1编码的页面,所以代码类似于这样:page_result=page.link_with(:text=>'link_text').click到目前为止,我得到的结果编码错误,所以我看到的字符如下:'T�tulo:'insteadof'Título:'我尝试了几种方法,包括:使用代理在第一个请求中声明编码:@page_search=@agent.get(:url=>'http://www.server.com',:headers=>{'Accept-Charset'=>'ISO-8859-1'})说明页面本身的编码page_result.

  8. ruby-on-rails - 仅在某些页面上使用 rails_xss - 2

    我正在使用rails_xss运行Rails2.3.14插入。我有另一个用于创建管理仪表板View的插件。我的问题是rails_xss正在转义我的仪表板插件生成的所有HTML。有没有一种方法可以将rails_xss配置为不转义匹配example.com/admin或基于目录(app/views/admin)或任何类似的页面结果一样吗? 最佳答案 更新仪表板生成插件以使用raw或html_safe进行内容输出可能会更简单。 关于ruby-on-rails-仅在某些页面上使用rails_xss

  9. ruby-on-rails - 有没有办法在 Rails 中以编程方式查看(或打印)方法定义? - 2

    假设我在我的Rails应用中某处定义了一个名为bla的函数。在ruby​​或rails中有没有一种方法可以动态/以编程方式打印用于定义该函数的代码?例如:defblaputs"HiThere"end然后如果我调用一个函数,例如get_definition:putsget_definition(:bla)这会打印出来"puts\"HiThere\""有规范的方法吗?我以前实际上不需要这样做,而且我知道这在Rails中并不是很常见的做法。我也不想使用元(反射)编程定义我的方法,然后存储用于定义我的方法的字符串。感谢您的帮助! 最佳答案

  10. ruby-on-rails - 在多个页面上使用相同表单的 Rails 最佳实践 - 2

    我正在开发一个Rails2.3.1网站。在整个网站中,我需要一个用于在各种页面(主页、创建帖子页面、帖子列表页面、评论列表页面等)上创建帖子的表单——只要说这个表单需要在由各种Controller)。这些页面中的每一个都显示在相应的Controller/操作中检索到的各种其他信息。例如,主页列出了最新的10篇文章、从数据库中提取的内容等。因此,我已将帖子创建表单移动到它自己的部分中,并将该部分包含在所有必要的页面中。请注意,部分POST中的表单到/questions(路由到PostsController::create——这是默认的Rails行为)。我遇到的问题是当Posts表单没有正

随机推荐