I've created a simplified example of the problem i've encountered. What i want is add a button to my fragment view when clicking on another button in the fragmentview.
Java
MainActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImageView = (ImageView) findViewById(R.id.imageView);
}
public void addSubmitButton(View view){
RelativeLayout rLayout = (RelativeLayout) findViewById(R.id.activityLayout);
RelativeLayout.LayoutParams lparams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
Button tv1 = new Button(this);
tv1.setText("Hello");
tv1.setLayoutParams(lparams);
rLayout.addView(tv1);
}
XML ActivityMain
<fragment
android:id="#+id/fragment"
tools:layout="#layout/fragment_main" />
XML fragment_main
<RelativeLayout
android:id="#+id/activityLayout"
tools:context=".MainActivityFragment">
<Button
android:id="#+id/button"
android:onClick="addSubmitButton" />
</RelativeLayout>
In the codes above I've removed not relevant code (like width height etc)
When i click the button onclick fires addSubmitButton, then the app crashes on a nullpointer for the line rLayout.addView(tv1); in addSubmitButton.
why is it null?
I think, this is not the correct way.
First, add the proper definition in your fragment view declaration in your activity's layout
android:name="com.example.android.fragments.MainActivityFragment"
You'd have to use a Fragment Manager to find the fragment populated into your activity. Once you have this fragment, you can get its view, in your case the RelativeLayout and then add the desired Button to this view.
The following might help:
FragmentManager fm = getFragmentManager();
fm.findFragmentById(R.id.yourFragmentId).getView().findViewById(R.id.activityLayout)
If you are using the support fragment use the getSupportFragmentManager()
Looks like you are missing the fully qualified name in your fragment element:
<fragment android:name="com.example.android.fragments.MyFragment"
android:id="#+id/fragment"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
Related
I wanted to use a custom color and font and size for my app's name in the action bar, so I went in and stylized it in MainActivity.java like so
//stylize the action bar
TextView tv = new TextView(getApplicationContext());
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ActionBar.LayoutParams.WRAP_CONTENT, ActionBar.LayoutParams.WRAP_CONTENT);
tv.setLayoutParams(lp);
tv.setText(R.string.Title);
tv.setTextSize(45);
tv.setTextColor(Color.parseColor("#FFFFFF"));
Typeface tf = Typeface.createFromAsset(getAssets(), "KGALittleSwag.ttf");
tv.setTypeface(tf);
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
getSupportActionBar().setCustomView(tv);
updateOptionsMenu();
This did the trick, and then when I added another activity I copied this code into it, and it looked great. At this point my app is almost ready to release, but I'm doing some refactoring and I now have 6 or so activities, and it feels more than a little redundant to put this code in each of them. Is there a better practice for applying these changes to the action bar universally?
This is what inheritance is for.
Create an abstract BaseActivity Class, in which you'll fo all these processing. All your activities where you want to apply these styles will inherit for BaseActivity.
public abstract class BaseActivity extends AppCompatActivity {
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
//stylize the action bar
TextView tv = new TextView(getApplicationContext());
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams (ActionBar.LayoutParams.WRAP_CONTENT, ActionBar.LayoutParams.WRAP_CONTENT);
tv.setLayoutParams(lp);
tv.setText(R.string.Title);
tv.setTextSize(45);
tv.setTextColor(Color.parseColor("#FFFFFF"));
Typeface tf = Typeface.createFromAsset(getAssets(), "KGALittleSwag.ttf");
tv.setTypeface(tf);
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
getSupportActionBar().setCustomView(tv);
updateOptionsMenu();
}
}
Then your children activities:
public abstract class ChildActivity extends BaseActivity {
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate (savedInstanceState); // Here it calls the parent onCreate method and therefore executes the styling code
}
}
What you can do is just make a XML layout file for your custom action bar, and than use that in all activities.
<?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:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/actionBarTxt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_gravity="center"
android:gravity="center"
android:maxLines="1"
android:text="your text"
android:textAlignment="center"
android:textColor="#ffffff"
android:textSize="20dp"
android:textStyle="bold" />
</RelativeLayout>
make sure that your TextView is centered, and that layout_width and layout_hight for your TextView is set to wrap_content
Than put this into every activity that you want to use custom action bar
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
getSupportActionBar().setCustomView(R.layout.custom_action_bar);
I am trying to get a fragment to show that contains an EditText and a button. I am new to using fragments, so I am not sure exactly what the error message I get when trying to create the fragment means.
I have a class that extends Fragment, this is where the EditText and button are created.
public class EditNameFragment extends android.support.v4.app.Fragment {
EditText editText;
ImageButton button;
public EditNameFragment(){
}
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.edit_name_dialog, container, false);
editText = (EditText) view.findViewById(R.id.editTextDialog);
button = (ImageButton) view.findViewById(R.id.submitNewItemButtonDialog);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//stuff
}
});
return view;
}
Here is edit_name_dialog.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:id="#+id/edit_name_dialog"
>
<EditText
android:id="#+id/editTextDialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<ImageButton
android:id="#+id/submitNewItemButtonDialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
</LinearLayout>
And here in my main activity (which must extend FragmentActivity because of another part) is where I try to set up my Fragment. I think it has something to do with what id I am referencing. I have seen some people using container classes when using fragments, but I do not understand why this is done.
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
EditNameFragment fragment = new EditNameFragment();
fragmentTransaction.add(R.id.edit_name_dialog, fragment, "tag");
fragmentTransaction.commit();
I get the error message when trying to run the code above
No view found for id 0x7f09002a (com.myapp:id/edit_name_dialog) for fragment EditNameFragment
If anyone could explain what I am missing here/ why people use container classes, that would be great. I know some people add fragments using XML, but I would like to do this only using java.
EDIT
I have added a class that extends FragmentActivity, following the model for a container class
public class EditNameFragmentActivity extends FragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_name_fragment_container);
}
}
Is the parameter for setContentView supposed to be the layout, or an id?
Here is the xml file that defines where the fragment should be
edit_name_fragment_container.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
>
<fragment android:name="com.returnjump.spoilfoil.EditNameFragment"
android:id="#+id/edit_name_fragment_container"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="#layout/edit_name_fragment" />
</LinearLayout>
So for the parameter in
fragmentTransaction.add(R.id.edit_name_dialog, fragment, "tag");
this is supposed to reference the id of the fragment, correct?
It still gives me the same error, what am I missing?
There are basically two ways to add a fragment to an activity like the documentation say:
"statically": by declaring the fragment inside the activity's layout file.
"dynamically": adding the fragment programmatically. Like you tried to do.
Here is the documentation: http://developer.android.com/guide/components/fragments.html
If you wish to add it dynamically, here is the documentation part that you want to read:
At any time while your activity is running, you can add fragments to your activity layout. You simply need to specify a ViewGroup in which to place the fragment.
To make fragment transactions in your activity (such as add, remove, or replace a fragment), you must use APIs from FragmentTransaction. You can get an instance of FragmentTransaction from your Activity like this:
FragmentManager fragmentManager = getFragmentManager()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
You can then add a fragment using the add() method, specifying the fragment to add and the view in which to insert it. For example:
ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
The first argument passed to add() is the ViewGroup in which the fragment should be placed, specified by resource ID, and the second parameter is the fragment to add.
Once you've made your changes with FragmentTransaction, you must call commit() for the changes to take effect.
And about why to use dynamic fragments instead of static fragments, it has been made for interactive UI allowing you to simply handle different fragments into one activity as you please.
really in need of some advice, dont know what is wrong here.
Context:
2 fragments with a Textview each and the main activity has 2 button and a edittext
Aim:
Type hello into the edittext box in the main activity and
When click on the button for fragment 1, the textview will change to hello.
Problem:
Face a runtime error when enter hello into edittext and click on button 1.
Logcat:
E/AndroidRuntime(1291): FATAL EXCEPTION: main
E/AndroidRuntime(1291): android.view.InflateException: Binary XML file line #29: Error inflating class fragment
E/AndroidRuntime(1291): android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
E/AndroidRuntime(1291):android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
E/AndroidRuntime(1291):android.view.LayoutInflater.inflate(LayoutInflater.java:489)
E/AndroidRuntime(1291): android.view.LayoutInflater.inflate(LayoutInflater.java:396)
E/AndroidRuntime(1291): com.example.FragmentOne.onCreateView(FragmentOne.java:19)
E/AndroidRuntime(1291):android.app.FragmentManagerImpl.moveToState(FragmentManager.java:829)
fragment_one.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="#00ffff">
<TextView
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="This is fragment No.1"
android:textStyle="bold" />
</LinearLayout>
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<EditText
android:id="#+id/easy"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" >
<requestFocus />
</EditText>
<Button
android:id="#+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="selectFrag"
android:text="Fragment No 1" />
<Button
android:id="#+id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="selectFrag"
android:text="Fragment No 2" />
<fragment
android:name="com.example.FragmentTwo"
android:id="#+id/fragment_place"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
MainActivity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void selectFrag(View view) {
Fragment fr;
if(view == findViewById(R.id.button2)) {
fr = new FragmentTwo();
}else {
fr = new FragmentOne();
}
FragmentManager fm = getFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.fragment_place, fr);
fragmentTransaction.commit();
}
}
FragmentOne.java
public class FragmentOne extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater,ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.fragment_one, container, false);
TextView monthlypayment= (TextView) view.findViewById(R.id.textView1);
EditText easy = (EditText) inflater.inflate(R.layout.activity_main, container, false).findViewById(R.id.easy);
monthlypayment.setText(easy.getText().toString());
return view;
}
}
There are two ways you can add a fragment to the activity layout:
Declare the fragment inside the activity's layout file.
Programmatically add the fragment to an existing ViewGroup.
Both methods are mentioned in the docs
http://developer.android.com/guide/components/fragments.html
If you want add the fragment to a container you need to use a ViewGroup in xml. Generally FrameLayout is used. So have the below in xml
<FrameLayout
android:id="#+id/fragment_place"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
The Activity code is fine. On Button click you replace the appropriate fragment in the container.
In your Fragment onCreateView you inflate the fragment layout and use the view object to initialize views of that layout. But you inflate activity_main.xml which is not required.
Quoting docs
Specifically, the fragment can access the Activity instance with
getActivity() and easily perform tasks such as find a view in the
activity layout
So for EditText you can use
EditText easy = (EditText)getActivity().findViewById(R.id.easy);
Or Initialize EditText in Activity on Button click get the value from EditTextand then you can pass the value of EditText from Activity to Fragment
Send data from activity to fragment in android
show me the onclick method, and the container u have fragment one in... its one of two things,
either you are programmatically adding a view which already exists, or you are tryin to update the ui without a handler.... handlers can be worked around in fragments, so im assuming its the first one....
I need to put an ImageView under a TextView that was constructed using java. The textview is displaying information from a previous activity. Here is my code:
package com.example.a_simple_ui;
public class MainActivity2 extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent recieve = getIntent();
String message = recieve.getStringExtra(MainActivity.EXTRA_MESSAGE);
TextView textView = new TextView(this);
textView.setTextSize(40);
textView.setText(message);
setContentView(textView);
}
}
So now I need a picture under the textview above and to change the background color. Either by java or XML. Thank you.
You can use any approach from bellow two suggestion:
1) If your layout design is fixed than it is better to use xml based layout (static layout) rather than adding layout run-time.
For that first create xml layout main_Activity.xml like:
main_Activity.xml
<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" >
<TextView
android:id="#+id/tvDesc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
<Imageview
android:id="#+id/ivIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/ic_launcher" />
</LinearLayout>
MainActivity2 .java
package com.example.a_simple_ui; public class MainActivity2 extends
Activity {
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(textView); Intent recieve = getIntent();
String message = recieve.getStringExtra(MainActivity.EXTRA_MESSAGE);
TextView textView =(TextView)findViewById(R.id.tvDesc);
textView.setTextSize(40);
textView.setText(message); } }
2) You need to add TextView and Imageview in linearlayout then need to set that linearlayout in setContentView() like:
package com.example.a_simple_ui;
public class MainActivity2 extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent recieve = getIntent();
String message = recieve.getStringExtra(MainActivity.EXTRA_MESSAGE);
TextView textView = new TextView(this);
textView.setTextSize(40);
textView.setText(message);
ImageView imageView = new ImageView(this);
imageView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
imageView.setImageResource(R.drawable.ic_launcher);
LinearLayout layout = new LinearLayout(this);
layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
layout.setOrientation(LinearLayout.VERTICAL);
layout.addView(textview);
layout.addView(imageView);
setContentView(layout);
}
}
Ok, actually I can't understand, why you use TextView class as you content view. In that case, you can, offcourse, make you own textview extending default one and create particular layout with imageview for it, but, the easiest (and more logical) way is to create lauout file for your activity with TextView and ImageView.
For example, it can be something like that:
<?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" >
<ImageView
android:id="#+id/myImageView"
android:layout_width="wrap_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="#+id/myTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
And your activity onCreate method will be looks something like:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(textView);
Intent recieve = getIntent();
String message = recieve.getStringExtra(MainActivity.EXTRA_MESSAGE);
TextView textView = (TextView) findViewById(R.id.myTextView);
textView.setTextSize(40);
textView.setText(message);
ImageView imageView = (ImageView) findViewById(R.id.myImageView);
}
You need to call setContentView before finding views by id.
If you have to create texview dynamic, from java (I can't see any reason for it from your code) you can add id property to LinearLayout and than find it by id and add texview to that, and it will be placed after imageview.
p.s. Actually there are a lot of ways to do that, please, define your question more preciselly if my answer doesn't suits you
p.p.s. If you really have to create textView in runtime and you can't use xml layouts, you can create LinearLayout in runtime (LinearLayout layout = new LinearLayout(this) and after that, create textView and ImageView and add that two views to that layout, after that make set this layout as content view for the activity
I have been trying for a while, and searching around a lot to figure this out, but no luck.
My problem is, in a nutshell: I can't set the Typeface of my Button programmatically. I can get it just fine with findViewById, and then I create my Typeface, and set it, nothing breaks everything seems normal. Except the change never shows up in the program. Its still the default typeface.
Here's my code.
public class MainActivity extends FragmentActivity {
Button lcb;
Typeface resoLite;
private SplashFragment splashFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
// Add the fragment on initial activity setup
splashFragment = new SplashFragment();
getSupportFragmentManager()
.beginTransaction()
.add(android.R.id.content, splashFragment)
.commit();
} else {
// Or set the fragment from restored state info
splashFragment = (SplashFragment) getSupportFragmentManager()
.findFragmentById(android.R.id.content);
}
SpannableString s = new SpannableString("resocializer");
s.setSpan(new TypefaceSpan(this, "titillium-bold"), 0, s.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// Update the action bar title with the TypefaceSpan instance
ActionBar actionBar = getActionBar();
//actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE);
actionBar.setTitle(s);
//Here's the important stuff. I get the button fine. I create the typeface
//fine. I set the typeface fine. but none of this appears to have any effect
//in the actual program when it's running.
lcb = (Button) findViewById(R.id.lcb);
resoLite = Typeface.createFromAsset(getAssets(), "fonts/titillium-bold.otf");
lcb.setTypeface(resoLite);
}
And my activity_main xml:
<?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" >
<com.facebook.widget.LoginButton
android:id="#+id/authButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
/>
<Button
android:id="#+id/lcb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/lcbText"
android:layout_gravity="center_horizontal"
android:layout_marginTop="60dp"
android:background="#C4A649"
android:textColor="#FFFFFF"
android:onClick="logConversation"/>
</LinearLayout>
I have tested the setTypeface with Logs and Typeface.equals() to check if it is setting to what I expect it to and it appears to be so. It just never changes in the actual button on the screen. I feel like there is something obvious I am missing. Any ideas?
EDIT: To be clear, I am trying to set the typeface to a custom font in my assets/fonts/ folder in the project, so setting it in the xml file won't work.
First place your font in the folder assets/fonts/your_font.ttf
Now in your Activity/Fragment class add these lines of code :
Typeface myTypeface = Typeface.createFromAsset(getAssets(), "fonts/your_font.ttf");
Button custom_btn = (Button) findViewById(R.id.btn);
custom_btn.setTypeface(myTypeface);
custom_btn.setOnClickListener(this);