【问题标题】:Changing background image of current fragment in viewpager在 viewpager 中更改当前片段的背景图像
【发布时间】:2019-12-02 23:01:45
【问题描述】:

我在一个浏览器中有 4 个片段。和我的 viewpager 所在的活动中的 FragmentStatePagerAdapter。 FragmentStatePagerAdapter 的 newInstance() 方法以 layout id 为参数,因此每个 Fragment 都有自己的布局:

ViewPager pager;

public class MainActivity extends FragmentActivity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);     
        pager = (ViewPager) findViewById(R.id.viewPager);
        pager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));}

    private static class MyPagerAdapter extends FragmentStatePagerAdapter {
       FragmentManager fm;
       SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();

        public MyPagerAdapter(FragmentManager fm) {
            super(fm);
            this.fm = fm;
        }

        @Override
        public Fragment getItem(int pos) {
        if(pos!=0){
            pos = pos%4;
        }
            Fragment frag;
            switch(pos) {
            case 0: frag = FirstFragment.newInstance(R.layout.fire_room_wall1);
                    return frag;
            case 1: frag = FirstFragment.newInstance(R.layout.fire_room_wall2);
                    return frag;
            case 2: frag = FirstFragment.newInstance(R.layout.fire_room_wall3);
                    return frag;
            case 3: frag = FirstFragment.newInstance(R.layout.fire_room_wall3);
                    return frag;
            default: return FirstFragment.newInstance(R.layout.fire_room_wall1);
            }
        }

        @Override
        public int getCount() {
            return 444444;
        }     

             @Override
                public Object instantiateItem(ViewGroup container, int position) {
                    Fragment fragment = (Fragment) super.instantiateItem(container, position);
                    registeredFragments.put(position, fragment);
                    return fragment;
                }

                @Override
                public void destroyItem(ViewGroup container, int position, Object object) {
                    registeredFragments.remove(position);
                    super.destroyItem(container, position, object);
                }

                public Fragment getRegisteredFragment(int position) {
                    return registeredFragments.get(position);
                }
    }
}

这是第一个片段:

public class FirstFragment extends Fragment{

     @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            int layout = getArguments().getInt("layout");
            View v = inflater.inflate(layout, container, false);    
            return v;
        }

        public static FirstFragment newInstance(int layout) {

            FirstFragment f = new FirstFragment();
            Bundle b = new Bundle();
            b.putInt("layout", layout);
            f.setArguments(b);
            return f;
        }
}

还有activity_main.xml:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >
<FrameLayout android:layout_width="match_parent"
    android:layout_height="match_parent">
<android.support.v4.view.ViewPager
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/viewPager"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    />
<com.example.viewpagerfragement.CustomView android:id="@+id/customView"
        android:layout_width="fill_parent" android:layout_height="fill_parent" />
</FrameLayout>
</RelativeLayout>

还有一个新实例参数fire_room_wall1.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
     android:background="@drawable/wall_nobrainjar"
     android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/first" >

//其他一些子视图

     <ImageView
        android:id="@+id/zoomed_image"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:visibility="gone"/>

//其他一些子视图

</RelativeLayout>

现在在我的程序中的某个时刻,我想更改当前片段布局的背景图像。我试图这样做:

  int i = pager.getCurrentItem();
    Fragment page = ((MyPagerAdapter)pager.getAdapter()).getRegisteredFragment(i);
    ((BitmapDrawable)page.getView().getBackground()).getBitmap().recycle();
    page.getView().setBackgroundResource(R.drawable.wall3_nopaperball);

但是“((BitmapDrawable)page.getView().getBackground()).getBitmap().recycle();”行返回 NullPointerException,因为page.getView().getBackground() 为空。我做错了什么或如何更改背景图片? 附言由于某种原因,page.getView() 的类型是 NoSaveStateFrameLayout,而不是人们期望的 RelativeLayout

【问题讨论】:

  • page.getView() 也为空?你能请我解释一下你为什么要做 .getBitmap().recycle();如果你想改变它?
  • 请查看我的答案..
  • @phemt.latd 我正在回收旧的背景图像,确保它不会占用内存。然后,在下一行中,我将新图像放在背景中。
  • 还有一个问题,page.getView() 为空?还是对象和 .getBackground() 为空?如果我记得获取片段页面的最佳方法是:viewPager.getChildAt(int x)
  • page.getView() 不为空,而是返回一些相当奇怪的东西:一个类型为“NoSaveStateFrameLayout”的对象

标签: android android-fragments android-viewpager fragmentstatepageradapter


【解决方案1】:

解决方案:--

实际上您的问题是您正在回收位图,即您正在释放该位图和像素数据,因此,显然您将获得空值。!

在android api文档中已经提到过:--

你只需要这样做:--

int i = pager.getCurrentItem();
Fragment page = ((MyPagerAdapter)pager.getAdapter()).getRegisteredFragment(i);
Bitmap bitmapNeedTobeRecycled = ((BitmapDrawable)page.getView().getBackground()).getBitmap()
page.getView().setBackgroundResource(R.drawable.wall3_nopaperball);
bitmapNeedTobeRecycled.recycle();

然后它工作..享受..!

【讨论】:

  • 这一行“Bitmap bitmapNeedTobeRecycled = ((BitmapDrawable)page.getView().getBackground()).getBitmap()”给出空指针异常,因为“page.getView().getBackground() " 为空。
  • 那么问题来了,如何在我的情况下获取片段的背景图片,查看我提供的布局(RelativeLayout)
【解决方案2】:

首先,不要在适配器中保留片段列表。寻呼机适配器应通过自定义方法提供数据,然后您的 getItem() 应使用它来创建片段。相反,getItem() 中的随机布局在您将其传递给适配器之前在您的项目列表(参见下面的代码)上执行。不要覆盖initialiseItem()destroyItem()。此外,您不必保留对FragmentManager 的引用。你可以像这样实现你的适配器:

创建自定义类来保存您的数据。

public class MyItem {
    private int layout;
    private int bitmap;

    public MyItem(layout, bitmap) {
        this.layout = layout;
        this.bitmap = bitmap;
    }

    //implement getters and setters
}

接下来像这样实现适配器:

public static class MyPagerAdapter extends FragmentStatePagerAdapter {
    private List<MyItem> items = new ArrayList<MyItem>(0);

    public void setItems(List<MyItem> items) {
        this.items = items;
    }

    @Override
    public Fragment getItem(int pos) {
        MyItem item = items.get(pos);
        return FirstFragment.newInstance(item.getLayout(), item.getBitmap());
    }

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

    public void updateItemBitmap(int position, int bitmap) {
        MyItem myItem = items.get(position);
        myItem.setBitmap(bitmap);
        notifyDataSetChanged();
    }

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

然后在getItem() 方法中,您根据该数据初始化您的片段。接下来创建用于更新项目的方法,该方法正在更新提供的位置,然后使适配器无效。不要忘记实现getItemPosition(),它会使 ViewPager 使所有项目无效,包括那些已经创建的项目。

最后,您可以像这样在您的活动中更新它:

int i = pager.getCurrentItem();
((MyPagerAdapter)pager.getAdapter()).updateItemBitmap(i,R.drawable.wall3_nopaperball);

您的片段实现如下所示:

public class FirstFragment extends Fragment{

     @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            int layout = getArguments().getInt("layout");
            int bitmap = getArguments().getInt("bitmap");
            View v = inflater.inflate(layout, container, false);
            v.setBackgroundResource(bitmap);    
            return v;
        }

        public static FirstFragment newInstance(int layout, int bitmap) {

            FirstFragment f = new FirstFragment();
            Bundle b = new Bundle();
            b.putInt("layout", layout);
            b.putInt("bitmap",bitmap);
            f.setArguments(b);
            return f;
        }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多