Android: Gridview not displayed in fragment - android

Good evening, i'm new in Android programming and i'm facing a problem in displaying a gridview in fragment.
I'm loading an inventory list in order to show if one item is checked or not.
I have loaded data in arraylist and i'm sure it is passed correctly to the fragment.
The problem is that the Gridadapter is trying to load only first item (for two times it seems) but the result is blank screen.
This is my fragment code
package testjava.pulsanti;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridView;
import android.widget.TextView;
import java.lang.reflect.Array;
import java.util.ArrayList;
public class Fragment2 extends Fragment {
ArrayList<bancale> transactionList;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View myfragmentview = inflater.inflate(R.layout.fragment_2, container, false);
if (getArguments() != null) {
transactionList = (ArrayList<bancale>) getArguments().getSerializable("bancali");
for (int i = 0; i < transactionList.size(); i++) {
bancale banc = transactionList.get(i);
System.out.println(banc.numeroudm + " " + banc.statoInventario);
}
if (transactionList != null) {
GridView gridView = myfragmentview.findViewById(R.id.GridviewInv);
GridAdapterInv gridAdapter = new GridAdapterInv(this.getContext(), transactionList);
gridView.setAdapter(gridAdapter);
}
}
return myfragmentview ;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
#Override
public void onPause() {
super.onPause();
System.out.println("Fragment 2 paused");
// Fragment frag = new Fragment1();
// getParentFragmentManager().beginTransaction().replace(R.id.Viewpager,frag).commit();
}
}
and this is the GridAdapterCode
package testjava.pulsanti;
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
public class GridAdapterInv extends BaseAdapter {
Context context;
ArrayList<bancale> bancali;
LayoutInflater inf;
public GridAdapterInv(Context context, ArrayList<bancale> bancali) {
this.bancali = bancali;
this.context = context;
inf = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return bancali.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View v, ViewGroup parent) {
ViewHolder holder;
if (v == null) {
v = inf.inflate(R.layout.elementogriglia_inv,null,false);
holder = new ViewHolder();
holder.imgView = (ImageView) v.findViewById(R.id.grid_image);
holder.textView = (TextView) v.findViewById((R.id.numUdm));
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
System.out.println(("Position:" + position));
bancale banc = bancali.get(position);
if (banc.statoInventario == 0) {
holder.imgView.setImageResource(R.drawable.unchecked);
}
else {
holder.imgView.setImageResource(R.drawable.checked);
}
holder.textView.setText(banc.numeroudm);
System.out.println(banc.numeroudm);
if (position % 2 == 0) {
v.setBackgroundColor(Color.LTGRAY);
} else {
v.setBackgroundColor(Color.WHITE);
}
return v;
}
public static class ViewHolder {
private TextView textView;
private ImageView imgView;
}
}
and that's my xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:context=".Fragment2"
tools:ignore="ExtraText">
<GridView
android:id="#+id/GridviewInv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:numColumns="1"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
...
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/relativeLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<ImageView
android:id="#+id/Icona"
android:layout_width="48dp"
android:layout_height="49dp"
android:contentDescription="TODO"
app:srcCompat="#drawable/checked" />
<TextView
android:id="#+id/idBancale"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="TextView"
android:textColor="#757575"
app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
I don't understand why the gridadapter is not Loading all items in my arraylist but it seems only loading the first and at the end it isn't displayed.
Someone can help me?
Thanks

Related

ListFragment item selection doesn't always work when nested into ViewPager2

I have a ViewPager2, connected with a TabLayout, that creates multiple fragments, each composed of a ListFragment instance with a single item that can be selected (using android:choiceMode="singleChoice").
The problem is that when running on the Android Emulator (Pixel 2, API 28) after some clicking and scrolling the selection doesn't happen at all as if I didn't click. But if I attach the Android Studio Profiler I can see the red circle every time I click, even if the toast is not displayed and the item not marked as selected.
This is my full code, it's just a simple example.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<-- Tab layout sync-ed with ViewPager2 -->
<com.google.android.material.tabs.TabLayout
android:id="#+id/tabs"
style="#style/Widget.MaterialComponents.TabLayout.Colored"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</com.google.android.material.appbar.AppBarLayout>
<!-- ViewPager2 to handle left/right scrolling too -->
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/tabviewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
l_v_page.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".LVPageFragment">
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:choiceMode="singleChoice"
android:background="#color/white">
</ListView>
</FrameLayout>
l_v_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?android:attr/activatedBackgroundIndicator" >
<TextView
android:id="#+id/row_num"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginRight="4dp"
android:gravity="center"
android:minHeight="?android:attr/listPreferredItemHeightLarge"
android:textSize="30dp"
android:textStyle="bold" />
<TextView
android:id="#+id/row_descr"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignTop="#id/row_num"
android:layout_alignBottom="#id/row_num"
android:layout_toRightOf="#id/row_num"
android:gravity="center_vertical"
android:textColorHighlight="#FFFFFF"
android:textSize="16sp" />
</RelativeLayout>
MainActivity.class
package com.example.testui4;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.Lifecycle;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import android.os.Bundle;
import com.example.testui4.databinding.ActivityMainBinding;
import com.google.android.material.tabs.TabLayoutMediator;
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
// Create adapter for ViewPager2
binding.tabviewpager.setAdapter(new VPAdapter(this));
// Connect tabs with the ViewPager2
new TabLayoutMediator(binding.tabs, binding.tabviewpager, (tab, position) ->
{ tab.setText("List " + (position + 1)); }).attach();
setContentView(binding.getRoot());
}
#Override
protected void onDestroy() {
super.onDestroy();
binding = null;
}
// Inner class to handle ViewPager2 with 4 fixed pages
private class VPAdapter extends FragmentStateAdapter {
public VPAdapter(#NonNull FragmentActivity fragmentActivity) { super(fragmentActivity); }
public VPAdapter(#NonNull FragmentManager fragmentManager, #NonNull Lifecycle lifecycle) { super(fragmentManager, lifecycle); }
#NonNull
#Override
public Fragment createFragment(int position) { return LVPageFragment.newInstance(position); }
#Override
public int getItemCount() { return 4; }
}
}
LVAdapter.class
package com.example.testui4;
import android.content.Context;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class LVAdapter extends BaseAdapter {
protected final Context context;
protected SparseArray<String> mChoices = null;
public LVAdapter(Context ctx) { this.context = ctx; }
#Override
public boolean hasStableIds() {
return true;
}
#Override
public int getCount() {
if (mChoices != null)
return mChoices.size();
else
return 0;
}
#Override
public Object getItem(int i) {
if (mChoices != null)
return mChoices.get(i);
else
return null;
}
#Override
public long getItemId(int i) { return i; }
#Override
public View getView(int position, View convertView, ViewGroup parent) {
RelativeLayout row = (RelativeLayout) convertView;
if (row == null) {
// The view is not recycled, must be re-created
LayoutInflater inflater = (LayoutInflater) LayoutInflater.from(context);
row = (RelativeLayout) inflater.inflate(R.layout.l_v_item, parent, false);
}
// Get objects
TextView txtNum = (TextView) row.findViewById(R.id.row_num);
TextView txtDescr = (TextView) row.findViewById(R.id.row_descr);
// Set properties
txtNum.setText(Integer.toString(mChoices.keyAt(position)));
txtDescr.setText(mChoices.valueAt(position));
// Return the row
return row;
}
public void updateChoices(SparseArray<String> choices) {
this.mChoices = choices;
notifyDataSetChanged();
}
}
LVPageFragment.class
package com.example.testui4;
import android.os.Bundle;
import android.util.Log;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.ListFragment;
import com.example.testui4.databinding.LVPageBinding;
public class LVPageFragment extends ListFragment {
private static final String ARG_NUMBER = "number";
private int mNumber = 1;
private LVPageBinding binding;
public LVPageFragment() { }
public static LVPageFragment newInstance(int number) {
LVPageFragment fragment = new LVPageFragment();
Bundle args = new Bundle();
args.putInt(ARG_NUMBER, number);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) { mNumber = getArguments().getInt(ARG_NUMBER); }
}
#Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
binding = LVPageBinding.inflate(inflater, container, false);
// List contents (may change in future for each fragment instance)
int intPage = mNumber + 1;
SparseArray<String> placeholder = new SparseArray<>();
placeholder.put(1, "ALPHA " + intPage);
placeholder.put(2, "BRAVO " + intPage);
placeholder.put(3, "CHARLIE " + intPage);
placeholder.put(4, "DELTA " + intPage);
placeholder.put(5, "FOXTROT " + intPage);
placeholder.put(6, "GOLF " + intPage);
placeholder.put(7, "HOTEL " + intPage);
placeholder.put(8, "INDIA " + intPage);
// Send data to the adapter and setup list fragment
LVAdapter adapter = new LVAdapter(getContext());
adapter.updateChoices(placeholder);
setListAdapter(adapter);
return binding.getRoot();
}
#Override
public void onListItemClick(#NonNull ListView l, #NonNull View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Toast.makeText(requireActivity(),"You clicked #" + (position + 1) + " on page #" + (mNumber + 1),
Toast.LENGTH_SHORT).show();
}
}
Result:
Why does that happen and how can I fix it?
EDIT: I tried to test the same app in a real device and there are no issues, so maybe it is a problem of the emulator?
There is a bug with the ViewPager2 and ListFragment: https://issuetracker.google.com/issues/256270071
I suppose it may or may not reproduce on real devices.
If having some predefined number of fragments this could be fixed calling pager.setOffscreenPageLimit with a value ≥ number of fragments.

clickListener is not working in GridView in android app

I am implementing an android application that has a GridView where every item is an ImageView with TextView below, I implemented the adapter and the GridView displays correctly, but it is supposed that when I click an image an other screen (Activity is launched) but unfortunately it is not the case here is my code:
the gridView_layout:
<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
>
<GridView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/videosGrid"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:numColumns="auto_fit"
android:background="#000"
android:horizontalSpacing="10dp"
android:verticalSpacing="10dp"
android:columnWidth="120dp"
android:stretchMode="spacingWidthUniform"></GridView>
</GridLayout>
the grid_item_layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/video_thumbnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:minWidth="170dp"
android:minHeight="140dp"
android:scaleType="fitXY"
android:clickable="true"/>
<!-- android:src="#drawable/alternative_rock_music" -->
<TextView android:id="#+id/video_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginTop="5dp"
android:textColor="#color/red"
android:textStyle="bold"
/>
</LinearLayout>
the adapter:
package com.app.utils;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.app.R;
import com.app.entities.VideoEntity;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.List;
public class MyGridViewAdapter extends BaseAdapter {
private static final String TAG = MyGridViewAdapter.class.getSimpleName();
private Context context;
private List<VideoEntity> videosList;
public MyGridViewAdapter(Context context) {
this.context = context;
}
#Override
public int getCount() {
return videosList.size();
}
#Override
public Object getItem(int position) {
return videosList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public List<VideoEntity> getVideosList() {
return videosList;
}
public void setVideosList(List<VideoEntity> videosList) {
this.videosList = videosList;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.d(TAG," getView(int, View, viewGroup - Ini ");
View row = convertView;
ViewHolder holder = null;
if(row == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.video_item ,parent, false);
holder = new ViewHolder(row);
row.setTag(holder);
}
else
{
holder = (ViewHolder) row.getTag();
}
VideoEntity tmp = videosList.get(position);
Picasso.with(context).load(tmp.getThumbnailURL()).into(holder.myVideo);
holder.title.setText(tmp.getTitle());
Log.d(TAG, " getView(int, View, viewGroup - Fi ");
return row;
}
class ViewHolder {
ImageView myVideo;
TextView title;
public ViewHolder(View v) {
Log.d(TAG," ViewHolder(View) - Ini ");
myVideo = (ImageView) v.findViewById(R.id.video_thumbnail);
title = (TextView) v.findViewById(R.id.video_title);
Log.d(TAG," ViewHolder(View) - Fi ");
}
}
}
and here is the activity where i am supposed to catch the click event on every item of the gridView:
package com.app.activities
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.GridView;
import com.app.entities.VideoEntity;
import com.app.utils.MyGridViewAdapter;
import java.util.ArrayList;
import static android.widget.AdapterView.*;
public class VideosCatalogActivity extends Activity implements AdapterView.OnItemSelectedListener, AdapterView.OnClickListener{
private static final String TAG = VideosCatalogActivity.class.getSimpleName();
private GridView videosGrid;
private ArrayList<VideoEntity> videosList;
#Override
protected void onCreate(Bundle savedInstanceState){
Log.d(TAG, " onCreate(Bundle) - Ini ");
super.onCreate(savedInstanceState);
setContentView(R.layout.videos_catalog_layout);
Bundle bundle = getIntent().getExtras();
videosList = bundle.getParcelableArrayList("com.app.entities.VideoEntity" );
videosGrid = (GridView) findViewById(R.id.videosGrid);
MyGridViewAdapter adapter = new MyGridViewAdapter(this);
adapter.setVideosList(videosList);
videosGrid.setAdapter(adapter);
videosGrid.setOnItemSelectedListener(this);
Log.d(TAG, " onCreate(Bundle) - Fi ");
}
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.d(TAG, " onItemClick(AdapterView<?>, View, int, long) - Ini ");
Intent intent = new Intent(getApplicationContext(),YoutubePlayerActivity.class);
intent.putExtra("VIDEO_ID",videosList.get(position).getId());
startActivity(intent);
Log.d(TAG, " onItemClick(AdapterView<?>, View, int, long) - Fi ");
}
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Log.d(TAG, " onItemClick(AdapterView<?>, View, int, long) - Ini ");
Intent intent = new Intent(getApplicationContext(),YoutubePlayerActivity.class);
intent.putExtra("VIDEO_ID",videosList.get(position).getId());
startActivity(intent);
Log.d(TAG, " onItemClick(AdapterView<?>, View, int, long) - Fi ");
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
#Override
public void onClick(View v) {
}
/*#Override
public void onNothingSelected(AdapterView<?> parent) {
} */
}
I tried to implement two different onClickListeners methods but none is working.
I don't know what i did wrong ???
Any help will be very appreciated.
Note: i can confirm that it is not a manifest problem, because i debugged and nothing happens when i click an image.
Change
`implements AdapterView.OnItemSelectedListener, AdapterView.OnClickListener`
to
`implements AdapterView.OnItemClickListener`
Change
`videosGrid.setOnItemSelectedListener(this)`
to
`videosGrid.setOnItemClickListener(this)`
Remove android:clickable="true" in ImageView
Remove both interfaces
AdapterView.OnItemSelectedListener
AdapterView.OnClickListener and respective methods.
and implement the AdapterView.OnItemClickListener
You need to clarify that AdapterView.OnItemClickListener is different to AdapterView.OnItemSelectedListener and AdapterView.OnClickListener also.
Your activity should implement AdapterView.OnItemClickListener, override it and you will get item click event. Remember to add this line: videosGrid.setOnItemClickListener(this).

ListView item open a new fragment

I am making a fitness app, where I want to have 3 nesting :
ListView with muscle group items
ListView of exercises (appears when to click on item from the muscle group ListView)
and description of exercise.
Something like this design:
But I don't know how do realize this.
Do I need create a new fragment to each item or I can use ViewPager here(if yes,how to do this)?
Give me advice,please, how to realize this design (any links of the same structure projects or any other examples)
thank you in advance
Here is the sample code
package com.sw.gitans201608042027;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
public class MainActivity extends FragmentActivity {
private static MainActivity mCurrent = null;
public static MainActivity getInstance() {
return mCurrent;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCurrent = this;
setContentView(R.layout.activity_main);
switchFragment(new ListFragment());
}
public void switchFragment(Fragment f) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.container, f);
transaction.commit();
}
}
package com.sw.gitans201608042027;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
public class ListFragment extends Fragment implements OnItemClickListener {
private String[] contents = { "a", "b" };
private String[] aArr = { "a1", "a2" }, bArr = { "b1", "b2" };
private SampleAdapter mAdapter;
public ListFragment(String[] contents) {
this.contents = contents;
}
public ListFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.lv, container, false);
mAdapter = new SampleAdapter(getActivity(), contents);
((ListView) v.findViewById(R.id.lv)).setAdapter(mAdapter);
((ListView) v.findViewById(R.id.lv)).setOnItemClickListener(this);
return v;
}
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
if (mAdapter.getItem(arg2) != null) {
if (((String) mAdapter.getItem(arg2)).equals("a") || ((String) mAdapter.getItem(arg2)).equals("b")) {
if (((String) mAdapter.getItem(arg2)).equals("a")) {
if (MainActivity.getInstance() != null)
MainActivity.getInstance().switchFragment(new ListFragment(aArr));
} else {
if (MainActivity.getInstance() != null)
MainActivity.getInstance().switchFragment(new ListFragment(bArr));
}
} else {
if (MainActivity.getInstance() != null)
MainActivity.getInstance().switchFragment(new TextFragment((String) mAdapter.getItem(arg2)));
}
}
}
}
package com.sw.gitans201608042027;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class SampleAdapter extends BaseAdapter {
private String[] contents;
private LayoutInflater mInflater;
public SampleAdapter(Context ctxt, String[] contents) {
this.contents = contents;
mInflater = LayoutInflater.from(ctxt);
}
#Override
public int getCount() {
if (contents != null)
return contents.length;
else
return 0;
}
#Override
public Object getItem(int position) {
if (contents == null || position >= contents.length)
return null;
else
return contents[position];
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Holder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item, null);
holder = new Holder();
holder.tv = (TextView) convertView.findViewById(R.id.list_txt);
convertView.setTag(holder);
} else
holder = (Holder) convertView.getTag();
holder.tv.setText(contents[position]);
return convertView;
}
private class Holder {
TextView tv;
}
}
package com.sw.gitans201608042027;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class TextFragment extends Fragment {
private String desc;
public TextFragment(String s){
desc = s;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.list_item, container, false);
((TextView)v.findViewById(R.id.list_txt)).setText(desc);
return v;
}
}
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"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.sw.gitans201608042027.MainActivity" >
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/list_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
lv.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="#+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>

Android's ArrayAdapter: added fragments to rows work wrongly

I am using ListView with ArrayAdapter and trying to add fragments to all rows of the ListView. However, the app does not work correctly: only one row on the screen showed with the added fragment but not all rows. Sometimes the app may be crashed because out of memory.
Can someone give me some advices? Thanks.
MainActivity.java
package com.me.test05;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
ListView myListView = (ListView) findViewById(R.id.myListView);
myListView.setAdapter(new MyArrayAdaptor(this, R.layout.row));
}
}
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
}
private static final String[] allnames = { "John", "Marry", "Smith", "Felicity", "Lion", "Math" };
public static class MyArrayAdaptor extends ArrayAdapter<String> {
private final Context context;
public MyArrayAdaptor(Context context, int resource) {
super(context, resource);
this.context = context;
}
#Override
public int getCount() {
return allnames.length * 100;
}
#Override
public String getItem(int position) {
return allnames[position % allnames.length];
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.row, parent, false);
TextView textView = (TextView) rowView.findViewById(R.id.textView1);
String str = getItem(position);
textView.setText(str);
FragmentTransaction ft = ((Activity) context).getFragmentManager().beginTransaction();
ft.replace(R.id.myFrameLayout, new PlaceholderFragment());
ft.commit();
return rowView;
}
}
}
File activity.xml:
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:fitsSystemWindows="true">
<ListView android:id="#+id/myListView"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:dividerHeight="2px">
</ListView>
</merge>
File row.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="abc" />
<FrameLayout
android:id="#+id/myFrameLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
</FrameLayout>
</LinearLayout>
File fragment_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView1"
android:layout_below="#+id/textView1"
android:text="Button" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
</LinearLayout>
Screen looks like:
I have solved that problem. The problem is the fragment manager always find (to replace by a new fragment) an id in global. That is why it always found and added all new fragments into the first row since it is the first one contains that id (as well as all other rows).
To solve the problem, I create dynamic ids which are unique for each row then replace that fixed id by them before letting fragment manager to do the rest. I also store those dynamic ids into rows' tags to reuse latter.
The new code is bellow, including the code for finding and reusing added fragments:
package com.me.test05;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.FrameLayout;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
ListView myListView = (ListView) findViewById(R.id.myListView);
myListView.setAdapter(new MyArrayAdaptor(this, R.layout.row));
}
}
public static class PlaceholderFragment extends Fragment {
private View rootView = null;
private String theString = null;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_main, container, false);
setString(theString);
return rootView;
}
public void setString(String str) {
theString = str;
if (theString != null && rootView != null) {
TextView textView = (TextView) rootView.findViewById(R.id.textView2);
textView.setText(str);
}
}
}
private static final String[] allnames = { "John", "Marry", "Smith", "Felicity", "Lion", "Math" };
public static class MyArrayAdaptor extends ArrayAdapter<String> {
private final Context context;
public MyArrayAdaptor(Context context, int resource) {
super(context, resource);
this.context = context;
}
#Override
public int getCount() {
return allnames.length * 100;
}
#Override
public String getItem(int position) {
return allnames[position % allnames.length];
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = convertView;
PlaceholderFragment myFragment = null;
if (rowView == null) {
rowView = inflater.inflate(R.layout.row, parent, false);
int newId = 100000 + position;
FrameLayout layout = (FrameLayout) rowView.findViewById(R.id.myFrameLayout);
layout.setId(newId);
rowView.setTag(newId);
myFragment = new PlaceholderFragment();
FragmentTransaction ft = ((Activity) context).getFragmentManager().beginTransaction();
ft.replace(newId, myFragment, "" + newId).commit();
} else {
Integer theId = (Integer) convertView.getTag();
myFragment = (PlaceholderFragment) ((Activity) context).getFragmentManager().findFragmentById(theId);
}
String str = getItem(position);
myFragment.setString(str + ", " + position);
TextView textView = (TextView) rowView.findViewById(R.id.textView1);
textView.setText(str);
return rowView;
}
}
}

Imageview getting automatically changed on scroll listview

I am new to android and facing one very comman problem of listview i googled alot but did'nt found anything usefull for my case.Hope you people show me the right direction.Whenever I am changing my image from "plus" to "tick" on click my last item image also got automatically changed on scroll.
My list_comapare_product XMl :-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white_color"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:background="#color/white_color"
android:gravity="center_vertical" >
<ImageView
android:id="#+id/img_product"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="#drawable/crane" />
<com.mss.skyjack.custom.views.SkyjackCustomTextview
android:id="#+id/tv_product_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:gravity="center"
android:text="test"
android:textAppearance="?android:attr/textAppearanceMedium" />
<ImageView
android:id="#+id/img_plus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="#drawable/plus" />
</RelativeLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:background="#color/black_color" />
</LinearLayout>
Here is my Adapter :-
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
public class ComapreProductSelectionAdapter extends BaseAdapter {
Activity activity;
List<SelectorTest> listSelector;
private LayoutInflater mLayoutInflater;
public ComapreProductSelectionAdapter(Activity activity,
List<SelectorTest> listSelector) {
this.activity = activity;
this.listSelector = listSelector;
mLayoutInflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return listSelector.size();
}
#Override
public SelectorTest getItem(int position) {
return listSelector.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
final int i = position;
final SelectorTest listItem = listSelector.get(position);
if (convertView == null) {
convertView = mLayoutInflater.inflate(
R.layout.list_comapare_product, parent, false);
viewHolder = new ViewHolder();
viewHolder.tvProductName = (TextView) convertView
.findViewById(R.id.tv_product_name);
viewHolder.imgProduct = (ImageView) convertView
.findViewById(R.id.img_product);
viewHolder.imgadd = (ImageView) convertView
.findViewById(R.id.img_plus);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.imgadd.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (viewHolder.imgadd.getDrawable().getConstantState() == activity
.getResources().getDrawable(R.drawable.plus)
.getConstantState()) {
viewHolder.imgadd.setImageResource(R.drawable.tick);
} else {
viewHolder.imgadd.setImageResource(R.drawable.plus);
}
}
});
return convertView;
}
static class ViewHolder {
TextView tvProductName;
ImageView imgProduct, imgadd;
View viewRightLine;
}
}
Thanks.
You need to keep track of which items have been "ticked". I copied your adapter and made necessary changes. You can just copy-paste the code and it should work.
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
public class ComapreProductSelectionAdapter extends BaseAdapter {
Activity activity;
List<SelectorTest> listSelector;
private LayoutInflater mLayoutInflater;
private ArrayList<Integer> tickedItems = new ArrayList<Integer>();
public ComapreProductSelectionAdapter(Activity activity,
List<SelectorTest> listSelector) {
this.activity = activity;
this.listSelector = listSelector;
mLayoutInflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return listSelector.size();
}
#Override
public SelectorTest getItem(int position) {
return listSelector.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
final int i = position;
final SelectorTest listItem = listSelector.get(position);
if (convertView == null) {
convertView = mLayoutInflater.inflate(
R.layout.list_comapare_product, parent, false);
viewHolder = new ViewHolder();
viewHolder.tvProductName = (TextView) convertView
.findViewById(R.id.tv_product_name);
viewHolder.imgProduct = (ImageView) convertView
.findViewById(R.id.img_product);
viewHolder.imgadd = (ImageView) convertView
.findViewById(R.id.img_plus);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.imgadd.setTag(position);
viewHolder.imgadd.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(tickedItems.contains((Integer)v.getTag()) {
//Already ticked, set to plus
viewHolder.imgadd.setImageDrawable(activity.getResources().getDrawable(R.drawable.plus));
tickedItems.remove((Integer)v.getTag());
} else {
tickedItems.add((Integer)v.getTag());
viewHolder.imgadd.setImageDrawable(activity.getResources().getDrawable(R.drawable.tick));
}
}
});
if(tickedItems.contains(position))
viewHolder.imgadd.setImageDrawable(activity.getResources().getDrawable(R.drawable.tick));
else
viewHolder.imgadd.setImageDrawable(activity.getResources().getDrawable(R.drawable.plus));
return convertView;
}
static class ViewHolder {
TextView tvProductName;
ImageView imgProduct, imgadd;
View viewRightLine;
}
}
As an extra, don't use ImageView.setImageResource() as it is inefficient.
Quote from Android docs about ImageView.setImageReource()
This does Bitmap reading and decoding on the UI thread, which can cause a latency hiccup. If that's a concern, consider using setImageDrawable(android.graphics.drawable.Drawable) or setImageBitmap(android.graphics.Bitmap) and BitmapFactory instead.

Categories

Resources