I've been trying to get Roboguice to work with fragments declared in a <fragment> block in the layout file and then injected into the activity, but, although the fragment exists somewhere off screen (an EditText in the fragment takes focus and fires events), It is not visible. Does RoboGuice support what I'm trying to do here or should I go about it a different way?
code:
<?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" >
<fragment
android:id="#+id/myFragment"
android:name="com.example.MyFragment"
android:layout_height="0dp"
android:layout_width="0dp"
android:layout_weight="1" >
<!-- Preview: layout=#layout/my_fragment -->
</fragment>
</LinearLayout>
Java:
#ContentView(R.layout.participant)
public final class Main extends RoboFragmentActivity {
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#InjectFragment(R.id.myFragment) private MyFragment myFragment;
}
Solved the issue, but for anyone else looking - The issue at hand was completely unrelated to RoboGuice, which allows fragment injection exactly as shown above. Rather the issue was that both of my layout dimensions for the fragment were set to 0dp, ensuring that my fragment would never be rendered.
Related
Consider this example:
There is a minimal activity in android which inflates this layout as root:
<!-- FILE activity_preference.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">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="#+id/settings_container"/>
</LinearLayout>
In the activity's onCreate:
setContentView(R.layout.activity_preference);
Then I want to replace settings_container with my PreferenceFragmentCompat.
I'm using the current androidx Jetpack library, this goes into the app's gradle file:
implementation 'androidx.preference:preference:1.1.0'
I've also created a custom PreferenceFragmentCompat for my needs, but it does not really do too much now:
public class MyPreferenceFragmentCompat extends PreferenceFragmentCompat {
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
// get the screen
PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(getContext());
// add item(s)
CheckBoxPreference item_Confirmation;
item_Confirmation = new CheckBoxPreference(this);
item_Confirmation.setKey("config_Confirmation");
item_Confirmation.setTitle("Confirmation");
item_Confirmation.setSummary("Confirmation");
item_Confirmation.setDefaultValue(false);
preferenceScreen.addPreference(item_Confirmation);
// set this screen as default
setPreferenceScreen(preferenceScreen);
}
Here is how activity transacts my fragment:
getSupportFragmentManager().beginTransaction().replace(R.id.settings_container, new MyPreferenceFragmentCompat()).commit();
However a wide margin gets inserted in front of the CheckboxItem:
How can I eliminate this margin or padding?
If you are using AndroidX, you can use Preference.setIconSpaceReserved(boolean iconSpaceReserved) method.
So, you will have:
item_Confirmation.setIconSpaceReserved(false);
You can also check this answer.
I have a project with Fragments and Activities. I want to try Navigation element, but I can't add Fragments on my graph - in the destination list, I have only Activities. Why does it happen?
Androidx, Java.
UPD: I can't find the correct tag for this navigation element, so only the Android tag present.
Gragle:
implementation 'android.arch.navigation:navigation-fragment:1.0.0'
implementation "android.arch.navigation:navigation-ui:1.0.0"
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.MainActivity">
<fragment
android:id="#+id/my_nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/main_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
The screen where I have no Fragments on the destination list:
And, I think it can be important, my preview of MainActivity:
I don't know why, but it gray.
UPD1: red mark on last screen is:
A <fragment> tag allows a layout file to dynamically include different layouts at runtime. At layout editing time the specific layout to be used is not known. You can choose which layout you would like previewed while editing the layout.
I think it's explain why my fragment grey on preview - layout is unknown on runtime. So, my problem is not connecting with it.
It's resolve itselfs when i create one fragment by hands on my navigation graph, and do "Invalidate/restart".
To resolve this issue you have to add tools:layout line to your fragment tag: tools:layout="#layout/fragment_sample_name"
It should looks like this in navigation graph code view
<fragment
android:id="#+id/sampleFragment"
android:name="com.example.sampleFragment"
android:label="#string/sample_name"
tools:layout="#layout/fragment_sample">
</fragment>
Be sure navigation tag have xmlns:tools="http://schemas.android.com/tools" added
<navigation 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/nav_sample_stackoverflow"
app:startDestination="#id/sampleFragment">
What I really want to do is add a preference screen to an existing layout with other items in it (such as a button) without using deprecated approaches. I have looked at the 'add button to preference screen' and I get that to semi-work using deprecated approaches.
I have two xml layouts. First the preference screen (at the moment the PreferenceCategory is superfluous) with 12 other CheckBoxPreferences omitted for clarity:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:key="#string/specialization_prefs"
android:title="#string/select_specializations">
<CheckBoxPreference
android:key="#string/pulse_ox_key"
android:title="#string/pulse_ox"
android:defaultValue="true" />
<CheckBoxPreference
android:key="#string/bp_key"
android:title="#string/bp"
android:defaultValue="true" />
</PreferenceCategory>
Then I have the activity layout (PreferenceActivity or Activity; does not seem to matter):
<?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/specializations_layout" >
<Button
android:id="#+id/btn_done"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="Exit and Save" />
<ListView android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>
The ListView was meant to be a dummy to be replaced with the PreferenceFragment which I got from a Stackoverflow suggestion. The Button I want to keep.
My PreferenceFragment is as follows:
public class SpecializationsFragment extends PreferenceFragment
{
#Override
public void onAttach(Activity specializationsActivity)
{
super.onAttach(specializationsActivity);
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.specializations);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
return super.onCreateView(inflater, container, savedInstanceState);
}
}
Finally my PreferenceActivity is as follows:
public class SpecializationsActivity extends PreferenceActivity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.specializations_layout);
getFragmentManager().beginTransaction()
.replace(android.R.id.list, new SpecializationsFragment())
.commit();
}
}
If I replace the 'android.R.id.list' with 'android.R.id.content' it sort of works. I see my button but my preference screen scrolls right over it. This is what I get when I follow the deprecated button solution. If I use the 'android.R.id.list' instead, the application crashes saying "addView(View) is not supported in AdapterView.
I have searched on that problem as well. What am I missing? This code currently does nothing but a GUI display. What do I need to add to get the button to display and the preference screen to scroll in the space below it as it is supposed to do in its own 'fragment'? I thought that was the whole idea behind fragments. (Yes they actually work quite well as long as preference screens are not present.) It also makes no difference using the 'add' method versus the 'replace' method.
For anyone who cares I found a solution. Not what I expected but it worked. First I needed to nest a layout within my layout. Then I needed to align this nested layout below the button. I also needed to have the dummy ListView in there but I do not know why. So the xml appears as follows:
<?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" >
<Button
android:id="#+id/btn_done"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="Exit and Save" />
<RelativeLayout
android:layout_below="#+id/btn_done"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/specializations_layout" >
<ListView android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>
</RelativeLayout>
The code now has the replace method (using 'add' or 'replace' made no difference) using the id added to the nested relative layout as follows:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.specializations_layout);
// Display the fragment as the main content.
getFragmentManager().beginTransaction()
.replace(R.id.specializations_layout, new SpecializationsFragment())
.commit();
findViewById(android.R.id.list).setBackgroundColor(Color.argb(0, 0, 0, 0));
}
I don't understand what is going on under the hood here, especially with the need for the dummy element and its android:id/list attribute. I would like to have seen it work without the ListView element as I believe would be the case if this was an ordinary fragment and not a preference screen. I would be grateful to anyone who can explain this to me!
I have 2 activities (lets call their layouts activity_one and activity_two). Both with seperate XML templates and seperate Activities.
in the onCreate(Bundle savedInstanceState) of one of them I am calling setContentView(R.layout.activity_one);
One of the subviews in this layout is a LinearLayout. I want to put the content of R.layout.activity_two within this LinearLayout and if possible use the code from its activity class (the onClickListeners etc).
The reason I want to do this is that the Tablet version of the app I am building should show data from both views.
Is this possible? How would I do this?
Thanks :).
You should use fragments for that, with fragments you will be able to have two separate layout files, two separate fragments - which will be quite similar to your current activities (its quite easy to convert activity to fragment), and also you will need additional activity that will include in itself those two fragments.
You can still have your current activities showing their layouts, just create FragmentActivity for each such activity, and show apropriate fragment.
Other solution might be with using layout include tag, that allows to include one layout into another.
btw. fragments were introduced to make it easier to build tablet versions (big screen) of application, while still being able to show UI version for phones (smaller screen).
// try this way here i just gave simple demo
**activity_one.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:gravity="center"
android:layout_height="match_parent">
<Button
android:id="#+id/btnActivityOne"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Activity One"/>
<include
android:layout_width="wrap_content"
android:layout_height="wrap_content"
layout="#layout/activity_two"/>
</LinearLayout>
**activity_two.xml**
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:id="#+id/btnActivityTwo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Activity Two"/>
</LinearLayout>
**MyActivity.java**
public class MyActivity extends Activity {
private Button btnActivityOne;
private Button btnActivityTwo;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_one);
btnActivityOne = (Button) findViewById(R.id.btnActivityOne);
btnActivityTwo = (Button) findViewById(R.id.btnActivityTwo);
btnActivityOne.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(MyActivity.this,"Activity One Button",Toast.LENGTH_SHORT).show();
}
});
btnActivityTwo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(MyActivity.this,"Activity Two Button",Toast.LENGTH_SHORT).show();
}
});
}
}
Simple work using actvities itself
For your first question
content of R.layout.activity_two within your LinearLayout
Use the <include ../> tag for that
Eg: <include layout="#layout/activity_two" /> within your LinearLayout
For your Second Question
if possible use the code from its activity class (the onClickListeners etc).
Make a class Extends Activity and add all the listeners you need in common and name the class as BaseActivity and extend BaseAcitivity instead of Activity for your 2 Activities.
I want to place a common banner and menu on each Activity with footer too.
Can anyone guide me how can I implement master and child page like asp.net in Android???
Any help would be appreciated.
You could have each of your Activities extend a common base class which has a onCreateOptionsMenu method which inflates the menu from the same XML each time. Though as you can't have multiple inheritance, this may be tricky when you want to have plain activities and list activities, for example.
Another way would be to have a Util class where you have a method like setupMenu(Menu) which each of your Activities can call if you're doing some more complex menu setup.
In terms of the XML UI layout for each of your Activities, you can include a common banner by using the <include/> tag.
The solution was pretty easy.
You need to extends "Activity" Class,in onCreate function SetContentView to your base xml layout and also need to override setContentView in base Activity Class
For Example:
1.Create "base_layout.xml" with the below code
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#000000"
android:padding="15dp" >
<LinearLayout android:orientation="horizontal" android:background="#000000"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:minHeight="50dp" android:paddingLeft="10dp">
<ImageView android:layout_width="wrap_content" android:id="#+id/ImageView01"
android:adjustViewBounds="true" android:layout_height="wrap_content"
android:scaleType="fitCenter" android:maxHeight="50dp" />
</LinearLayout>
<LinearLayout android:id="#+id/linBase"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</LinearLayout>
</LinearLayout>
2.Create "BaseActivity.java"
public class BaseActivity extends Activity {
ImageView image;
LinearLayout linBase;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.base_layout);
linBase = (LinearLayout)findViewById(R.id.linBase);
}
#Override
public void setContentView(int id) {
LayoutInflater inflater = (LayoutInflater)getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(id, linBase);
}
}
and
public class SomeActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.some_layout);
//rest of code
}
}
The only thing I noticed so far was that when requesting a progress bar (requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS)) this needs to be done before calling super.onCreate. I think this is because nothing can be drawn yet before calling this function.
This worked great for me and hopefully you will find this useful in your own coding.
I've had the same problem and solved it using ActivityGroup.
I suppose that menu items will move user to another activity, so with the same menu in every activity closing application with BACK button can be almost impossible (after some time user will have to go back through all activities he had ever seen).
I haven't found any good tutorials in english so have written mine some time ago (it's somewhat too short and in polish only, but Google Tranlslated version should be understandable) check this
You can also check how the TabHost works
ViewStub is the solution
activity_masterpage.xml
<LinearLayout 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" >
<ViewStub android:id="#+id/stub_content"
android:inflatedId="#+id/subTree"
android:layout_width="match_parent"
android:layout_height="match_parent" />
stub = (ViewStub) findViewById(R.id.stub_content);
stub.setLayoutResource(R.layout.content_layout);
stub.inflate();