在 viewpager 中处理片段 - android
Working with fragments inside viewpager - android
我在 viewpager 中的位置有问题。我有带有按钮的片段的容器布局。有些碎片有图片,有些则没有。如果片段包含图像,我想显示按钮。我知道容器发送到片段的位置有问题,但是如何处理容器中的位置,以及为什么第一个片段 0 和 1 作为容器发送到第一个片段的位置。
这是我的代码得到的示例:
例如,如果 16.fragment 包含图像,则按钮显示在 15.fragment 上,但我希望该按钮显示在同一片段(16.fragment)中。
这是我的片段代码 class
public class PitanjaFragment extends Fragment{
public static final String ARG_PAGE = "page";
private int broj;
private ImageView image;
public static String uri;
public static ListView listView;
public static boolean odgovoreno;
public static boolean tocno;
public static ArrayList<Odgovor> odgovorList;
private PitanjaAdapter adapter;
private DBTools db;
public static PitanjaFragment create(int pageNumber) {
PitanjaFragment fragment = new PitanjaFragment();
Bundle args = new Bundle();
Log.i("broj u pageru je sljedeci", String.valueOf(pageNumber));
args.putInt(ARG_PAGE, pageNumber);
fragment.setArguments(args);
return fragment;
}
public PitanjaFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
broj = getArguments().getInt(ARG_PAGE);
}
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_pitanja, container, false);
image = (ImageView) view.findViewById(R.id.imageSlikaImageView);
db = new DBTools(getActivity());
listView = (ListView) view.findViewById(R.id.listView);
updateDisplay();
return view;
}
public void updateDisplay() {
image.setImageBitmap(null);
for (int j = 0; j < ContainerIspiti.getAllImages.size(); j++) {
if (ContainerIspiti.getAllImages.get(j).getIdPitanja() == ContainerIspiti.getAllPitanja.get(broj)
.getIdPitanja()
&& ContainerIspiti.getAllImages.get(j).getNazivSlike() != null) {
image.setVisibility(View.VISIBLE);
ContainerIspiti.povecalo.setEnabled(true);
uri = PregledZnakova.PHOTOS_BASE_URL
+ ContainerIspiti.getAllImages.get(j).getNazivSlike();
int rounded_value = 40;
DisplayImageOptions options = new DisplayImageOptions.Builder().showImageForEmptyUri(R.drawable.placeholder).showStubImage(R.drawable.placeholder).cacheInMemory().cacheOnDisc().displayer(new RoundedBitmapDisplayer(rounded_value)).build();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getActivity().getApplicationContext()).defaultDisplayImageOptions(options).build();
ImageLoader.getInstance().init(config);
ImageLoader.getInstance().displayImage(uri, image,options);
} else {
image.setVisibility(View.GONE);
ContainerIspiti.povecalo.setEnabled(false);
}
}
odgovorList = db.getAllOdgovore(Integer.toString(ContainerIspiti.getAllPitanja.get(broj)
.getIdPitanja()));
adapter = new PitanjaAdapter(getActivity(),
R.layout.pitanja_entry, odgovorList);
listView.setAdapter(adapter);
for (int i=0;i<ContainerIspiti.getAllPitanja.size();i++){
if (ContainerIspiti.getAllPitanja.get(i).isTocno()){
Log.i("Ovo pitanje je tocno", ContainerIspiti.getAllPitanja.get(i).getTextPitanja());
}
}
}
}
这是容器的代码 class
public class ContainerIspiti extends FragmentActivity{
private ImageView next, previous, odgovori, informacije;
public static ImageView povecalo;
private TextView textPitanja, brojPitanja;
private ViewPager pager;
private PagerAdapter mPagerAdapter;
public static ArrayList<Pitanja> getAllPitanja;
public static ArrayList<Pitanje_has_Slika> getAllImages;
private Intent intent;
private DBTools db = new DBTools(this);
private ProgressDialog pDialog;
private int broj = 0;
private Typeface custom_font;
private HashMap<Integer, List<Integer>> odgBrojPitanja;
private static RelativeLayout relative;
private List<Integer> kliknuti;
private static ImageView expandedImageView;
private static ImageLoaderConfiguration config;
private static DisplayImageOptions options;
@Override
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
Bundle bundle = new Bundle();
intent = getIntent();
custom_font = Typeface.createFromAsset(getAssets(), "fonts/Aller.ttf");
odgBrojPitanja = new HashMap<Integer, List<Integer>>();
setContentView(R.layout.activity_container_pitanja);
Dohvati d = new Dohvati();
d.execute();
relative = (RelativeLayout) findViewById(R.id.RelativeLayoutContainerPitanjeExpandedImageView);
povecalo = (ImageView) findViewById(R.id.povecaloButtonPitanja);
povecalo.setImageResource(R.drawable.gumb_povecalo);
textPitanja = (TextView) findViewById(R.id.kategorijaTextViewPitanjeActivity);
brojPitanja = (TextView) findViewById(R.id.brojPitanjaTextViewPitanjeActivity);
pager = (ViewPager) findViewById(R.id.pagerPitanja);
options = new DisplayImageOptions.Builder().cacheInMemory().cacheOnDisc().build();
config = new ImageLoaderConfiguration.Builder(this.getApplicationContext()).defaultDisplayImageOptions(options).build();
}
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return PitanjaFragment.create(position);
}
@Override
public int getCount() {
return getAllPitanja.size();
}
}
private class Dohvati extends AsyncTask<String, String, String>{
@Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(ContainerIspiti.this);
pDialog.show();
}
@Override
protected String doInBackground(String... params) {
getAllPitanja = db
.getAllPitanja(intent.getStringExtra("id_kategorije"));
getAllImages = db.getAllPitanjaImages();
return null;
}
@Override
protected void onPostExecute(String result) {
pDialog.dismiss();
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
pager.setAdapter(mPagerAdapter);
pager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener(){
@Override
public void onPageSelected(int position) {
invalidateOptionsMenu();
broj = position;
brojPitanja.setText(String.valueOf(broj+1) + "/" + String.valueOf(getAllPitanja.size()));
for (int j = 0; j < getAllImages.size(); j++){
if (getAllPitanja.get(broj).getIdPitanja() == getAllImages.get(j).getIdPitanja()){
//Log.i("getAllImages koja sadrzi je sljedeca", getAllImages.get(j).getNazivSlike());
povecalo.setVisibility(View.VISIBLE);
} else {
povecalo.setVisibility(View.INVISIBLE);
}
}
}
});
textPitanja.setText(intent.getStringExtra("NAZIV_KATEGORIJE"));
brojPitanja.setText(String.valueOf(broj+1) + "/" + getAllPitanja.size());
}
}
public static void zoomImage(String uri){
ImageLoader.getInstance().init(config);
ImageLoader.getInstance().displayImage(uri, expandedImageView,options);
relative.bringToFront();
relative.setVisibility(View.VISIBLE);
expandedImageView.setScaleType(ScaleType.CENTER_INSIDE);
expandedImageView.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
relative.setVisibility(View.GONE);
}
});
}
}
希望有人帮忙
您的 ContainerIspiti
和 PitanjaFragment
中有一个相同的 for
循环 运行 来确定是否显示图像,我认为问题可能出现了那里。相反,如果每个 PitanjaFragment
实例都标识它是否有图像,则可以检查 ViewPager
中选择的 PitanjaFragment
来确定是否显示该按钮。
我尚未测试以下代码,但这应该足以为您指明正确的方向。
首先,向 PitanjaFragment
添加一个私有布尔字段以指示此实例是否正在显示图像:
PitanjaFragment.java
public class PitanjaFragment extends Fragment{
private boolean isDisplayingImage;
然后,当您确定它是否显示图像时更新此字段:
PitanjaFragment.java
public void updateDisplay() {
image.setImageBitmap(null);
for (int j = 0; j < ContainerIspiti.getAllImages.size(); j++) {
if (ContainerIspiti.getAllImages.get(j).getIdPitanja() ==
ContainerIspiti.getAllPitanja.get(broj).getIdPitanja()
&& ContainerIspiti.getAllImages.get(j).getNazivSlike() != null) {
image.setVisibility(View.VISIBLE);
// the Views on an Activity instance should not be accessed statically
//ContainerIspiti.povecalo.setEnabled(true);
// Instead, update the new boolean field
isDisplayingImage = true;
// ...
} else {
image.setVisibility(View.GONE);
// the Views on an Activity instance should not be accessed statically
//ContainerIspiti.povecalo.setEnabled(false);
// Instead, update the new boolean field
isDisplayingImage = false;
}
}
// ...
}
然后,添加一个getter以便其他代码可以访问这个值:
PitanjaFragment.java
public boolean hasImage() {
return isDisplayingImage;
}
接下来,我们将继续ContainerIspiti.java
,在这里我们将访问所选的PitanjaFragment
以查找它是否有图像,然后相应地设置povecalo
的状态。
首先,将 povecalo
改回私有的非静态字段,因为我们不再尝试从 PitanjaFragment
访问它(本答案末尾有更多信息):
ContainerIspiti.java
public class ContainerIspiti extends FragmentActivity{
private ImageView next, previous, odgovori, informacije, povecalo;
//public static ImageView povecalo;
然后,由于 FragmentStatePagerAdapter
不提供按位置检索特定 Fragment
的方法,您需要先将此功能添加到 ScreenSlidePagerAdapter
(请参阅 android - Retrieve a Fragment from a ViewPager 了解有关此解决方案的更多信息):
ContainerIspiti.java
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
// ...
@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);
}
}
最后需要从选中的片段中获取hasImage()
值,并相应设置povecalo
的状态:
ContainerIspiti.java
private class Dohvati extends AsyncTask<String, String, String>{
// ...
pager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener(){
@Override
protected void onPostExecute(String result) {
// ...
pager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener(){
@Override
public void onPageSelected(int position) {
// ...
// Replace the for() loop with this
if (((PitanjaFragment) mPagerAdapter.getRegisteredFragment(position)).hasImage()) {
povecalo.setEnabled(true);
povecalo.setVisibility(View.VISIBLE);
}
else {
povecalo.setEnabled(false);
povecalo.setVisibility(View.INVISIBLE);
}
}
}
});
// ...
}
}
同样,我还没有测试过这段代码,所以如果您有任何问题,请发表评论。
我想指出的另一件事是,使用静态字段来存储实例数据并不是一个好的解决方案,即使您确定只有一个对象实例也是如此。
在这种情况下,我们清理了 povecalo
,但您仍在 Activity
、ContainerIspiti
,用于存储由 ContainerIspiti
的实例生成的数据。 PitanjaFragment
然后直接从 class 访问这些静态字段。
相反,您至少应该考虑将它们设为私有非静态字段,并使用 getter 方法从实例而不是从 class.
访问它们
我在 viewpager 中的位置有问题。我有带有按钮的片段的容器布局。有些碎片有图片,有些则没有。如果片段包含图像,我想显示按钮。我知道容器发送到片段的位置有问题,但是如何处理容器中的位置,以及为什么第一个片段 0 和 1 作为容器发送到第一个片段的位置。
这是我的代码得到的示例: 例如,如果 16.fragment 包含图像,则按钮显示在 15.fragment 上,但我希望该按钮显示在同一片段(16.fragment)中。
这是我的片段代码 class
public class PitanjaFragment extends Fragment{
public static final String ARG_PAGE = "page";
private int broj;
private ImageView image;
public static String uri;
public static ListView listView;
public static boolean odgovoreno;
public static boolean tocno;
public static ArrayList<Odgovor> odgovorList;
private PitanjaAdapter adapter;
private DBTools db;
public static PitanjaFragment create(int pageNumber) {
PitanjaFragment fragment = new PitanjaFragment();
Bundle args = new Bundle();
Log.i("broj u pageru je sljedeci", String.valueOf(pageNumber));
args.putInt(ARG_PAGE, pageNumber);
fragment.setArguments(args);
return fragment;
}
public PitanjaFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
broj = getArguments().getInt(ARG_PAGE);
}
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_pitanja, container, false);
image = (ImageView) view.findViewById(R.id.imageSlikaImageView);
db = new DBTools(getActivity());
listView = (ListView) view.findViewById(R.id.listView);
updateDisplay();
return view;
}
public void updateDisplay() {
image.setImageBitmap(null);
for (int j = 0; j < ContainerIspiti.getAllImages.size(); j++) {
if (ContainerIspiti.getAllImages.get(j).getIdPitanja() == ContainerIspiti.getAllPitanja.get(broj)
.getIdPitanja()
&& ContainerIspiti.getAllImages.get(j).getNazivSlike() != null) {
image.setVisibility(View.VISIBLE);
ContainerIspiti.povecalo.setEnabled(true);
uri = PregledZnakova.PHOTOS_BASE_URL
+ ContainerIspiti.getAllImages.get(j).getNazivSlike();
int rounded_value = 40;
DisplayImageOptions options = new DisplayImageOptions.Builder().showImageForEmptyUri(R.drawable.placeholder).showStubImage(R.drawable.placeholder).cacheInMemory().cacheOnDisc().displayer(new RoundedBitmapDisplayer(rounded_value)).build();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getActivity().getApplicationContext()).defaultDisplayImageOptions(options).build();
ImageLoader.getInstance().init(config);
ImageLoader.getInstance().displayImage(uri, image,options);
} else {
image.setVisibility(View.GONE);
ContainerIspiti.povecalo.setEnabled(false);
}
}
odgovorList = db.getAllOdgovore(Integer.toString(ContainerIspiti.getAllPitanja.get(broj)
.getIdPitanja()));
adapter = new PitanjaAdapter(getActivity(),
R.layout.pitanja_entry, odgovorList);
listView.setAdapter(adapter);
for (int i=0;i<ContainerIspiti.getAllPitanja.size();i++){
if (ContainerIspiti.getAllPitanja.get(i).isTocno()){
Log.i("Ovo pitanje je tocno", ContainerIspiti.getAllPitanja.get(i).getTextPitanja());
}
}
}
}
这是容器的代码 class
public class ContainerIspiti extends FragmentActivity{
private ImageView next, previous, odgovori, informacije;
public static ImageView povecalo;
private TextView textPitanja, brojPitanja;
private ViewPager pager;
private PagerAdapter mPagerAdapter;
public static ArrayList<Pitanja> getAllPitanja;
public static ArrayList<Pitanje_has_Slika> getAllImages;
private Intent intent;
private DBTools db = new DBTools(this);
private ProgressDialog pDialog;
private int broj = 0;
private Typeface custom_font;
private HashMap<Integer, List<Integer>> odgBrojPitanja;
private static RelativeLayout relative;
private List<Integer> kliknuti;
private static ImageView expandedImageView;
private static ImageLoaderConfiguration config;
private static DisplayImageOptions options;
@Override
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
Bundle bundle = new Bundle();
intent = getIntent();
custom_font = Typeface.createFromAsset(getAssets(), "fonts/Aller.ttf");
odgBrojPitanja = new HashMap<Integer, List<Integer>>();
setContentView(R.layout.activity_container_pitanja);
Dohvati d = new Dohvati();
d.execute();
relative = (RelativeLayout) findViewById(R.id.RelativeLayoutContainerPitanjeExpandedImageView);
povecalo = (ImageView) findViewById(R.id.povecaloButtonPitanja);
povecalo.setImageResource(R.drawable.gumb_povecalo);
textPitanja = (TextView) findViewById(R.id.kategorijaTextViewPitanjeActivity);
brojPitanja = (TextView) findViewById(R.id.brojPitanjaTextViewPitanjeActivity);
pager = (ViewPager) findViewById(R.id.pagerPitanja);
options = new DisplayImageOptions.Builder().cacheInMemory().cacheOnDisc().build();
config = new ImageLoaderConfiguration.Builder(this.getApplicationContext()).defaultDisplayImageOptions(options).build();
}
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return PitanjaFragment.create(position);
}
@Override
public int getCount() {
return getAllPitanja.size();
}
}
private class Dohvati extends AsyncTask<String, String, String>{
@Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(ContainerIspiti.this);
pDialog.show();
}
@Override
protected String doInBackground(String... params) {
getAllPitanja = db
.getAllPitanja(intent.getStringExtra("id_kategorije"));
getAllImages = db.getAllPitanjaImages();
return null;
}
@Override
protected void onPostExecute(String result) {
pDialog.dismiss();
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
pager.setAdapter(mPagerAdapter);
pager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener(){
@Override
public void onPageSelected(int position) {
invalidateOptionsMenu();
broj = position;
brojPitanja.setText(String.valueOf(broj+1) + "/" + String.valueOf(getAllPitanja.size()));
for (int j = 0; j < getAllImages.size(); j++){
if (getAllPitanja.get(broj).getIdPitanja() == getAllImages.get(j).getIdPitanja()){
//Log.i("getAllImages koja sadrzi je sljedeca", getAllImages.get(j).getNazivSlike());
povecalo.setVisibility(View.VISIBLE);
} else {
povecalo.setVisibility(View.INVISIBLE);
}
}
}
});
textPitanja.setText(intent.getStringExtra("NAZIV_KATEGORIJE"));
brojPitanja.setText(String.valueOf(broj+1) + "/" + getAllPitanja.size());
}
}
public static void zoomImage(String uri){
ImageLoader.getInstance().init(config);
ImageLoader.getInstance().displayImage(uri, expandedImageView,options);
relative.bringToFront();
relative.setVisibility(View.VISIBLE);
expandedImageView.setScaleType(ScaleType.CENTER_INSIDE);
expandedImageView.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
relative.setVisibility(View.GONE);
}
});
}
}
希望有人帮忙
您的 ContainerIspiti
和 PitanjaFragment
中有一个相同的 for
循环 运行 来确定是否显示图像,我认为问题可能出现了那里。相反,如果每个 PitanjaFragment
实例都标识它是否有图像,则可以检查 ViewPager
中选择的 PitanjaFragment
来确定是否显示该按钮。
我尚未测试以下代码,但这应该足以为您指明正确的方向。
首先,向 PitanjaFragment
添加一个私有布尔字段以指示此实例是否正在显示图像:
PitanjaFragment.java
public class PitanjaFragment extends Fragment{
private boolean isDisplayingImage;
然后,当您确定它是否显示图像时更新此字段:
PitanjaFragment.java
public void updateDisplay() {
image.setImageBitmap(null);
for (int j = 0; j < ContainerIspiti.getAllImages.size(); j++) {
if (ContainerIspiti.getAllImages.get(j).getIdPitanja() ==
ContainerIspiti.getAllPitanja.get(broj).getIdPitanja()
&& ContainerIspiti.getAllImages.get(j).getNazivSlike() != null) {
image.setVisibility(View.VISIBLE);
// the Views on an Activity instance should not be accessed statically
//ContainerIspiti.povecalo.setEnabled(true);
// Instead, update the new boolean field
isDisplayingImage = true;
// ...
} else {
image.setVisibility(View.GONE);
// the Views on an Activity instance should not be accessed statically
//ContainerIspiti.povecalo.setEnabled(false);
// Instead, update the new boolean field
isDisplayingImage = false;
}
}
// ...
}
然后,添加一个getter以便其他代码可以访问这个值:
PitanjaFragment.java
public boolean hasImage() {
return isDisplayingImage;
}
接下来,我们将继续ContainerIspiti.java
,在这里我们将访问所选的PitanjaFragment
以查找它是否有图像,然后相应地设置povecalo
的状态。
首先,将 povecalo
改回私有的非静态字段,因为我们不再尝试从 PitanjaFragment
访问它(本答案末尾有更多信息):
ContainerIspiti.java
public class ContainerIspiti extends FragmentActivity{
private ImageView next, previous, odgovori, informacije, povecalo;
//public static ImageView povecalo;
然后,由于 FragmentStatePagerAdapter
不提供按位置检索特定 Fragment
的方法,您需要先将此功能添加到 ScreenSlidePagerAdapter
(请参阅 android - Retrieve a Fragment from a ViewPager 了解有关此解决方案的更多信息):
ContainerIspiti.java
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
// ...
@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);
}
}
最后需要从选中的片段中获取hasImage()
值,并相应设置povecalo
的状态:
ContainerIspiti.java
private class Dohvati extends AsyncTask<String, String, String>{
// ...
pager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener(){
@Override
protected void onPostExecute(String result) {
// ...
pager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener(){
@Override
public void onPageSelected(int position) {
// ...
// Replace the for() loop with this
if (((PitanjaFragment) mPagerAdapter.getRegisteredFragment(position)).hasImage()) {
povecalo.setEnabled(true);
povecalo.setVisibility(View.VISIBLE);
}
else {
povecalo.setEnabled(false);
povecalo.setVisibility(View.INVISIBLE);
}
}
}
});
// ...
}
}
同样,我还没有测试过这段代码,所以如果您有任何问题,请发表评论。
我想指出的另一件事是,使用静态字段来存储实例数据并不是一个好的解决方案,即使您确定只有一个对象实例也是如此。
在这种情况下,我们清理了 povecalo
,但您仍在 Activity
、ContainerIspiti
,用于存储由 ContainerIspiti
的实例生成的数据。 PitanjaFragment
然后直接从 class 访问这些静态字段。
相反,您至少应该考虑将它们设为私有非静态字段,并使用 getter 方法从实例而不是从 class.
访问它们