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>
Related
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
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.
My app is to perform ListView. When it was running, the error message notified that "Unfortunately, App has stopped". Here is my code.
package com.example.admin.customadapter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ListView;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
ListView listView;
ArrayList<Nation>nationifo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView)findViewById(R.id.ListViewNation);
nationifo = new ArrayList<>();
nationifo.add(new Nation("VietNam",1945));
nationifo.add(new Nation("Malaysia",1975));
nationifo.add(new Nation("Laos",1943));
NationAdapter adp = new NationAdapter(
MainActivity.this,
R.layout.nation_list,
nationifo
);
listView.setAdapter(adp);
}
}
Nation.java
package com.example.admin.customadapter;
public class Nation {
public String name;
public Integer year;
public Nation(String Name, Integer Year){
Name = name;
Year = year;
}
}
NationAdapter.java
package com.example.admin.customadapter;
import android.annotation.SuppressLint;
import android.content.Context;
import android.text.Layout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.List;
public class NationAdapter extends BaseAdapter {
Context mycontext;
int mylayout;
List<Nation>arrayNation;
public NationAdapter (Context context, int layout, List<Nation>nationList){
mycontext = context;
mylayout = layout;
arrayNation = nationList;
}
public int getCount() {
return arrayNation.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#SuppressLint("ViewHolder")
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) mycontext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(mylayout,null);
TextView txtv1 = (TextView) convertView.findViewById(R.id.textView);
txtv1.setText(arrayNation.get(position).name);
TextView txtv2 =(TextView) convertView.findViewById(R.id.textView2);
txtv2.setText(String.valueOf(arrayNation.get(position).year));
return convertView;
}
}
nation_list.xml
<?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"
android:background = "#ffffff">
<TextView
android:textColor="#ff0400"
android:text="TextView"
android:layout_width="match_parent"
android:layout_height="30dp"
android:id="#+id/textView" />
<TextView
android:textColor="#0022ff"
android:text="TextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/textView2" />
</LinearLayout>
My Android Studio is 2.2. But I don't think that this version is diferrent to another.
try to use the following
convertView = inflater.inflate(mylayout,parent,false);
instead of
convertView = inflater.inflate(mylayout,null);
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;
}
}
}
I am trying to display a custom listview but nothing appears.
My activity:
import java.util.ArrayList;
import org.json.JSONArray;
import org.json.JSONException;
import com.example.elnoorgeh.ServerAPI;
import android.app.Fragment;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView.FindListener;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
public class BlogFragment extends Fragment {
JSONArray jArray;
TextView title;
RelativeLayout layout;
int previousID = 0;
int currentID = 0;
ArrayList<String> titles;
ArrayList<String> contents;
ListView list;
public BlogFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_blog, container,
false);
new AsyncFetch().execute();
return rootView;
}
private class AsyncFetch extends AsyncTask<Object, Object, Object> {
#Override
protected Object doInBackground(Object... params) {
// TODO Auto-generated method stub
jArray = new JSONArray();
jArray = ServerAPI.getData();
titles = new ArrayList<String>();
contents = new ArrayList<String>();
for (int i = 0; i < jArray.length(); i++) {
String blogTitle = null;
String content = null;
try {
blogTitle = jArray.getJSONObject(i).getString("title");
content = jArray.getJSONObject(i).getString("content");
titles.add(blogTitle);
contents.add(content);
} catch (JSONException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println(blogTitle);
System.out.println(content);
}
// display(titles, contents);
return null;
}
protected void onPostExecute(Object result) {
layout = (RelativeLayout) getView().findViewById(R.id.blogPage);
layout.removeAllViews();
CustomList adapter = new CustomList(getActivity(), titles);
list = new ListView(getActivity());
System.out.println("list done");
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(getActivity(),
"You Clicked at " + titles.get(position),
Toast.LENGTH_SHORT).show();
}
});
}
}
public void display(ArrayList<String> t, ArrayList<String> c) {
}
}
Custom ListView class:
import java.util.ArrayList;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class CustomList extends ArrayAdapter<String> {
private final Activity context;
private final ArrayList<String> web;
// private final Integer[] imageId;
public CustomList(Activity context, ArrayList<String>web) {
super(context, R.layout.fragment_listview);
this.context = context;
this.web = web;
// this.imageId = imageId;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView = inflater.inflate(R.layout.fragment_listview, null, true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.txt);
ImageView imageView = (ImageView) rowView.findViewById(R.id.img);
txtTitle.setText((CharSequence) web.get(position));
// imageView.setImageResource(imageId[position]);
return rowView;
}
}
fragment_blog:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/blogPage"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
<TextView
android:id="#+id/txtLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:maxLines="20"
android:singleLine="false"
android:textSize="16dp" />
</RelativeLayout>
fragment_listview:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TableRow>
<ImageView
android:id="#+id/img"
android:layout_width="50dp"
android:layout_height="50dp" />
<TextView
android:id="#+id/txt"
android:layout_width="wrap_content"
android:layout_height="50dp" />
</TableRow>
</TableLayout>
I can't find any errors or notice something irregular, so why is that happening?
you should extend BaseAdapter and implement abstract methods
#Override
public int getCount() {
return web.size();
}
#Override
public Object getItem(int position) {
return web.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
also you might change
txtTitle.setText((CharSequence) web.get(position));
to
txtTitle.setText((CharSequence) getItem(position));
now your adapter don't know size of web array
edit:
you can get one inflater in constructor and keep in class, no need to getting inflater each time (little bit better for perfomance)
LayoutInflater inflater = context.getLayoutInflater();
edit 2:
localhost put proper comment - you are removing all Views from RelativeLayout, also ListView, and creating new ListView without adding to Relative. keeping reference will not auto-add View
protected void onPostExecute(Object result) {
layout = (RelativeLayout) getView().findViewById(R.id.blogPage);
layout.removeView(getView().findViewById(R.id.txtLabel);
//assuming you need to remove only txtLabel
CustomList adapter = new CustomList(getActivity(), titles);
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(getActivity(),
"You Clicked at " + titles.get(position),
Toast.LENGTH_SHORT).show();
}
});
}