Using MPChartLibrary within a fragment - android

I am working on an Android project and I am trying to implement a Library called MPAndroidChart from https://github.com/PhilJay/MPAndroidChart.
I am trying to implement it in a fragment but I keep getting an error and I cannot see why.
Below is my activity.
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
Fragment chartFragment = new ChartFragment();
transaction.replace(R.id.fragmentContainer, chartFragment);
transaction.commit();
}
}
Below is my activities layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="#layout/toolbar" />
<FrameLayout android:id="#+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Below is my Fragment class
public class ChartFragment extends Fragment
{
private LineChart mChart;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.graph, container, false);
return v;
}
}
And below is the layout for the fragment
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.github.mikephil.charting.charts.LineChart
android:id="#+id/lineChart1"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
At the moment it crashes when it tries to inflate the view in my OnCreateView function.
The error I am getting is:
java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.MyCompany.ChartTest/com.MyCompany.ChartTest.MainActivity}:
android.view.InflateException: Binary XML file line #5: Error
inflating class com.github.mikephil.charting.charts.LineChart

I honestly do not see anything that could be wrong.
The only difference I see between the Fragments used in the example project is that they use wrap_content instead of match_parent for the width and height of the chart.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.github.mikephil.charting.charts.LineChart
android:id="#+id/lineChart1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>

I've managed to confirm where the problem is.
I have my apps theme defined in a library that is used by my various other apps, but for some reason when referencing the theme from the library when using MPAndroidChartLib I get this exception. If I copy and paste the theme style from my Library and it to my apps own styles file and reference this instead it works fine.

Try this, it may help:
<?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"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.github.mikephil.charting.charts.LineChart
android:id="#+id/lineChart1"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
The line:
xmlns:app="http://schemas.android.com/apk/res-auto"
is important.
I hope it helps.

I struggled with this exact issue and finally found a working solution.
The clue was an error message on the design preview of the chart fragment:
The following classes could not be instantiated:
charting.charts.LineChart
Exception Details
java.lang.ClassNotFoundException:
com.nineoldandroids.animation.ValueAnimator$AnimatorUpdateListener
Adding com.nineoldandroids:library:2.4.+ to my project's build.gradle file fixed the issue:
dependencies {
compile 'com.android.support:support-v4:19.1.0'
compile 'joda-time:joda-time:2.5'
compile 'com.nineoldandroids:library:2.4.+'
compile files('libs/MPChart.jar')
}

Adding lines below in onCreate() did the trick for me
getActivity().getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);

Related

Collapsingtoolbar in fragment not show/hide header when scrolling

I replace fragment in a activity and in my fragment I need a CoordinatorLayout.
Here is my code :
CoordinatorActivity class:
public class CoordinatorActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_coordinator);
Fragment newFragment = new FragmentCoordinator();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fr_main, newFragment);
transaction.addToBackStack(null);
transaction.commit();
}
}
activity_coordinator.xml file:
<?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"
android:id="#+id/fr_main"
tools:context="com.app.hoatv.CoordinatorActivity">
</FrameLayout>
FragmentCoordinator class:
public class FragmentCoordinator extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_coordinator, container, false);
}
}
fragment_coordinator.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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.app.hoatv.CoordinatorActivity">
<android.support.design.widget.CoordinatorLayout
android:layout_height="match_parent"
android:layout_width="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
app:elevation="0dp"
android:fitsSystemWindows="true"
android:theme="#style/AppTheme">
<include layout="#layout/layout_group_header"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_height="match_parent"
android:layout_width="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:fillViewport="true">
<android.support.v7.widget.AppCompatTextView
android:layout_height="1000dp"
android:layout_width="match_parent"
android:text="#string/lorem"
android:background="#color/colorAccent"
android:id="#+id/container"/>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
</LinearLayout>
layout_group_header.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="100dp"
android:background="#a70000">
</LinearLayout>
but when I scrolling NestedScrollView layout_group_header.xml not show or hide. It always show in my fragment screen.
What happened in my code? and How I can fix it?
What happened in my code? and How I can fix it?
There are few things which you should consider. First, you are opening a view(LinearLayout) inside AppBarLayout which there might be a Toolbar but that's not just the case.
First part: (Important one): The best idea and correct way of creating such layouts is to first, remove LinearLayout from the root of the fragment_coordinator layout then copy-paste the codes from fragment_coordinator to activity_coordinator. After that, use FrameLayout as the content's Container inside NestedScrollView.
Making Changes Part (As your requirements): After all, you can place codes anywhere you want in the main layout, for example, if you want the layout_group_header to be hidden after scrolling in the layout, you may wanna use layout_group_header codes inside fragment_coordinator which it will be a scrolling content. Othewise, you can use the codes inside CoordinatorLayout or anywhere instead of including it like that.
P.s: Design is completely seems to be wrong. Use first part which is an important part of creating such layouts. Note that there will be some changes inside java-kotlin sides too. (Changing layout address or etc)

No view found for id for fragment, even that the FrameLayout is a child of the main layout

I've created code so that Fragment is added dynamically when I tap on a menu button. However I get the error:
No view found for id 0x7f0d009a (tech.glasgowneuro.attysecg:id/fragment_container2) for fragment XYPlotFragment{a75aa2e #0 id=0x7f0d009a}
I've been through all the other posts here and the std answer is that the Frame layout needs to be child of the main layout. I think I've done that right. Still no id is found.
activity_plot_window.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainlayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<tech.glasgowneuro.attysecg.InfoView
android:id="#+id/infoview"
title="Plot Window"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp" />
<tech.glasgowneuro.attysecg.RealtimePlotView
android:id="#+id/realtimeplotview"
title="Plot Window"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp" />
</RelativeLayout>
<FrameLayout
android:id="#+id/fragment_container2"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</RelativeLayout><!-- </LinearLayout> -->
main JAVA code of the Activity:
public class AttysECG extends AppCompatActivity {
...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
....
setContentView(R.layout.activity_plot_window);
Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
setSupportActionBar(myToolbar);
....
}
...
case R.id.showplot:
// Create a new Fragment to be placed in the activity layout
XYPlotFragment plotFragment = new XYPlotFragment();
// Add the fragment to the 'fragment_container' FrameLayout
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container2, plotFragment).commit();
The question is why do I get this exception? If I do a findViewById(fragment_container2) then the result is null.
How can I get a valid id for the fragment_container2?
At this point the view is certainly inflated because I trigger this crash long after the app has been started.
I've figured it out. Android studio created two "activity_plot_window.xml" files. One has the suffix _v21 so that there are two versions for the older APIs and the newer ones. It's explained here:
https://developer.android.com/training/material/compatibility.html
I've added the Framelayout to the _v21 file and now it works. See the screenshot. It's very easy to oversee when not expanded (just a grey (2)).
You need to find it through FragmentManager:
getSupportFragmentManager().findFragmentById(R.id.fragment_container2);

Fragment with TextInputLayout crashes app on Android Marshmallow

I've discovered the following issue. I use Material Design' class android.support.design.widget.TextInputLayout in XML layout.
When I inflate this layout in fragment, my app falls with the following error:
android.view.InflateException: Binary XML file line #563: Error inflating class <unknown>
The fall occures on Samsung Galaxy S7 with Android 6.0.1. When I start the app on Lenovo A319 with Android 4.4.2 everything goes fine, no crash.
When I use XML layout with android.support.design.widget.TextInputLayout class for activity (without any fragments), Galaxy S7 works fine too.
It seems that there is something wrong on Marshmallow when app tries to inflate android.support.design.widget classes in fragment.
Is there some way to fix that?
Here is my code:
DocumentEditFragment.java
public class DocumentEditFragment extends BaseFragment {
...
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View view = inflater.inflate(R.layout.fragment_document_edit, container, false); // The app falls here on Galaxy S7
...
}
DocumentActivity.java
public class DocumentActivity extends AppCompatActivity {
private DocumentEditFragment docEditFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_document);
docEditFragment = new DocumentEditFragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.fragment_document, docEditFragment);
ft.commit();
}
}
fragment_document_edit.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"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="0dp"
android:layout_margin="0dp"
<ScrollView
android:id="#+id/doc_edit_scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:layout_marginLeft="16dp"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
>
...
<!-- line #563 is below: -->
<android.support.design.widget.TextInputLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="22dp"
android:layout_marginLeft="60dp"
android:layout_marginRight="16dp"
app:errorEnabled="true"
android:theme="#style/TextLabel"
>
<android.support.v7.widget.AppCompatEditText
android:id="#+id/doc_edit_comment"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="14sp"
android:text="1st line\n2nd line"
android:singleLine="false"
android:hint="Comment"
android:textColorHint="#69202020"
/>
</android.support.design.widget.TextInputLayout>
</ScrollView>
</LinearLayout>
activity_document.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/fragment_document"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="my.app.DocumentFragment"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
tools:context="my.app.DocumentFragment"
/>
UPDATE:
I've uploaded the sample project that produces the same error on Galaxy S7 edge as my working project does (I cannot make public the corporate project). Here is the repository link.
SOLVED
I've moved the attribute
android:theme="#style/TextLabel"
from <android.support.design.widget.TextInputLayout /> into <android.support.v7.widget.AppCompatEditText /> - and everything goes fine! Thanks to Nico from Udacity for wise advice!

How to get included views with Android Databinding?

I'm playing with Android databinding library and I'm trying to use it with included layouts.
The code I have is like this:
activity_main.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id = "#+id/linearLayout">
<include
layout="#layout/view" />
</LinearLayout>
</layout>
view.xml
<View xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id = "#+id/myView">
</View>
MainActivity.java
public MainActivity extends AppCompatActivity{
private ActivityMainBinding mBinding;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
LinearLayout layout = mBinding.linearLayout; // this field is visible
View myView = mBinding.myView // THIS FIELD IS NOT VISIBLE
}
}
As I have written in comments the view myView which is declared in an "included" layout is not visible. If I replace the with the actual code in the view.xml then mBinding.myView becomes visible, the cause seems to be the include then.
The official documentation states only that
"Data binding does not support include as a direct child of a merge element."
but in my case View is a child of LinearLayout, it's not a direct child..
Any hints?
You need to provide an ID to the include statement:
<include android:id="#+id/included"
layout="#layout/view" />
Now you can access the include view:
View myView = mBinding.included;
If your included layout is a binding layout, the include will be a generated Binding. For example, if view.xml is:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#{#android:color/black}"
android:id="#+id/myView"/>
</layout>
then the layout field will be a ViewBinding class:
View myView = mBinding.included.myView;

How to display one activity inside another in Android?

I have one activity and want to display another inside it. Here's my layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1">
</LinearLayout>
</LinearLayout>
How can I display an Activity in inner LinearLayout on button click?
Use one layout for several activities
Layout instance is inflated for each activity using a setContentView method, usually in onCreate:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_common_layout);
}
So there's no problem to use the same XML layout for different activities.
Display one activity inside another
You can use a Fragment API to complete the task. See full details in developer's guide.
Declare a layout like that and Android will create fragments for you:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<fragment android:name="com.example.MyFragment"
android:id="#+id/my_fragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1" />
</LinearLayout>
Then create a MyFragment class and load it when appropriate.
Create fragments yourself. Do not define the Fragment in XML layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/my_parent_layout">
</LinearLayout>
After your parent Activity is created you can add a new Fragment in this way:
FragmentManager fragmentManager = getFragmentManager()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
MyFragment fragment = new MyFragment();
fragmentTransaction.add(R.id.my_parent_layout, fragment);
fragmentTransaction.commit();
Here MyFragment is defined like this:
public class MyFragment extends Fragment {
...
}
If you're targeting below Android 3.0, consider using support package for that.

Categories

Resources