I am working on an app which works well in landscape layout, but now I'm trying to get it to work in portrait layout as well. The problem is, setText does not update the text in the TextView which I am trying to display. The same fragment is called in landscape layout and works great.
MainActivity.java
//If landscape layout
if(mTwoPane) {
switch(index) {
case 0:
case 3:
Bundle arguments = new Bundle();
TextFragment tf = new TextFragment();
if (index == 0) {
arguments.putString("typ", "info");
} else {
arguments.putString("typ", "kontakt");
}
tf.setArguments(arguments);
ft = getFragmentManager().beginTransaction();
ft.replace(R.id.details, tf);
ft.commit();
break;
case 2:
..
..
}
//If portrait layout
else{
Context context = view.getContext();
switch(index) {
case 0:
case 3:
Intent intent = new Intent(context, TextActivity.class);
if(index == 0){
intent.putExtra("typ", "info");
}else{
intent.putExtra("typ", "kontakt");
}
context.startActivity(intent);
break;
default:
break;
}
}
TextActivity.java
public class TextActivity extends AppCompatActivity {
FragmentTransaction ft;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.portrait_details_layout);
if (savedInstanceState == null) {
Bundle arguments = new Bundle();
arguments.putString("typ", getIntent().getStringExtra("typ"));
TextFragment fragment = new TextFragment();
fragment.setArguments(arguments);
ft = getFragmentManager().beginTransaction();
ft.replace(R.id.detailss, fragment);
ft.commit();
}
}
}
TextFragment.java
public class TextFragment extends Fragment {
private static TextView textview;
private String typ;
private static final String TAG = TextFragment.class.getName();
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
if(getArguments().containsKey("typ")){
typ = getArguments().getString("typ");
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View view = inflater.inflate(R.layout.text_fragment, container, false);
textview = (TextView) view.findViewById(R.id.textView1);
setText();
Log.d(TAG, "typ = " + typ +"\ntextview.getText = " + textview.getText().toString());
return view;
}
private void setText(){
if(typ == "kontakt") {
textview.setText("Kontakt..");
}else if(typ == "info"){
textview.setText("Info..");
}
}
}
text_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textAppearance="?android:textAppearanceLarge"
android:autoLink="phone|email"/>
portrait_details_layout.xml
<?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:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
tools:context="com.example.app.MainActivity"
android:baselineAligned="false">
<FrameLayout
android:id="#+id/detailss"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/detailsElementBackground" />
</LinearLayout>
In MainActivity.java, if mTwoPane = true, I directly create an instance of the fragment (and display it to the right of a ListView I have), but if it's in portrait mode I want it to be displayed alone, without the ListView, so therefore I call an Activity which is linked to another layout (portrait_details_layout.xml).
In TextFragment.java I print out a message to Logcat in onCreateView. If I run the app and try to view the fragment in landscape mode, the message prints:
index == 0:
com.example.app.TextFragment: typ = info
textview.getText = Info..
index == 3:
com.example.app.TextFragment: typ = kontakt
textview.getText = Kontakt..
Which is exactly what I want. Now, if I do the same in portrait mode:
index == 0:
com.example.app.TextFragment: typ = info
textview.getText =
index == 3:
com.example.app.TextFragment: typ = kontakt
textview.getText =
It just shows a blank screen. However, if I hard code the text in text_fragment.xml, it shows that text, and textview.getText will also return that text.
What am I missing here?
I think the problem is the way you compare Strings in your custom setText() in TextFragment class. You should use .equals() method and not == operator.
For example here or here you can read more about it.
Related
EDIT 4 Alright, so I've changed my example code to exactly what was suggested, with a null check.
now in the public class MainActivity extends AppCompatActivity I've got
private templateFragment1 fragTest;
and then in onCreate I've got
final FragmentManager fragMan = getFragmentManager();
fragTest = (templateFragment1) fragMan.findFragmentByTag("1");
onSave.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
if(fragTest != null) {
String editTestText = fragTest.editTextGetter();
Toast.makeText(getApplicationContext(), editTestText, Toast.LENGTH_SHORT).show();
}
}
});
And in templateFragment1 I've got
privateEditText text;
which I've binded in onCreateView like this
text = (EditText) getActivity().findViewById(R.id.editTextTest);
then I have the method underneath onCreateView
public String editTextGetter(){
String value1 = text.getText().toString();
return value1;
}
And now what happens..is nothing. I hit the save button and there's no Toast, no error message. So I guess this means it's returning null?
EDIT 3 Here's a couple videos demonstrating the bug.
https://www.youtube.com/watch?v=w60Vljd2R4M&feature=youtu.be
https://www.youtube.com/watch?v=xqpVGBAHw0w&feature=youtu.be
I understand that there are several questions similar to this already, but none seem to address my specific issue here.
Inside my main activity I have a button that adds instances of fragments. Each time it does it also assigns them a tag of "1", "2", etc. Just to see if it's possible, I'm only trying to call a method from the first one.
In my main activity I have:
// initializing button that will call the fragment's method
Button onSave = (Button) findViewById(R.id.saveButton);
FragmentManager fragMan = getFragmentManager();
// calling my first created fragment
final templateFragment1 fragTest = (templateFragment1) fragMan.findFragmentByTag("1");
// my button that should call the frag's method and then display it as a toast
onSave.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
// here I'm assigning the fragment's method to a string
String editTestText = fragTest.editTextGetter();
// display as toast
Toast.makeText(getApplicationContext(), editTestText, Toast.LENGTH_SHORT).show();
}
});
In my fragment:
public String editTextGetter(){
EditText text = (EditText) getActivity().findViewById(R.id.editTextTest);
String value1 = text.getText().toString();
return value1;
}
editTextGetter() is below the onCreateView method if that matters.
Now what happens is just an app crash upon clicking the main activity's button.
EDIT: Here's my commit code as requested:
addDay.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
++fragIdCount;
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
String fragString = Integer.toString(fragIdCount);
templateFragment1 frag2 = new templateFragment1();
fragmentTransaction.add(R.id.templateFragmentLayout, frag2, fragString);
fragmentTransaction.commit();
}
});
As you can see, I'm incrementing a number from 0 (fragIdCount) and then converting it to a string. I then assign that as the tag of the fragment. So I'm trying to call my fragments with this assigned tag.
EDIT 2: OK guys, here's code that can copy+pasted into a new project. It replicates my issues, and I'd really appreciate if yall could take a look at it!
MainActivity.java
public class MainActivity extends AppCompatActivity {
int fragIdCount = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button addDay = (Button) findViewById(R.id.addDay);
Button removeDay = (Button) findViewById(R.id.removeDay);
// Here I'm making it so I have an instance of the fragment displayed on create
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
String fragString = Integer.toString(fragIdCount);
templateFragment1 frag2 = new templateFragment1();
fragmentTransaction.add(R.id.templateFragmentLayout, frag2, fragString);
fragmentTransaction.commit();
// My button that adds fragment. Obviously this can quickly generate a bunch of fragment instances
// I try to make that manageable by incrementing a fragment count to use as tags
addDay.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
++fragIdCount;
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
String fragString = Integer.toString(fragIdCount);
templateFragment1 frag2 = new templateFragment1();
fragmentTransaction.add(R.id.templateFragmentLayout, frag2, fragString);
fragmentTransaction.commit();
fragmentManager.executePendingTransactions();
}
});
// remove button. same concept as the add button
removeDay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v){
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
String fragString = Integer.toString(fragIdCount);
//Fragment f = getFragmentManager().findFragmentByTag(fragString);
if(fragIdCount != 0){
fragmentTransaction.remove(fragmentManager.findFragmentByTag(fragString)).commit();
--fragIdCount;
}
}
});
// initialize Save button (which SHOULD get the value of an editText from whichever
// fragment I specify)
Button onSave = (Button) findViewById(R.id.saveButton);
onSave.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
// Eventually I'll want to make this a for loop to perform this operation on all fragments created.
FragmentManager fragMan = getFragmentManager();
// this should get the fragment "1"
templateFragment1 fragTest = (templateFragment1) fragMan.findFragmentByTag("1");
// and this should run the method "editTextGetter()" inside of the previously specified fragment
String editTestText = fragTest.editTextGetter();
// just a quick way to show if I got the correct value, for debugging
Toast.makeText(getApplicationContext(), editTestText, Toast.LENGTH_SHORT).show();
}
});
}
}
activity_main.xml
<ScrollView
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"
>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.liftrpoc.scheduler1.pushpulldetails"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/templateFragmentLayout"
android:orientation="vertical">
</LinearLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/addDay"
android:text="Add Day"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/removeDay"
android:text="Remove Day"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/saveButton"
android:text="Save"
/>
</LinearLayout>
</ScrollView>
templateFragment1.java
public class templateFragment1 extends Fragment {
public templateFragment1() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
LinearLayout view = (LinearLayout) inflater.inflate(R.layout.fragment_template_fragment1, container, false);
// a good bit of extra code that adds it's own instanced fragments, just like in the main activity.
// this shouldn't have anything to do with what we're trying to do though. It doesn't touch anything else.
return view;
}
// here's the editText method I'm trying to access from my main activity.
public String editTextGetter(){
EditText text = (EditText) getActivity().findViewById(R.id.editTextTest);
String value1 = text.getText().toString();
return value1;
}
}
fragment_template_fragment1.xml
<?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="wrap_content"
android:background="#E3E3E3"
android:orientation="vertical"
android:id="#+id/ParentLinearLayout1"
>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/editTextTest"
/>
</LinearLay
Use an ArrayList and store each fragment you make in it.
then when you want to call an specific function in your fragment or get a view just get your desired fragment from the ArrayList and after that do your job.
Some areas of improvement to your code:
In your main activity, it's easier to just make fragTest a class property.
private templateFragment1 fragTest;
/** I believe these exists in your onCreate()? **/
// initializing button that will call the fragment's method
Button onSave = (Button) findViewById(R.id.saveButton);
FragmentManager fragMan = getFragmentManager();
// calling my first created fragment
fragTest = (templateFragment1) fragMan.findFragmentByTag("1");
if(fragTest == null) {
// Create fragTest
}
// my button that should call the frag's method and then display it as a toast
onSave.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
// Wrapping this with a null pointer check may be unnecessary
// but callbacks can be ... funny.
if(fragTest != null {
// here I'm assigning the fragment's method to a string
String editTestText = fragTest.editTextGetter();
// display as toast
Toast.makeText(getApplicationContext(), editTestText, Toast.LENGTH_SHORT).show();
}
}
});
/** End of onCreate **/
In your fragment, again, make text a class property and bind to it's view in onCreateView.
private EditText text;
// TODO In onCreateView, bind text to R.id.editTextTest
public String editTextGetter(){
String value1 = text.getText().toString();
return value1;
}
Other considerations
Orientation changes: you may want to add setRetainInstance(true) to the onCreate of you fragments. Full details here.
I tried to send a int value from current activity to the new one, here is the parts in current activity.
dialog.setPositiveButton("4 players", new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, "Start a new game!", Toast.LENGTH_SHORT).show();
// need send extra value to PlayerBoardActivity to decide how many buttons I should have
Intent intent = new Intent(MainActivity.this,
PlayBoardActivity.class);
intent.putExtra(PLAYER_NO, 4);
startActivity(intent);
}
});
dialog.setNegativeButton("2 players", new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, "Start a new game!", Toast.LENGTH_SHORT).show();
// need send extra value to PlayerBoardActivity to decide how many buttons I should have
Intent intent = new Intent(MainActivity.this,
PlayBoardActivity.class);
intent.putExtra(PLAYER_NO, 2);
startActivity(intent);
}
});
The problem is, I create 2 layout files for the new activity. When I press the negative button in the dialog for example, what I want is let the new activity (PlayerBoardActivity in my case) load the layout file corresponding to the value I have sent by "intent.putExtra(PLAYER_NO, 2); "
The code in the new activity is
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final String PLAYER_NO = "the number of players";
Bundle b = getIntent().getExtras();
int a = b.getInt(PLAYER_NO);
if (b != null) {
if (a == 2) {
setContentView(R.layout.two_player);
}
if(a == 4){
setContentView(R.layout.four_player);
}
}
}
I do want to know whether I can load different layout file in this way? Or is there any better solution for my problem.
Thank you all in advance.
If you use
intent.putExtra(PLAYER_NO, 2);
you should call following code to get values (without using "Bundle"):
getIntent().getIntExtra(PLAYER_NO, -1)
In your code, the problem is in your second activity to which you are calling.
You are trying to fetching the values from intent in incorrect way.
Try this in your second activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
int b = intent.getIntExtra(PLAYER_NO, 0);
if (b == 2) {
setContentView(R.layout.two_player);
}
if(b == 4){
setContentView(R.layout.four_player);
}
}
Ji Yang... it is fine..if both the layout content the same kind of structure and dealing with different resources of any layout in the same activity is not so difficult..
suppose layout two_player.xml is
<?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="wrap_content"
android:paddingTop="6dp"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:orientation="vertical">
<TextView
android:id="#+id/textview1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#777370"
android:textSize="16sp"
android:paddingLeft="5dp"
android:text="Dummy Text"
android:visibility="gone"
android:textStyle="bold"/>
</RelativeLayout>
and layout four_player.xml is something like that
<?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="wrap_content"
android:paddingTop="6dp"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:orientation="vertical">
<ImageView
android:id="#+id/iv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/order_content"
android:src="#drawable/order_next_sap"
android:layout_alignLeft="#+id/order_content"/>
<ImageView
android:id="#+id/iv2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/order_content"
android:src="#drawable/order_next_sap"
android:layout_alignLeft="#+id/order_content"/>
</RelativeLayout>
means ...both layout of different defination.. than its difficult to use resource of both layout in same activity and its not good too..
The better solution in this case is to create fragment of both layout
class TwoPlayerFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v=inflater.inflate(R.layout.two_player, container, false);
return v;
}
}
class FourPlayerFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v=inflater.inflate(R.layout.four_player, container, false);
return v;
}
}
and use the fragment according to the intent value pass from dialog..
try this,
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final String PLAYER_NO = "the number of players";
Intent b = getIntent();
int a = b.getExtras().getInt(PLAYER_NO);
if (b != null) {
if (a == 2) {
setContentView(R.layout.two_player);
}
if(a == 4){
setContentView(R.layout.four_player);
}
}
}
You are doing very wrong way. You should use fragment for this. You should create two fragment in which you can inflate different different layout. But this is your call.
From PlayBoardActivity you are sending data like :
intent.putExtra(PLAYER_NO, 4);
So in new activity you need to retreive like:
int b=getIntent.getIntExtra(PLAYER_NO,defaulValue);
you are trying to get value from bundle which is wrong.
I've been trying to change my textViews text in a fragmentActivity based on whether or not user has clicked the button in the first main activity. I have 2 xml files and 2 .java files and the code at the moment crashes when the app starts.
This is the button code
public void getNum(View view) {
buttonCheck = 1;
}
And this is the code from FragmentTab
public class FragmentTab extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_layout, container, false);
TextView tv = (TextView) v.findViewById(R.id.text);
tv.setText("nothing has been input yet");
if (FirstActivity.buttonCheck == 1){
tv = (TextView) v.findViewById(R.id.text);
tv.setText("value");}
FirstActivity.buttonCheck = 0;
return v;
}
The first error i get from my code from logcat is: "java.lang.NullPointerException
at com.ezentertainment.dietabialkowa.FragmentTab.onCreateView(FragmentTab.java:23)" and line 23 is tv.setText("nothing has been input yet");
any help at all is greatly appreciated, I have been fighting with this issue for quite some time now..
tl;dr how to change fragment value based upon input from mainActivity?
edit: here is the fragment_layout.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#eaecee">
<TextView
android:id="#+id/textResult"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="value"
android:textAppearance="?android:attr/textAppearanceMedium" />
Your textview id is
android:id="#+id/textResult"
So, that's why you're getting a null pointer exception.
Also, it's probably a good idea to do a null check when finding a view by ID, just in case something isn't instantiated yet, so it doesn't kill your app. Something like:
TextView tv = (TextView) v.findViewById(R.id.textResult);
if (tv != null){
tv.setText("nothing has been input yet");
} else {
// log something if you want.
}
How about using setArguement:
In Activity:
Bundle bundle = new Bundle();
bundle.putString("email", email);
FragmentA fragment = new FragmentA();
fragment.setArguments(bundle);
getSupportFragmentManager().beginTransaction().add(container, fragment, tag).addToBackStack(tag).commit(); //please input container and tag yourself
In FragmentA:
String email;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle arguments = getArguments();
if (arguments != null)
email = bundle.getString("email");
...
}
I'm new to Android development and I'm searching the best way to manage multiple webview at the same time.
My goal is to create a simple web browser with a small menu listing my opened "tab" and replace my content section inside my layout by the user's selection. I don't want to have visible tab like Chrome and the stock browser on a tablet.
What is the best way to manage multiple view, switch between them and keep their state ?
Should I use multiple fragment (each one containing a webview) and FragmentManager to replace the content ?
Manage manually a framelayout by removing and adding the selected webview ?
UPDATE:
I played with Fragment today and I made a quick test project.
Here some code:
My Layout:
<RelativeLayout 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" >
<FrameLayout android:id="#+id/fff"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</FrameLayout>
</RelativeLayout>
My Activity:
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
private WebFragment f1;
private WebFragment f2;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
f1 = new WebFragment();
f2 = new WebFragment();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fff, f1);
fragmentTransaction.commit();
f1.loadUrl("file:///android_asset/home.html");
f2.loadUrl("file:///android_asset/home.html");
}
private void switchFragment(int id) {
FragmentTransaction trx = getFragmentManager().beginTransaction();
if (id == 1) {
trx.replace(R.id.fff, f1);
} else if (id == 2) {
trx.replace(R.id.fff, f2);
}
trx.commit();
}
...
}
My Fragment:
<?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" >
<WebView android:id="#+id/ww"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
public class WebFragment extends Fragment {
private static final String TAG = "WebFragment";
private View v = null;
private WebView ww;
private String url = null;;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.d(TAG, "WebFragment onCreateView");
if (v == null) {
v = inflater.inflate(R.layout.test_layout, container, false);
this.ww = (WebView) v.findViewById(R.id.ww);
// WebView settings here...
this.ww.setWebViewClient(new WebViewClient());
if (this.url != null)
this.ww.loadUrl(url);
}
return v;
}
public void loadUrl(String url) {
this.url = url;
if (this.ww != null)
this.ww.loadUrl(url);
}
}
By using the menu of my activity, I can switch to one or the other fragments.
Obviously, I will need some kind of controller to manage the fragment and a "bridge" to populate the activity's events but it seems to be ok.
Is it ok to keep multiple fragments (each one contain a webview) like that in memory ?
I need to keep the webview and their content but the fragment is only use in this case as a container.
Still open to some comments or suggestions.
Thanks again for your help.
Is it possible to add views to a different layout than the one called in setContentView() in the OnCreate()?
Im trying to use Zylincs ViewPager (found at http://www.zylinc.com/blog-reader/items/viewpager-page-indicator.html) and I have that part setup and working great.
What this leaves me with is 4 layouts. 1 is main.xml, and the other three are main_pg0.xml, main_pg1.xml, and main_pg3.xml
The three pages are where the content of each "page" is where main.xml contains the page viewer.
In the onCreate im using setContentView(main.xml).
What im trying to do now is be able to add textViews programically to some of the pages.
What I have right now is:
LayoutInflater factory = getLayoutInflater();
View layout = factory.inflate(R.layout.main_pg0, null);
View linearLayout = layout.findViewById(R.id.linearLayout);
TextView valueTV = new TextView(this);
valueTV.setText("hallo hallo");
valueTV.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));
((LinearLayout) linearLayout).addView(valueTV);
This is as far as I've been able to get, which does not add the textview at all.
----EDIT----
Hoping to clarify a little more what im trying to do
Heres my code
Main.java
public class Main extends FragmentActivity implements PageInfoProvider {
public GlobalVars globalVars;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
globalVars = (GlobalVars) getApplicationContext();
MyPagerAdapter adapter = new MyPagerAdapter();
ViewPager myPager = (ViewPager) findViewById(R.id.viewpager);
myPager.setAdapter(adapter);
myPager.setCurrentItem(0);
ViewPagerIndicator indicator = (ViewPagerIndicator) findViewById(R.id.indicator);
myPager.setOnPageChangeListener(indicator);
indicator.init(0, adapter.getCount(), this);
Resources res = getResources();
Drawable prev = res.getDrawable(R.drawable.indicator_prev_arrow);
Drawable next = res.getDrawable(R.drawable.indicator_next_arrow);
indicator.setArrows(prev, next);
}
private class MyPagerAdapter extends PagerAdapter {
public int getCount() {
return 3;
}
public Object instantiateItem(View collection, int position) {
LayoutInflater inflater = (LayoutInflater) collection.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
int resId = 0;
switch (position) {
case 0:
resId = R.layout.main_pg0;
LoadVehicles();
break;
case 1:
resId = R.layout.main_pg1;
break;
case 2:
resId = R.layout.main_pg2;
break;
}
View view = inflater.inflate(resId, null);
((ViewPager) collection).addView(view, 0);
return view;
}
#Override
public void destroyItem(View arg0, int arg1, Object arg2) {
((ViewPager) arg0).removeView((View) arg2);
}
#Override
public void finishUpdate(View arg0) {
// TODO Auto-generated method stub
}
#Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == ((View) arg1);
}
#Override
public void restoreState(Parcelable arg0, ClassLoader arg1) {
// TODO Auto-generated method stub
}
#Override
public Parcelable saveState() {
// TODO Auto-generated method stub
return null;
}
#Override
public void startUpdate(View arg0) {
// TODO Auto-generated method stub
}
}
public String getTitle(int position) {
String title = "--Untitled--";
switch (position) {
case 0:
title = "Page 0";
break;
case 1:
title = "Page 1";
break;
case 2:
title = "Page 2";
break;
}
return title;
}
}
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.zylinc.view.ViewPagerIndicator
android:id="#+id/indicator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#EAEAEA"
android:paddingBottom="8dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingTop="8dp" />
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#ffeaeaea" >
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:layout_alignBottom="#+id/current"
android:background="#C5C5C5" />
<ImageView
android:id="#+id/current"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerInParent="true"
android:src="#drawable/indicator_current" />
</RelativeLayout>
<android.support.v4.view.ViewPager
android:id="#+android:id/viewpager"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
main_pg0.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:background="#FFFFFF"
android:orientation="vertical"
android:id="#+id/linearLayout" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:text="main_pg0.xml"
android:textColor="#0C0C0C"
android:textSize="18sp" />
</LinearLayout>
What im trying to do is add a text view programmatically to main_pg0.xml ONLY, while leaving the other 2 pages alone
You haven't explicitly mentioned whether you're feeding Fragments to the ViewPager, but since you're working from the Zylinc implementation, I'm going to assume you are. As a matter of fact, I'll just use the provided example code to show you the idea.
The key to understanding how to realise what you're after is to get that the pages in the ViewPager are self-contained units in the form of Fragments. They are reusable, have their own life cycle, and can handle their own layouts. Hence, if you want to make runtime modifications to the layout of the pages, you will want to do this inside the Fragment(s) that make up these pages.
The following method can be found in the example code's ItemFragment class. I've simply added the TextView from your own code snippet to it. For demonstration purposes, I did hide the ListView that used to fill up all the space in the date_fragment.xml layout file.
#Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.date_fragment, container, false);
View tv = v.findViewById(R.id.text);
((TextView)tv).setText(readableDateFormat.format(date));
// changes below
TextView valueTV = new TextView(getActivity());
valueTV.setText("hallo hallo");
valueTV.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
((ViewGroup)v).addView(valueTV);
return v;
}
That will give you the "hallo hallo" text (you're a Dutchie? ;)) directly underneath the date in the page:
By the way, you might want to consider switching to Jake's ViewPagerIndicator. Although I haven't closely looked at the one you're currently using, Jake's seems more flexible to me and cleaner to work with. Up to you of course.
Edit: Okay, so you're not actually using fragments in the ViewPager, but are rather feeding it the layouts. That's fine, although it'll probably become harder to manage when the pages get more complex. Anyways, key to changing the page's layouts at runtime is still to do it whenever you build/inflate it. When using fragments, that would be in the overridden method, as shown above. In your case, however, you'll need to do it directly in instantiateItem(...).
I didn't actually type this out in an IDE, so please mind and minor syntactical errors.
public Object instantiateItem(View collection, int position) {
LayoutInflater inflater = (LayoutInflater) collection.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = null;
switch (position) {
case 0:
view = inflater.inflate(R.layout.main_pg0, null);
TextView valueTV = new TextView(getActivity());
valueTV.setText("hallo hallo");
valueTV.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
((ViewGroup)view).addView(valueTV);
break;
case 1:
view = inflater.inflate(R.layout.main_pg1, null);
// or perhaps better for readability: build the layout in a different method, passing in the root
buildSecondPageLayout(view);
break;
case 2:
view = inflater.inflate(R.layout.main_pg2, null);
buildThirdPageLayout(view);
break;
}
return view;
}
You have to add view in main view which is inflated layout.So just add one line.
LayoutInflater factory = getLayoutInflater();
View layout = factory.inflate(R.layout.main_pg0, null);
View linearLayout = layout.findViewById(R.id.linearLayout);
TextView valueTV = new TextView(this);
valueTV.setText("hallo hallo");
valueTV.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));
((LinearLayout) linearLayout).addView(valueTV);
layout.addView(linearLayout);