Include layout in view programmatically within a fragment - java

Alright so I have a fragment and I'd like to include, within its' xml file another layout which is programmatically inflated
Fragment:
public class zGoal_Fragment extends Fragment{
private LinearLayout todayView;
private View view;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.main_goal_view, container, false);
todayView = (LinearLayout)view.findViewById(R.id.todayView);
return view;
}
}
xml's file for fragment:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:id="#+id/todayView"
>
</LinearLayout>
and xml layout I want included within the above xml programmatically:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/goalEditLayout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#color/test_color_two"
>
</LinearLayout>
I've tried a couple different methods all of which led to " on a null object reference" errors...
plz help :))

I suppose the solution which you are looking for are Android ViewStubs. These are dynamically inflated layouts.
For more information you could refer these :
How to use View Stub in android
https://developer.android.com/reference/android/view/ViewStub.html
However, if you don't wish to inflate one layout inside another during runtime, you could try this the include tag:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:id="#+id/todayView">
<include layout="#layout/your_layout_file_name"/>
</LinearLayout>

Have you tried something like this:
LinearLayout child = getLayoutInflater().inflate(R.layout.goalEditLayout, null);
todayView.addView(child);
Edit:
Inside onCreateView:
LinearLayout inflatedLayout = (LinearLayout) inflater.inflate(R.layout.goalEditLayout, todayView, true);

Related

Load fragment with layout from another APK

I have two APKs. First APK is a main APK which loads second APK.
MainActivity.java (first APK): Object mainFragment was loaded by DexClassLoader early
setContentView(R.layout.activity_main);
LinearLayout fragContainer = findViewById(R.id.main_fragment);
LinearLayout ll = new LinearLayout(context);
ll.setOrientation(LinearLayout.HORIZONTAL);
ll.setId(View.generateViewId());
getSupportFragmentManager().beginTransaction().add(ll.getId(), mainFragment, "mainFragment").commit();
fragContainer.addView(ll);
activity_main.xml (first APK):
<?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="horizontal" >
<LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="#+id/main_fragment"
android:orientation="vertical"
/>
</LinearLayout>
MainFragment.java (second APK):
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, viewGroup, false);
view.findViewById(R.id.emailSignInButton).setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
}
});
return view;
}
fragment_main.xml (second APK):
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:text="#string/sign_in"
android:layout_width="88dp"
android:layout_height="wrap_content"
android:id="#+id/emailSignInButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="32dp"
android:layout_marginEnd="32dp" android:layout_marginTop="8dp"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
I don't understand, why in the line
View view = inflater.inflate(R.layout.fragment_main, viewGroup, false);
view is always NULL. Do I need to load R.layout.fragment_main into memory like mainFragment?
#CommonsWare already answered you: you are loading classes, not resources.
In Android´s packages, you have both classes (Like R), and resources (Preprocessed XML files, like layouts, for example). A ClassLoader is capable of reading and loading the first ones, so, loading another´s APK R class is possible. But R´s indexes just point towards resource files, they don´t contain the actual values of said resources. So, the R class you sideloaded does not provide the route to a valid resource. If R could do that, then the APK/AAR/APKLib formats would not exists; regular JAR files would suffice. But they don`t,because android resource files are different from class files, and thus, a "link" of sorts is necessary to make them visible to your classes: the R class.
if you want to make your current code work, you need to replace fragment_main.xml with a coded viewgroup instance. Create a class/method providing a constraintLayout instance housing your button (MyViewFactory.createConstraintLayoutWithButton, for example), set the properties via code, and replace
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, viewGroup, false);
view.findViewById(R.id.emailSignInButton).setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
}
});
return view;
}
with something like
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle savedInstanceState) {
View view = MyViewFactory.createConstraintLayoutWithButton(getContext)
view.findViewById(R.id.emailSignInButton).setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
}
});
return view;
}
As long as you don´t use resources, you´ll be fine. That said, this approach is quite fragile, so maybe it would be better to create intent filters between your APKs in order to make APK 2 to work for APK 1.
Edit:
You can use the R constants as ids for your code generated views, as long as you set them manually first. For example:
public static ConstraintLayout createConstraintLayoutWithButton(Context context){
Constraintlayout mylayout = new ConstraintLayout(context);
//set up of the layout
Button myButton = new Button(context);
//set up of the button
button.setId(R.id.emailSignInButton);
myLayout.addView(button);
return mylayout;
}
And then you can locate that button with the id.

Hide the textview from included layout in Fragment class [duplicate]

I have a fragment class which uses Recycleview to show list of Text and Image.
How can I access Recycleview row items and set an custom text to any Textview or Hide the Desired Textview from fragment class.
This is my layout
<?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:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:paddingBottom="4dp"
android:paddingLeft="2dp"
android:paddingRight="2dp"
android:paddingTop="4dp">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none" />
<include
android:id="#+id/include_tag"
layout="#layout/row_item"/>
</FrameLayout>
and My row item layout is
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res /android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent">
<TextView
android:id="#+id/flower_Name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textStyle="bold"
android:maxLines="1"
android:layout_centerInParent="true"
android:gravity="center_vertical|center_horizontal"
android:textAlignment="center"
android:textColor="#E91E63"
android:fontFamily="sans-serif-condensed"
android:text="Sagar Rawal"/>
<TextView
android:layout_marginTop="8dp"
android:id="#+id/flower_details"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textStyle="bold"
android:maxLines="3"
android:textColor="#673AB7"
android:text="This Text need to Be Change "/>
</RelativeLayout>
and my Fragment class i s
public View onCreateView(final LayoutInflater inflater, #Nullable final ViewGroup container, #Nullable Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.activity_main, container, false);
View test1View = view.findViewById(R.id.include_tag);
mhideText = (TextView) test1View.findViewById(R.id.flower_details);
mhideText.setVisibility(View.INVISIBLE);
return view;
But it doesn't work. and Textview is still Visible.
Please help. Thanks in advance.
You must have a custom ViewHolder which should extends RecyclerView.ViewHolder. In your ViewHolder you can link row item and you can access all views from your row layout.
Your custom ViewHolder looks like:
public static class MyViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView textView;
public MyViewHolder(TextView v) {
super(v);
textView = v;
//Note: To set custom text
textView.setText("My custom text");
//Note: To hide TextView remove comment from below line
//textView.setVisibility(View.GONE);
}
}
Above code shows sample ViewHolder as MyViewHolder where you can access your views.
If you are passing parent Layout to MyViewHolder instead of passing TextView then you can find child views using v.findViewById(R.id.xxx)
Your adapter should contain similar code as below:
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
TextView v = (TextView) LayoutInflater.from(parent.getContext())
.inflate(R.layout.my_text_view, parent, false);
...
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
In above code snippet, creating instance of MyViewHolder by passing the view TextView. You can pass parent layout in your case its RelativeLayout from your row layout.
Use this ViewHolder to take any actions on views like set custom text to TextView or you can hide TextView as per your requirements.
To refer full example you can follow the android documentation or click here.
To achieve communication between ViewHolder and fragment you can use Interface.
Thank you!
Try doing this :
rowview = inflater.inflate(R.layout.row_item, container, false);
mhideText = (TextView)rowview.findViewById(R.id.flower_details);
mhideText.setVisibility(View.INVISIBLE);

ImageView In Fragment not showing

I have a strange issue that I have a workaround for but wondered if anyone could shed some light on why this is happening and a more elegant fix maybe?
I have a ViewPager with a series of Fragments. The Fragments use their own layout and when an ImageView is added to the layout the ImageView isnt rendered at runtime.
If I explicitly set the imageDrawable for the ImageView inside the Fragment's onCreateView method (even though the image is the same image as being referenced in the layout xml then the image shows fine.
Here is my Fragment xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="#+id/baseRelLayout"
android:background="#color/colorPrimary">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="#drawable/flamerite_remote_6"
android:layout_marginStart="36dp"
android:id="#+id/remote6ButtonImage"
android:layout_alignParentBottom="false"
android:layout_alignStart="#+id/textView3"
android:scaleType="fitXY"
android:background="#color/colorPrimary"
android:layout_alignBottom="#+id/remote9ButtonImage" />
</RelativeLayout>
And here is where I am re-setting the image drawable inside onCreateView
public class WizardFragment extends Fragment {
public static final String STEP_NUMBER = "STEP_NUMBER";
public static final WizardFragment newInstance(String message){
WizardFragment f = new WizardFragment();
Bundle bdl = new Bundle(1);
bdl.putString(STEP_NUMBER,message);
f.setArguments(bdl);
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View v = inflater.inflate(R.layout.wizard_fragment_step_1, container, false);
ImageView remoteImage9Button = (ImageView)v.findViewById(R.id.remote9ButtonImage);
remoteImage9Button.setImageDrawable(ResourcesCompat.getDrawable(getResources(),R.drawable.flamerite_remote_9, null)); //THIS IS THE LINE THAT MAKES THE IMAGE WORK AGAIN
return v;
}
}
I can of course keep this re-set of the imageDrawable in but think it is strange that the image shoudlnt be showing when only set in the xml layout
Any thoughts greatly appreciated!!
I do not know the reason, but in my case the same issue was resolved when I changed
image src definition from
app:srcCompat="#drawable/logo"
to
android:src="#drawable/logo"
Just add android:src="#drawable/logo" instead of app:srcCompat

Android how to load different images in a webview after short time intervals

Im implementing a small app which having a webview.i want to load different images (banners) on top of it.here is my current working..
my xml file
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<WebView
android:id="#+id/webview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
</LinearLayout>
</ScrollView>
my java code..(still not implement multiple image load in small intervals part )
public class FirstFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_one, null);
// Getting reference to WebView of the fragment_one layout
mWebView = (WebView) root.findViewById(R.id.webview);
mWebView.getSettings().setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);
mWebView.loadUrl("http://thailandshoponline.com/wp-content/uploads/2013/01/Thailand- Shop-Online-Banner-2.gif");
return root;
}
}
i think i have to use timer to delay the refreshing task.but i doesn't know the proper way of doing it..please help

Add layouts to a fragment programmaticcaly

Introduction
I want to have different fragments depending on the user's choice from the navigation drawer. For every item in the navigation drawer is a different site that should called. I want to achieve this by fragments.
The main fragment will get displayed first by doing the following in the onCreate-method
if ( savedInstanceState == null ) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
Fragment fragment = MainFragment.passList(hashMap);
ft.replace(R.id.content_frame, new MainFragment());
ft.commit();
}
As you can see I'm passing data (a hashmap) to a method of the fragment which works perfectly. The data then gets put into string arrays. This works and the data can also be used in the onCreate-method of the fragment.
This is the xml of the main activity
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ListView
android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#android:color/darker_gray"
android:dividerHeight="0.1dp" />
</android.support.v4.widget.DrawerLayout>
And this is the XML of the main fragment
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainRelativeLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/activatedBackgroundIndicator"
android:gravity="center_vertical"
android:paddingRight="10dp"
>
<ScrollView
android:id="#+id/mainScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1.03" >
<LinearLayout
android:id="#+id/mainListView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
</LinearLayout>
</ScrollView>
</RelativeLayout>
What I want to achieve now is to display data in the scroll view. But the question I have, is how do I populate that and how do I initliaze it?
Normally I would go and just create them like that - because findViewById doesn't work in a Fragment (Have to write the method by my own)
ScrollView sv = new ScrollView(getActivity());
LinearLayout ll = new LinearLayout ( getActivity() );
sv.addView(ll);
ll.addView(SAMPLETEXTVIEW);
View mainView = inflater
.inflate(R.layout.main_fragment, container, false);
return mainView;
but that just leaves me with a blank screen and no actual text added. How can I achieve this? The data is there - I know that, because it gets printed out with System.out.println - I just need a way to display it. Thx in advance!
EDIT
When I do it like that
View rootView = inflater.inflate(R.layout.main_fragment, container, false);
ScrollView sv = (ScrollView) rootView.findViewById(R.id.mainScrollView);
LinearLayout ll = (LinearLayout) rootView.findViewById(R.id.mainListView);
sv.addView(ll);
I get just an IllegalStateException that ScrollView can only host one direct child... But I don't get it. The linearlayout is the only thing that is the direct child. Why is there a problem?
Here is the complete onCreateView-method
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.main_fragment, container, false);
ScrollView sv = (ScrollView) rootView.findViewById(R.id.mainScrollView);
LinearLayout ll = (LinearLayout) rootView.findViewById(R.id.mainListView);
sv.addView(ll);
source = new TextView[hashMapSize];
for (int i = 0; i < hashMapSize; i++) {
source[i] = new TextView(getActivity());
source [i].setText( "Source: " + sourceArr [i] );
ll.addView(source[i]
}
return rootView;
}
The reason you get the IllegalStateException is because you inflate your R.layout.main_fragment which already contains your ScrollView that already has one direct child (declared in you layout xml).
You shouldn't add in code with sv.addView(ll) it's already there. All you need to do is get the references as you already do with findViewById.
Remove the sv.addView(ll); and you should be fine.

Categories

Resources