I haven't touched this codebase in a couple of months. Now that I've picked it up again, some code that I didn't think I'd changed has stopped working: All listfragment listviews in the app populated by a simplecursoradapter have stopped working and are just blank. At first I thought the cursor or the database was at fault or that perhaps the adapter wasn't being set correctly, so I added some debugging to the onLoadFinished:
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
Log.d("IndexListFragment", "Rows returned: " + cursor.getCount());
Log.d("IndexListFragment", cursor.getColumnName(0));
Log.d("IndexListFragment", mAdapter.toString());
Log.d("IndexListFragment", this.getListView().getAdapter().toString());
mAdapter.swapCursor(cursor);
}
This returns what I'd expect:
IndexListFragment: Rows returned: 2324
IndexListFragment: _id
IndexListFragment: android.support.v4.widget.SimpleCursorAdapter#41d06a18
IndexListFragment: android.support.v4.widget.SimpleCursorAdapter#41d06a18
So as far as I can tell, the cursor is there and full of data, but swapping it in doesn't get the listview populated. Any ideas?
For completeness, here's the onCreate where the adapter is created and set:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String[] from = new String[] { GuidebookProvider.COL_NAME,
GuidebookProvider.COL_GRADE };
int[] to = new int[] { android.R.id.text1, android.R.id.text2 };
mAdapter = new SimpleCursorAdapter(getActivity(),
android.R.layout.simple_list_item_2, null, from, to, 0);
setListAdapter(mAdapter);
getLoaderManager().initLoader(0, null, this);
}
And the onCreateLoader:
#Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle loaderArgs) {
String orderBy = GuidebookProvider.COL_NAME;
String[] projection = new String[] { GuidebookProvider.COL_ID, GuidebookProvider.COL_NAME, GuidebookProvider.COL_GRADE };
return new CursorLoader(getActivity(),
GuidebookProvider.CONTENT_URI_CLIMB, projection, null, null,
orderBy);
}
Edit: I've done a little more work debugging this issue. The fragment works fine if I run it directly from an activity like this:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.widget.FrameLayout;
public class TestActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FrameLayout frame = new FrameLayout(this);
frame.setId(android.R.id.content);
if (savedInstanceState == null) {
Bundle args = new Bundle();
args.putInt(IndexListFragment.ARGUMENT_INDEX_TYPE, IndexListFragment.IndexType.ALPHA.value);
Fragment indexListFragment = new IndexListFragment();
indexListFragment.setArguments(args);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(android.R.id.content, indexListFragment).commit();
}
}
}
However, calling it as part of a Tab ends up with a blank tab:
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTabHost;
public class TestActivity extends FragmentActivity {
private FragmentTabHost mTabHost;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_tab_host);
mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
Bundle args = new Bundle();
args.putInt(IndexListFragment.ARGUMENT_INDEX_TYPE,
IndexListFragment.IndexType.ALPHA.value);
Drawable drawable = null;
mTabHost.addTab(mTabHost.newTabSpec("A-Z")
.setIndicator("A-Z", drawable), IndexListFragment.class, args);
}
}
Here's my xml for the tabhost:
<?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:orientation="vertical" >
<android.support.v4.app.FragmentTabHost
android:id="#android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="0" />
<FrameLayout
android:id="#+id/realtabcontent"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1" />
</android.support.v4.app.FragmentTabHost>
</LinearLayout>
The fact that the fragment populates correctly when called directly but not when called from within a tab seems to show that the problem isn't at all with the cursors or adapters but with the way the listfragment operating inside a tab.
Can anyone point out what I've done wrong (or what's changed in the last couple of updates of the SDK) to break this code? It used to work fine.
This Code may help you just try it
ViewAllLesson.java :
import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ListView;
import com.xyz.R;
import com.xyz.db.LessonDatabaseConnector;
import com.xyz.pojo.AssignmentPojo;
import com.xyz.pojo.LessonPojo;
public class ViewAllLessons extends Fragment {
public LessonDatabaseConnector dao;
private View rootView;
List<LessonPojo> lessons;
ArrayList<String> con = new ArrayList<String>();
LayoutInflater mInflater;
LessonCustomAdapter lessonCustomAdapter;
private ListView listView;
public static CheckBox selectAll;
private Button deleteBtn;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.add_exams);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.lesson_view_all_list, container,
false);
// dao = new AssignmentDatabaseConnector(getActivity());
listView = (ListView) rootView.findViewById(R.id.Lesson_ListAll);
selectAll = (CheckBox) rootView.findViewById(R.id.SelectAll);
deleteBtn = (Button) rootView.findViewById(R.id.LessonDeleteBtn);
Button addNew = (Button) rootView.findViewById(R.id.LessonAddNewBtn);
addNew.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// Toast.makeText(getActivity(), "hi",
// Toast.LENGTH_LONG).show();
Lesson lesson = new Lesson();
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.item_detail_container, lesson).commit();
}
});
// viewgr.setScrollContainer(false);
dao = new LessonDatabaseConnector(getActivity());
lessons = dao.getAllLessonList();
lessonCustomAdapter = new LessonCustomAdapter(getActivity(), lessons,
this);
listView.setAdapter(lessonCustomAdapter);
/* To Check List View is empty */
if (lessons.size() <= 0) {
View empty = rootView.findViewById(R.id.empty);
ListView list = (ListView) rootView
.findViewById(R.id.Lesson_ListAll);
list.setEmptyView(empty);
listView.setVisibility(0);
empty.setVisibility(1);
}
selectAll.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// Toast.makeText(getActivity(), "hi",
// Toast.LENGTH_LONG).show();
if (((CheckBox) v).isChecked()) {
LessonCustomAdapter.flag = true;
lessonCustomAdapter.notifyDataSetChanged();
} else {
LessonCustomAdapter.flag = false;
LessonCustomAdapter.checkedvalue.clear();
lessonCustomAdapter.notifyDataSetChanged();
}
}
});
// Set the list adapter and get TODOs list via DAO
deleteBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
LessonDatabaseConnector dao = new LessonDatabaseConnector(
getActivity());
for (int i = 0; i < LessonCustomAdapter.checkedvalue.size(); i++) {
//
System.out
.println("===========LessonCustomAdapter.checkedvalue.size()==========SIZE======>>>>"
+ LessonCustomAdapter.checkedvalue.size());
System.out
.println("===========DELETED LESSON=================>>>>"
+ LessonCustomAdapter.checkedvalue.get(i));
dao.DeleteLesson(LessonCustomAdapter.checkedvalue.get(i));
}
LessonCustomAdapter.flag = false;
ViewAllLessons viewAllLessons = new ViewAllLessons();
getFragmentManager().beginTransaction()
.replace(R.id.item_detail_container, viewAllLessons)
.commit();
// finish();
}
});
return rootView;
}
private List<AssignmentPojo> getAllAssignmentsList() {
// TODO Auto-generated method stub
return null;
}
}
LessonCustomAdapter :
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.TextView;
import android.widget.Toast;
import com.xyz.R;
import com.xyz.pojo.LessonPojo;
public class LessonCustomAdapter extends BaseAdapter {
protected static boolean flag = false;
private TextView mLessonTitle, mLessonDate;
private final Context context;
List<LessonPojo> Lessons;
private ViewAllLessons viewAllLessons;
private ArrayList<Boolean> itemChecked = new ArrayList<Boolean>();
private CheckBox SingleChk;
public static ArrayList<Long> checkedvalue = new ArrayList<Long>();
LessonCustomAdapter(Context context, List<LessonPojo> Lessons2,
ViewAllLessons viewAllLessons) {
this.context = context;
this.Lessons = Lessons2;
this.viewAllLessons = viewAllLessons;
for (int i = 0; i < Lessons2.size(); i++) {
itemChecked.add(i, false); // initializes all items value with false
}
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return Lessons.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View rowView = convertView;
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
rowView = inflater.inflate(R.layout.lesson_view_row_list, parent,
false);
}
mLessonDate = (TextView) rowView.findViewById(R.id.LessonDate);
mLessonDate.setText(Lessons.get(position).getLdate());
mLessonTitle = (TextView) rowView.findViewById(R.id.LessonTitle);
mLessonTitle.setText(Lessons.get(position).getLtitle());
SingleChk = (CheckBox) rowView.findViewById(R.id.singleChk);
/*
* if (flag) { System.out.println("66666666666666666666666666666666" +
* flag); for (int i = 0; i < Lessons.size(); i++) {
* SingleChk.setChecked(flag); SingleChk.setEnabled(!flag); }
*
* } else { SingleChk.setChecked(itemChecked.get(position)); }
*/
checkedvalue.clear();
if (ViewAllLessons.selectAll.isChecked()) {
SingleChk.setChecked(true);
Boolean val = false;
for (int i = 0; i < Lessons.size(); i++) {
checkedvalue.add(Long.parseLong(Lessons.get(i).getId()));
System.out
.println("ADD SUCCEFULLYYYYYYYY ====================== "
+ Long.parseLong(Lessons.get(position).getId()));
}
} else {
SingleChk.setChecked(false);
checkedvalue.clear();
}
rowView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Bundle bundle = new Bundle();
ViewSingleLesson viewSingleLesson = new ViewSingleLesson();
bundle.putString("ID", Lessons.get(position).getId());
bundle.putString("TITLE", Lessons.get(position).getLtitle());
bundle.putString("COURSE", Lessons.get(position).getLcourse());
bundle.putString("LEVEL", Lessons.get(position).getLlevel());
bundle.putString("CLASS", Lessons.get(position).getLclass());
bundle.putString("DATE", Lessons.get(position).getLdate());
bundle.putString("DESC", Lessons.get(position).getLdesc());
bundle.putString("ATTACH", Lessons.get(position).getLfilepath());
viewSingleLesson.setArguments(bundle);
viewAllLessons.getFragmentManager().beginTransaction()
.replace(R.id.item_detail_container, viewSingleLesson)
.commit();
}
});
SingleChk.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Boolean val = false;
Toast.makeText(context, "hi " + Lessons.get(position).getId(),
Toast.LENGTH_LONG).show();
if (((CheckBox) v).isChecked()) {
for (int i = 0; i < checkedvalue.size(); i++) {
if (checkedvalue.get(i) == Long.parseLong(Lessons.get(
position).getId())) {
val = true;
System.out
.println("DUPLICATE ====================== "
+ Long.parseLong(Lessons.get(
position).getId()));
} else {
val = false;
}
}
if (val == false) {
checkedvalue.add(Long.parseLong(Lessons.get(position)
.getId()));
System.out
.println("ADD SUCCEFULLYYYYYYYY ====================== "
+ Long.parseLong(Lessons.get(position)
.getId()));
}
} else {
ViewAllLessons.selectAll.setChecked(false);
checkedvalue.remove(Long.parseLong(Lessons.get(position)
.getId()));
System.out
.println("Removed SUCCEFULLYYYYYYYY ====================== "
+ Integer.parseInt(Lessons.get(position)
.getId()));
// itemChecked.set(position, false);
}
}
});
return rowView;
}
}
Got a chance to have a look at this today and finally sorted it out. The problem was in my xml layout setup. Oddly, according to my git repository, this file hasn't changed for 9 months so I guess I was doing something that only worked by accident. I found a tutorial FragmentTabHosts with a different layout and updated my layout to:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<android.support.v4.app.FragmentTabHost
android:id="#android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="0" />
</android.support.v4.app.FragmentTabHost>
<FrameLayout
android:id="#+id/realtabcontent"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1" />
</LinearLayout>
That somehow fixed the issue. A bit more hunting around revealed an example layout xml for FragmentTabHost in the TabActivity documentation: http://developer.android.com/reference/android/app/TabActivity.html
I updated to use the version found in the documentation and it also works:
<android.support.v4.app.FragmentTabHost
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TabWidget
android:id="#android:id/tabs"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"/>
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="0"/>
<FrameLayout
android:id="#+id/realtabcontent"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
</android.support.v4.app.FragmentTabHost>
Given I found it in Android's documentation, I'll stick with this version.
Related
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.
I have to change the views on swipe. This can be obtained through view pager. But I have 60 views and creating 60 different fragment will not be a good approach.
Please someone guide me what will be the best way to design swiping 60 views.
Firstly create one fragment where you can inflate different views using "position" parameter as follow..
public class SuperAwesomeCardFragment extends Fragment {
private static final String ARG_POSITION = "position";
private int position;
View mainView;
public static SuperAwesomeCardFragment newInstance(int position) {
SuperAwesomeCardFragment f = new SuperAwesomeCardFragment();
Bundle b = new Bundle();
b.putInt(ARG_POSITION, position);
f.setArguments(b);
return f;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
position = getArguments().getInt(ARG_POSITION);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if(position==1){
mainview = inflater.inflate(R.layout.layout1, null);
}else if(position==2){
mainview =inflater.inflate(R.layout.layout2, null);
.
.
.
.
}else if(position==50){
mainview =inflater.inflate(R.layout.layout50, null);
}
return mainView;
}
}
Now in Your MainActivity Create an Adapter that extends FragmentPagerAdpater and in getItem() method create the instances of previously create fragment as follow
public class MyPagerAdapter extends FragmentPagerAdapter {
private final String[] TITLES = { "Title1", "Title2"...., "Title50"};
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public CharSequence getPageTitle(int position) {
return TITLES[position];
}
#Override
public int getCount() {
return TITLES.length;
}
#Override
public Fragment getItem(int position) {
return SuperAwesomeCardFragment.newInstance(position);
}
}
}
Then finally add this in your Activity's OnCreat() method...
MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager());
yourViewPager.setAdapter(adapter);
Thus you will have to create single fragment and use it for multiple views.
Thank you. Hope it helps..!!
You can safely use the ViewPager with an implementation of FragmentStatePagerAdapter. The adapter will optimize the memory usage by destroying fragments that are not visible at a given moment. Check the documentation for details and code sample.
Below is the complete code to add Fragments to a View pager.
Since this is just a demonstration I have used just a textView and each fragment added will have a random colour.On clicking a button you can add as many fragments as you want.On clicking the Page you can just remove it from the View Pager.You can move from one Page to another in a View Pager by Swiping to the right or left.
MainActivity.java
import android.graphics.Color;
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.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.widget.Button;
import java.util.ArrayList;
import java.util.Random;
public class MainActivity extends FragmentActivity {
private MyPagerAdapter mpg;
private ArrayList<MyFragment> fragmentlist = new ArrayList<>();
public FragmentManager fmr = getSupportFragmentManager();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ViewPager pager = (ViewPager) findViewById(R.id.viewPager);
mpg = new MyPagerAdapter(fmr,fragmentlist);
pager.setAdapter(mpg);
for (int q = 0; q < 5; q++) {
int r = new Random().nextInt(100) + 155;
int g = new Random().nextInt(100) + 155;
int b = new Random().nextInt(100) + 155;
fragmentlist.add(MyFragment.newInstance(q, "Page number: " + (q + 1), Color.rgb(r, g, b)));
mpg.notifyDataSetChanged();
}
Button B1 = (Button) findViewById(R.id.button);
B1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int r = new Random().nextInt(100) + 155;
int g = new Random().nextInt(100) + 155;
int b = new Random().nextInt(100) + 155;
int count = mpg.getCount();
fragmentlist.add(MyFragment.newInstance(count, "Page number: " + (count+1), Color.rgb(r, g, b)));
mpg.notifyDataSetChanged();
}
});
}
public void delete(int pos) {
int i = 0;
while (i <= fragmentlist.size()) {
if (pos == fragmentlist.get(i).getPosition()) break;
i++;
}
fragmentlist.remove(i);
mpg.notifyDataSetChanged();
}
public class MyPagerAdapter extends FragmentStatePagerAdapter {
private ArrayList<MyFragment> fragmentList;
public MyPagerAdapter(FragmentManager fm, ArrayList<MyFragment> f) {
super(fm);
this.fragmentList = f;
}
#Override
public Fragment getItem(int pos) {
return fragmentlist.get(pos);
}
#Override
public int getCount() {
return fragmentlist.size();
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
}
MyFragment.java
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;
import java.util.List;
public class MyFragment extends Fragment {
int pos;
#Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.f_1, container, false);
pos = getArguments().getInt("num");
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.v("MainActivity", "Deleting at pos - " + pos);
MainActivity activity = (MainActivity) getActivity();
activity.delete(pos);
}
});
TextView tv = (TextView) v.findViewById(R.id.tvFragFirst);
FrameLayout fl = (FrameLayout) v.findViewById(R.id.frame_layout);
tv.setText(getArguments().getString("msg"));
fl.setBackgroundColor(getArguments().getInt("colour"));
return v;
}
public int getPosition() {
return pos;
}
public static MyFragment newInstance(int num,String text,int clr) {
MyFragment f = new MyFragment();
Bundle b = new Bundle();
b.putString("msg", text);
b.putInt("colour", clr);
b.putInt("num",num);
f.setArguments(b);
return f;
}
}
And the xml.files,
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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.example.shakthivels.assingment10.MainActivity"
android:id="#+id/r_v"
>
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/viewPager"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ADD a fragment"
android:id="#+id/button"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
f_1.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"
android:id="#+id/av"
>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:id="#+id/frame_layout">
<TextView
android:id="#+id/tvFragFirst"
android:layout_width="203dp"
android:layout_height="127dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:textSize="26sp"
android:text="TextView"
android:layout_gravity="center"
android:textColor="#000000" />
</FrameLayout>
</RelativeLayout>
1
2
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();
}
});
}
What I need is a Horizontal scrollable ListView that serves as a horizontally scrollable menu.
I searched for a solution and came up with the this library.
I am trying to implement it.sephiroth.android.library.widget.AdapterView.OnItemClickListener on it.sephiroth.android.library.widget.HListView object in a DialogFragment.
I can get the list to populate but I can't seem to be able to attach listeners to the item.
I have been trying for 2 days to figure this out, but no game. This feature is still not working. So I turn to the old WWW for salvation..
This is my DialogFragment XML fragment_layout.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:orientation="vertical"
android:background="#800000"
android:descendantFocusability="blocksDescendants" >
<it.sephiroth.android.library.widget.HListView
android:id="#+id/hlvPlacesListScrollMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:scrollbars="none"
android:divider="#android:color/transparent"
/>
this is my viewitem.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#800000"
android:clickable="false"
android:focusable="false"
android:orientation="vertical" >
<ImageButton
android:id="#+id/ibScrollMenuImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#800000"
android:clickable="false"
android:focusable="false"
android:scaleType="centerCrop" />
<TextView
android:id="#+id/tvScrollMenuTitle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:focusable="false"
android:gravity="center_horizontal"
android:textColor="#f4f4f4" />
</LinearLayout>
This is my main_activity_layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/llDialogFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#34f34f"
android:orientation="vertical"
tools:context=".MainActivity" >
</LinearLayout>
Pretty basic.
My MainActicity is :
package com.example.hscrollviewtest;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.Menu;
public class MainActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
LifeStatsDialogFragment menuFragment = new LifeStatsDialogFragment();
ft.add(R.id.llDialogFragment, menuFragment).commit();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
the Dialogfrgment .java :
package com.example.hscrollviewtest;
import it.sephiroth.android.library.widget.AdapterView;
import it.sephiroth.android.library.widget.AdapterView.OnItemClickListener;
import it.sephiroth.android.library.widget.HListView;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class LifeStatsDialogFragment extends DialogFragment implements
OnItemClickListener {
private HListView scroll;
private View rootView;
private HorizontalScrollMenuAdapter mAdapter;
final String[] IMAGE_TITLE = new String[] { "Home", "Work", "School",
"Sport" };
final int[] MENU_IMAGES = new int[] { R.drawable.ic_circle_home,
R.drawable.ic_circle_work, R.drawable.ic_circle_school,
R.drawable.ic_circle_gym };
public LifeStatsDialogFragment newInstance() {
return new LifeStatsDialogFragment();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
rootView = inflater.inflate(R.layout.fragment_layout, container, false);
mAdapter = new HorizontalScrollMenuAdapter(getActivity(),
R.layout.fragment_layout, R.id.tvScrollMenuTitle, IMAGE_TITLE,
MENU_IMAGES);
scroll = (HListView) rootView
.findViewById(R.id.hlvPlacesListScrollMenu);
scroll.setAdapter(mAdapter);
scroll.invalidate();
scroll.setOnItemClickListener(this);
for (int i = 0; i < scroll.getAdapter().getCount(); i++) {
Log.i(this.getClass().getSimpleName(), "first item in scroll : "
+ scroll.getChildAt(i) + "and its clickable?? "
+ scroll.getAdapter().getItemViewType(i) + "\n");
}
Log.i(this.getClass().getSimpleName(),
"The number of children for HlistView is: "
+ scroll.getParent().toString());
return rootView;
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// TODO Auto-generated method stub
}
}
and this is the adapter(which works when I use it in the HorizontalVariableListViewDemo):
package com.example.hscrollviewtest;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.TextView;
public class HorizontalScrollMenuAdapter extends ArrayAdapter<String>{
private String[] mButtonText;
private int[] mIconId;
private final String TAG = this.getClass().getSimpleName();
//Constructor
public HorizontalScrollMenuAdapter(Context context, int resource,
int textViewResourceId, String[] menuItemName, int[] menuItemImage) {
super(context, resource, textViewResourceId, menuItemName);
// TODO Auto-generated constructor stub
mButtonText = menuItemName;
mIconId = menuItemImage;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return mIconId.length;
}
#Override
public String getItem(int position) {
// TODO Auto-generated method stub
return null;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
LayoutInflater mInflater = (LayoutInflater) parent.getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.viewitem, null);
holder = new ViewHolder();
holder.name = (TextView) convertView.findViewById(R.id.tvScrollMenuTitle);
holder.icon=(ImageButton) convertView.findViewById(R.id.ibScrollMenuImage);
//holder.icon.setBackgroundResource(android.R.color.transparent);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.name.setText(mButtonText[position]);
holder.icon.setImageResource(mIconId[position]);
holder.icon.setTag(mIconId[position]);
Log.d(TAG,"returned view to fragment");
return convertView;
}
static class ViewHolder{
TextView name;
ImageButton icon;
}
}
I hope one of you can see my blindspot.
Thaks
Probably you are implementing the wrong OnItemClickListener.
Try to use
public class LifeStatsDialogFragment extends DialogFragment implements
it.sephiroth.android.library.widget.AdapterView.OnItemClickListener {
//...
}
I would try 2 things:
Put the fragment in the xml layout in the first place, and avoid add in the onCreate.
What happens in the onItemClick? - its currently empty. Try using an independent onItemClickListener:
list.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(getActivity(), "clicked", Toast.LENGTH_SHORT);
}
});
I have one main activity which is fragment activity here I am setting two tabs with two fragments A and B in the B fragment I have one button when the user click on the button I want to change fragment B to fragment C. But the tabs above are visible...
How I can achieve replacing fragments inside tabs?
Any solution are greatly appreciated.
Basic concept- We can achieve this by creating a container. Each tab will be assigned with a specific container. Now when we need a new fragment then we will replace same using this container.
Kindly follow undermentioned code step by step to have better understanding.
Step-1: Create Tabs for your app. Say "Home.java". It will contain code for creating tabs using fragment.
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTabHost;
import android.widget.TextView;
import app.drugs.talksooner.container.GoContainerFragment;
import app.drugs.talksooner.container.LearnContainerFragment;
import app.drugs.talksooner.container.MoreContainerFragment;
import app.drugs.talksooner.container.TalkContainerFragment;
import app.drugs.talksooner.container.WatchContainerFragment;
import app.drugs.talksooner.utils.BaseContainerFragment;
public class Home extends FragmentActivity {
private static final String TAB_1_TAG = "tab_1";
private static final String TAB_2_TAG = "tab_2";
private static final String TAB_3_TAG = "tab_3";
private static final String TAB_4_TAG = "tab_4";
private static final String TAB_5_TAG = "tab_5";
private FragmentTabHost mTabHost;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.home);
initView();
}
private void initView() {
mTabHost = (FragmentTabHost)findViewById(android.R.id.tabhost);
mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
// mTabHost.addTab(mTabHost.newTabSpec(TAB_1_TAG).setIndicator("Talk", getResources().getDrawable(R.drawable.ic_launcher)), TalkContainerFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec(TAB_1_TAG).setIndicator("Talk"), TalkContainerFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec(TAB_2_TAG).setIndicator("Learn"), LearnContainerFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec(TAB_3_TAG).setIndicator("Go"), GoContainerFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec(TAB_4_TAG).setIndicator("Watch"), WatchContainerFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec(TAB_5_TAG).setIndicator("More"), MoreContainerFragment.class, null);
/* Increase tab height programatically
* tabs.getTabWidget().getChildAt(1).getLayoutParams().height = 150;
*/
for (int i = 0; i < mTabHost.getTabWidget().getChildCount(); i++) {
final TextView tv = (TextView) mTabHost.getTabWidget().getChildAt(i).findViewById(android.R.id.title);
if (tv == null)
continue;
else
tv.setTextSize(10);
}
}
#Override
public void onBackPressed() {
boolean isPopFragment = false;
String currentTabTag = mTabHost.getCurrentTabTag();
if (currentTabTag.equals(TAB_1_TAG)) {
isPopFragment = ((BaseContainerFragment)getSupportFragmentManager().findFragmentByTag(TAB_1_TAG)).popFragment();
} else if (currentTabTag.equals(TAB_2_TAG)) {
isPopFragment = ((BaseContainerFragment)getSupportFragmentManager().findFragmentByTag(TAB_2_TAG)).popFragment();
} else if (currentTabTag.equals(TAB_3_TAG)) {
isPopFragment = ((BaseContainerFragment)getSupportFragmentManager().findFragmentByTag(TAB_3_TAG)).popFragment();
} else if (currentTabTag.equals(TAB_4_TAG)) {
isPopFragment = ((BaseContainerFragment)getSupportFragmentManager().findFragmentByTag(TAB_4_TAG)).popFragment();
} else if (currentTabTag.equals(TAB_5_TAG)) {
isPopFragment = ((BaseContainerFragment)getSupportFragmentManager().findFragmentByTag(TAB_5_TAG)).popFragment();
}
if (!isPopFragment) {
finish();
}
}
}
Your home.xml file
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/realtabcontent"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1" />
<android.support.v4.app.FragmentTabHost
android:id="#android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="0dip"
android:layout_height="0dip"
android:layout_weight="0" />
</android.support.v4.app.FragmentTabHost>
</LinearLayout>
Step-2: Define Base container fragment which will be helpful for backtracking and replacment of fragments "check out replaceFragement() ". Our class "BaseContainerFragment.java"
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import app.drugs.talksooner.R;
public class BaseContainerFragment extends Fragment {
public void replaceFragment(Fragment fragment, boolean addToBackStack) {
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
if (addToBackStack) {
transaction.addToBackStack(null);
}
transaction.replace(R.id.container_framelayout, fragment);
transaction.commit();
getChildFragmentManager().executePendingTransactions();
}
public boolean popFragment() {
Log.e("test", "pop fragment: " + getChildFragmentManager().getBackStackEntryCount());
boolean isPop = false;
if (getChildFragmentManager().getBackStackEntryCount() > 0) {
isPop = true;
getChildFragmentManager().popBackStack();
}
return isPop;
}
}
Step3: Now here I am considering for one fragment only hoping that rest can be handled by you in same fashion. Defining container Fragment class. Each tab will have specific container. Say TalkContainerFragment.java for first tab
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import app.drugs.talksooner.R;
import app.drugs.talksooner.Talk;
import app.drugs.talksooner.utils.BaseContainerFragment;
public class TalkContainerFragment extends BaseContainerFragment {
private boolean mIsViewInited;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.e("test", "tab 1 oncreateview");
return inflater.inflate(R.layout.container_fragment, null);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.e("test", "tab 1 container on activity created");
if (!mIsViewInited) {
mIsViewInited = true;
initView();
}
}
private void initView() {
Log.e("test", "tab 1 init view");
replaceFragment(new Talk(), false);
}
}
It's xml file. "container_fragment.xml" this xml container contains frameLayout. we will use this id to replace different Fragments.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container_framelayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
Your main class. "Talk.java"
public class Talk extends Fragment {
/** Define global variables over here */
//private ProgressDialog pDialog;
StaticApiList sal;
TalkModelAll tma;
JSONObject myJasonObject = null;
private ListView lv;
private ArrayList<TalkModelAll> m_ArrayList = null;
//ArrayList<String> stringArrayList = new ArrayList<String>();
TalkArrayAdapter taa;
Set<String> uniqueValues = new HashSet<String>();
TextView rowTextView = null;
boolean vivek = false;
int postid;
String title;
String thumsrc;
String largeimg;
String excert;
String description;
String cat;
String myUrl;
String jsonString;
int mCurCheckPosition;
String check_state = null;
String ccc;
LinearLayout myLinearLayout;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.talk, container, false);
Button btn = (Button) rootView.findViewById(R.id.your_btn_id);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
//Here TalkDetail is name of class that needs to open
TalkDetail fragment = new TalkDetail();
// if U need to pass some data
Bundle bundle = new Bundle();
bundle.putString("title", m_ArrayList.get(arg2).title);
bundle.putString("largeimg", m_ArrayList.get(arg2).largeimg);
bundle.putString("excert", m_ArrayList.get(arg2).excert);
bundle.putString("description", m_ArrayList.get(arg2).description);
bundle.putString("cat", m_ArrayList.get(arg2).cat);
//bundle.putInt("postid", m_ArrayList.get(arg2).postid);
fragment.setArguments(bundle);
((BaseContainerFragment)getParentFragment()).replaceFragment(fragment, true);
}
});
return rootView;
}
}
That's it. You are good to go. The whole magic lies in calling R.id. instead of R.layout.
Cheers!