New to Android - Fragments - java

New to android programming. For the past 3 days I've been going through tutorials and feel like I get the major parts of it. Every time I try to run the following code, android causes it to force quit before even opening up. I've gotten other more simpler fragments to work with little effort, but this is confusing me. There is no error being printed at all, probably because it shuts down immediately. Any help would be much aprreciated.
EDIT: Using the debugger I was able to get an
"InflateException: Binary XML file #9: Error inflating class fragment.
It stops after the follwing code:
lv = (ListView) view.findViewById(R.id.lvMain);
Frag_MainList.java
public class Frag_MainList extends Fragment implements OnItemClickListener, OnItemLongClickListener{
ListView lv;
ImageView ivAddNote;
Communicator communicator;
Adapter_SQL database = new Adapter_SQL(getActivity());
ArrayList<Element> list;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.frag_mainlist, container, false);
lv = (ListView) view.findViewById(R.id.lvMain);
database.open();
list = database.getChildrenLess();
database.close();
Adapter_List adapter = new Adapter_List(getActivity(), list);
lv.setAdapter(adapter);
lv.setOnItemClickListener(this);
lv.setOnItemLongClickListener(this);
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
#Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
communicator.SendID(pos);
return true;
}
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
database.open();
database.switchComplete(list.get(pos).id);
database.close();
}
public void setCommunicator(Communicator communicator){
this.communicator = communicator;
}
public interface Communicator{
public void SendID(int index);
}
}
Activity_Main.java
public class Activity_Main extends Activity implements Frag_MainList.Communicator{
Frag_MainList frag1;
Frag_ListChildren frag_children;
FragmentManager manager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
manager = getFragmentManager();
frag1 = (Frag_MainList) manager.findFragmentById(R.id.fMainList);
frag1.setCommunicator(this);
}
#Override
public void SendID(int index) {
frag_children = (Frag_ListChildren) manager.findFragmentById(R.id.fListChildren);
if (frag_children != null && frag_children.isVisible()){
frag_children.displayChildren(index);
}else{
Intent intent = new Intent("com.likwid.wishlist.LISTCHILDREN");
intent.putExtra("id", index);
startActivity(intent);
}
}
}
frag_mainlist.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" >
<ListView
android:id="#+id/lvMain"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
activity_main.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="wrap_content"
android:background="#00BBFF"
android:orientation="horizontal"
android:id="#+id/main_layout" >
<fragment
android:id="#+id/fMainList"
android:name="com.likwid.wishlist.Frag_MainList"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
</LinearLayout>

I figured it out. It seems the problem was with the database. getActivity in Frag_MainList would be called before the activity was actually created. Putting getActivity in the the "onActivityCreated" method allowed for getActivity to be properly called and seemed to take away all the problems it was causing. I think the reason it was showing a fragment error is because the fragment was faulty, making inflating in it impossible. Thanks everyone!

Related

TextView in Fragment Returning Null in Android Studio

i am new to Android Studio.. i am facing null pointer exception error on my TextView inside a Fragment, please help..here is my code. this is nothing but a simple interface between two fragments. i am getting Null pointer exception error when i click on an item in ListView Fragment. for sure the TextView in DetailsFragment didn't assign or point to the source of whatever it is. please help on solving this.
public class MainActivity extends AppCompatActivity implements list_Fragment.ItemSelected {
ArrayList<String> Descriptions = new ArrayList<String>();;
TextView tvDescription;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Descriptions.add("Description for Item 1");
Descriptions.add("Description for Item 2");
Descriptions.add("Description for Item 3");
Descriptions.add("Description for Item 4");
tvDescription = findViewById(R.id.tvDescription);
}
#Override
public void onItemSelected(int index) {
tvDescription.setText(Descriptions.get(index));
}}
list_fragment
public class list_Fragment extends ListFragment {
ArrayList<String> Data = new ArrayList<String>();
ItemSelected activity;
public interface ItemSelected{
void onItemSelected(int index);
}
public list_Fragment() {
// Required empty public constructor
}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
activity=(ItemSelected) context;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Data.add("Item 1");
Data.add("Item 2");
Data.add("Item 3");
Data.add("Item 4");
setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, Data));
}
#Override
public void onListItemClick(#NonNull ListView l, #NonNull View v, int position, long id) {
activity.onItemSelected(position);
}
}
and the details Fragment code, where i am getting the error i believe, is
public class DetailsFragment extends Fragment {
public DetailsFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return (LinearLayout) inflater.inflate(R.layout.fragment_details, container, false);
}
}
Main XML file
<?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:id="#+id/ll_Horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
tools:context=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/listfragmentView"
android:name="com.example.fragmentcheck.list_Fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="3"
android:background="#android:color/holo_blue_dark"
tools:layout="#layout/fragment_list_" />
<androidx.fragment.app.FragmentContainerView
android:id="#+id/detailsfragmentView"
android:name="com.example.fragmentcheck.DetailsFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#color/purple_200"
tools:layout="#layout/fragment_details" />
</LinearLayout>
ListFragment 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:id="#+id/linearLayout2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/design_default_color_primary_variant"
android:orientation="vertical"
tools:context=".list_Fragment">
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
DetailsFragment 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:id="#+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/design_default_color_on_secondary"
android:orientation="vertical"
tools:context=".DetailsFragment">
<TextView
android:id="#+id/tvDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/textview"
android:textColor="#FFFFFF"
android:textSize="20sp" />
</LinearLayout>
Error
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.fragmentcheck, PID: 28112
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object r*emphasized text*eference
at com.example.fragmentcheck.MainActivity.onItemSelected(MainActivity.java:34)
at com.example.fragmentcheck.list_Fragment.onListItemClick(list_Fragment.java:54)
tvDescription is in the DetailsFragment layout, you need to do any layout configuration in the code for that Class
i.e.
class DetailsFragment extends Fragment {
...
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_details, container, false)
tvDescription = view.findViewById(R.id.tvDescription);
tvDescription.setText("some text");
return view
}
}
You have tvDescription in DetailsFragment xml, while you are finding it's id in MainAcitvity. MainActivity just have FragmentContainerView , it doen't have any text view inside it.
You need to inflate the Fragment's view and call findViewById() on the View it returns.
Updated DetailsFragment
public class DetailsFragment extends Fragment {
TextView tvDescription;
public DetailsFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_details, container, false)
tvDescription = view.findViewById(R.id.tvDescription);
tvDescription.setText("some text");
return view
}
}
Change both: androidx.fragment.app.FragmentContainerView
To: fragment
In the main_activity xml

How to refresh the data after click the item on listview for fragment

I have two fragments both AFragment and BFragment. The AFragment has a ListView. The BFragment has a Texview and a Button. The Afragment will change the fragment and putString to BFragment when the user clicked the item on ListView. The BFragment got the data from Afragment and display the date to TextView. How can I do?
The sample is like that
You can use libs https://github.com/greenrobot/EventBus . very easy!!!
EventBus in 3 steps
Define events:
public static class MessageEvent { /* Additional fields if needed */ }
Prepare subscribers: Declare and annotate your subscribing method, optionally specify a thread mode:
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {/* Do something */};
Register and unregister your subscriber. For example on Android, activities and fragments should usually register according to their life cycle:
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
Post events:
EventBus.getDefault().post(new MessageEvent());
You can use Interface and LocalBroadcastReceiver both for refreshing the Fragment.
Create one LocalBroadcastReceiver
LocalBroadcastManager.getInstance(context).registerReceiver(refreshFragment ,
new IntentFilter("refreshFragment"));
and its Method in BFragment
private BroadcastReceiver refreshFragment = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Do The Changes You Want To Refresh BFragment
}
};
And Than Call This LocalBroadcastReceiver in OnClick Event of the Button in AFragment.
Intent intent =new Intent("refreshFragment");
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
You can do this by below approach without using external libraries:
Assume you've a MainActivity which hosts the two fragments FragmetA (which has a ListView) and FragmentB (which has the TextView)
Here's the full scenario:
Create an interface # FragmentB which will be used by MainActivity to know when a list item is selected
MainActivity will register a listener to FragmentA by overriding onAttachFramemnt() and implementing this interface
When the user selects a list item from FragmentA; FragmentB will trigger the callback back to MainActivity
MainActivity will forward the trigger to a public method in FragmentB which is used to set the text of the TextView to the current item.
Here is the code:
1. Layout
1.1 activity_main
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
tools:context=".MainActivity">
<fragment
android:id="#+id/fragment_b"
android:name="com.example.android.sendingdatafromfragmenta_to_fragmentb.FragmentB"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<fragment
android:id="#+id/fragment_a"
android:name="com.example.android.sendingdatafromfragmenta_to_fragmentb.FragmentA"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
1.2 fragment_a
<?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">
<ListView
android:id="#+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
1.3 fragment_b
<?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">
<TextView
android:id="#+id/tvSelectedItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="No Item selected" />
</LinearLayout>
2. Java
2.1 MainActivity
public class MainActivity extends AppCompatActivity implements FragmentA.OnListItemClickListener {
private static final String LOG_TAG = "LOG_TAG";
private FragmentB mFragmentB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// inflating fragment B from xml
mFragmentB = (FragmentB) getSupportFragmentManager().findFragmentById(R.id.fragment_b);
}
#Override
public void onAttachFragment(Fragment fragment) {
Log.i(LOG_TAG, "onAttachFragment");
super.onAttachFragment(fragment);
if (fragment instanceof FragmentA) {
((FragmentA) fragment).setOnListItemClickListener(this);
}
}
#Override
public void onListItemClick(String selectedITem) {
mFragmentB.setSelectedITemText(selectedITem);
}
}
2.2 FragmentA
public class FragmentA extends Fragment {
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_a, container, false);
final String[] data = {"item 1", "item 2", "item 3", "item 4", "item 5"};
ListView listView = view.findViewById(R.id.listView);
ArrayAdapter adapter = new ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, data);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (mOnListItemClickListener != null) {
mOnListItemClickListener.onListItemClick(data[position]);
}
}
});
return view;
}
interface OnListItemClickListener {
void onListItemClick(String selectedITem);
}
OnListItemClickListener mOnListItemClickListener;
public void setOnListItemClickListener(OnListItemClickListener listener) {
mOnListItemClickListener = listener;
}
}
2.3 FragmentB
public class FragmentB extends Fragment {
View view;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_b, container, false);
return view;
}
public void setSelectedITemText(String text) {
TextView selectedItemTextView = view.findViewById(R.id.tvSelectedItem);
selectedItemTextView.setText(text);
}
}
Results

Spinner with fragments

I have a layout with spinner and a fragment below it. When I select an item in the spinner it should show related fragments. I'm new to android and I want to know how could I do that. Thanks in advance.
Here is my 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">
<Spinner
android:layout_width="match_parent"
android:layout_height="40dp"
android:id="#+id/spinner"/>
<fragment
android:layout_width="match_parent"
android:layout_height="420dp"
android:id="#+id/fragment"
android:layout_margin="10dp"/>
My Java code:
public class Main extends Activity implements AdapterView.OnItemSelectedListener{
private Spinner spinner;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
spinner = (Spinner) findViewById(R.id.spinner);
ArrayAdapter adapter = ArrayAdapter.createFromResource(this, R.array.spin, android.R.layout.simple_spinner_item);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(Main.this);
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
}
You have to check which value you are getting in selection on spinner than relevant fragment you have to open.
so in
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String selected = parent.getItemAtPosition(position).toString();
if(){
//Open appropriate fragment here.
}
}

Setup the ListFragment to list files from a directory?

I am working on a sound recorder app. I have made the app so that it properly records mp3 files and saves them. Now I want to make it to be able to display the recordings and after they are clicked to start up a custom dialog in which the user can play the file, pause, or move the progress bar...
This is what I basically want to achieve here:
This is what I have at the moment:
I would like to populate the ListFragment with mp3 files from a specific directory. So basically list files from SDCard in ListFragment.
public class TwoFragment extends ListFragment implements AdapterView.OnItemClickListener{
public TwoFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_two, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ArrayAdapter adapter = ArrayAdapter.createFromResource(getActivity(), R.array.heroes, android.R.layout.simple_list_item_1);
setListAdapter(adapter);
getListView().setOnItemClickListener(this);
}
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l){
Toast.makeText(getActivity(), "Item " + i, Toast.LENGTH_SHORT).show();
}
}
And this is the xml file for FragmentTwo
<?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" >
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
<TextView
android:id="#android:id/empty"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</TextView>
</LinearLayout>
I am kinda lost at the moment, I have tried googling, haven't really made any progress as I don't know how to properly "link"(?) the files from sdcard to display in ListView. I should probably do something with the Adapter but I'm not sure. Thanks for any help!

Why instantiateItem doesn't call and ViewPager doesn't work?

I try to make simple application with sliding images. I use this article http://www.androidbegin.com/tutorial/android-viewpager-gallery-images-and-texts-tutorial/.
This is my xml with viewpager:
main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<android.support.v4.view.ViewPager
android:id="#+id/pages"
android:layout_height="match_parent"
android:layout_width="match_parent">
</android.support.v4.view.ViewPager>
</LinearLayout>
this is my xml with image:
item.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageView
android:id="#+id/image"
android:layout_gravity="center"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="#drawable/ic_launcher" />
</RelativeLayout>
this is my adapter:
ViewerPagerAdapter.java
public class ViewerPagerAdapter extends PagerAdapter {
private Context mContext;
private ArrayList<CueModel> mArray;
private LayoutInflater mInflater;
private ImageView mImage;
public ViewerPagerAdapter(Context _context){
mContext = _context;
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void setArray(ArrayList<Bitmap> arr){
mArray = arr;
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
View itemView = mInflater.inflate(R.layout.item, container, false);
mImage = (ImageView)itemView.findViewById(R.id.image);
mImage.setImageBitmap(mArray.get(position));
container.addView(itemView);
return itemView;
}
#Override
public int getCount() {
return mArray.size();
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View)object);
}
#Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0.equals(arg1);
}
this is my activity:
OneActivity.java
(mArrays full of image)
public class OneActivity extends Activity {
ArrayList<Bitmap> mArrays;
ViewerPagerAdapter mAdapter;
ViewPager mPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main.xml);
mPager = (ViewPager) findViewById(R.id.pages);
mAdapter = new ViewerPagerAdapter(OneActivity.this);
mAdapter.setArrays(mArrays);
mPager.setAdapter(mAdapter);
}
}
I don't understand what I did wrong. instantiateItem doesn't call.
PS.Difference between my app and
article I have a few activity(and my arraylist initialized by items)
Thank you
#instantiateItem() is called whenever the ViewPager needs a new View. Initially, it'll call #instantiateItem() twice for the View in the center and view to the right if the adapter's getCount() > 0. That's why in your #setArray() method you need to call #notifyDataSetChanged() every time you change the array. You also need to call it every time you add or remove items from the list. If your array is empty in #onCreate(), then #getCount() == 0 so the ViewPager thinks it's empty and won't bother.
I know this is very old post but I am answering this becoz someone would get benefited. I got the same issue - instantiateItem () was not getting called.
After trying so many thing I manage to finally found the mistake I did in my code and it was a silly one I forgot to set adapter to viewpager:
viewPager.setAdapter(adapter)
For modern versions (2020+) where the error message is
Binary XML file line #(lineNumber): Error inflating class android.viewpager.widget.ViewPager
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
you might want to update
android.support.v4.view.ViewPager to
androidx.viewpager.widget.ViewPager
In my case, the size of the list was zero. Therefore, this method was not calling. When the list was not empty, it worked properly.

Categories