I am very new to Android programming. Following is what I am doing:
I have an EditTextBox. And when it is in focus I would want to display a custom number pad. To implement this, following are the code snippets:
layout file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/activity_twopane"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout android:id="#+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3"/>
<FrameLayout android:id="#+id/keyPadFragmentContainer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
In the Fragment class, defined a Callbacks interface which the parent activity has to implement
public interface Callbacks {
void onAnswerEditTextSelected(Fragment fragment);
}
Added a listener to the EditText
mAnswerEditText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(!mNumberPadShown) {
mCallbacks.onAnswerEditTextSelected(QuizFragment.this);
}
});
In the Parent activity, I have the following:
#Override
public void onAnswerEditTextSelected(Fragment fragment) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Fragment numFragment = NumberPadFragment.newInstance(fragment);
ft.add(R.id.keyPadFragmentContainer, numFragment);
ft.commit();
}
At runtime I get No view found for id 0x7f ...(classname:id/keyPadFragmentContainer) for fragment NumberPadFragment. Can you please tell me where I am going wrong.
Thank you
if it's just numbers that you need, there is already a way to do it without any customization . it's called inputType.
it can be done either in XML or programmatically.
example :
<EditText android:inputType="number" android:digits="0123456789."
.../>
for more buttons, you can create a custom keyboard, as shown here:
http://www.fampennings.nl/maarten/android/09keyboard/index.htm
http://tutorials-android.blogspot.co.il/2011/06/create-your-own-custom-keyboard-for.html
https://stackoverflow.com/a/14676866/878126
i'm pretty sure the API demos have a sample for it too.
Related
I am trying to replace the fragment in Volley's onResponse(). It's getting replaced, but in a weird way.
The old frag is still visible while the new one isn't.
The old frag is non interactive & click events are being handled by
the new frag.
It's like the new frag is beneath the old frag.
If I try to replace the frag outside Volley's onResponse(), then everything works the way it should: the old frag goes away showing the new one.
getNetworkManager().jsonGETRequest(new NetworkManagerRequestData(getActivity(), this,
orderListUrl,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject jsonObject) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.main_frame, IdleFragment.newInstance());
transaction.commit();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
..
}
}, NetworkManager.getDefaultPolicyForNonTransactions(), false));
The fragments are being added dynamically using a FrameLayout. I have an activity with 5-6 frags. Everything is working beautifully with animations, except this transaction.
Here's the R.id.main_frame which is an empty FrameLayout.
<FrameLayout
android:id="#+id/main_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
..
/>
UPDATE
So I tried implementing the fragment transaction inside an AsyncTask
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.main_frame, IdleFragment.newInstance());
transaction.commit();
}
}.execute();
This has same behaviour. Normally transacting outside any async callbacks is working fine though.
Here is the layout of the frag i am trying to replace
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/pitch_grey"
android:clickable="true"
android:fillViewport="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
.....
</RelativeLayout>
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
The problem is the Swipe Refresh Layout. When you are trying to replace the fragment while its refreshing, then the previous fragment will freeze. This is an issue in the SwipeRefreshLayout itself.
You can wrap your swipeRefreshLayout inside FrameLayout. This might work.
<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">
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/pitch_grey"
android:clickable="true"
android:fillViewport="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
.....
</RelativeLayout>
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
</FrameLayout>
Ref: When switch fragment with SwipeRefreshLayout during refreshing, fragment freezes but actually still work
You cannot replace a fragment that is statically placed in an xml layout file. Is the idle fragment statically placed? You should create a container (e.g. a FrameLayout) in the layout and then add the fragment programatically using FragmentTransaction.
Also use an empty FrameLayout as fragment container. Avoid, using LinearLayout or RelativeLayout. I faced this problem once using LinearLayout and replaced LinearLayout with FrameLayout and it worked fine.
Another suggestion, avoid doing fragment transactions in asynchronous calls. It may cause IllegalState Exception. If you still want to do this, use commitAllowStateLoss instead of commit.
I've never used Fragments before but now I have a PlayerStatus fragment, that I want to use in two different activities. It shows player status:
public class PlayerStatus extends Fragment {
Player player;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.player_status, container, false);
return view;
}
public void setPlayer(Player player) {
this.player = player;
}
}
Fragment's layout looks like this:
<?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:layout_weight="1"
android:orientation="vertical"
android:paddingTop="0dp" >
<include
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
layout="#layout/money" />
<include
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
layout="#layout/wins" />
<include
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
layout="#layout/level" />
</LinearLayout>
I get it in the activity this way:
#Override
protected void onResume() {
super.onResume();
setContentView(R.layout.game);
fPlayerStatus = (PlayerStatus) getFragmentManager().findFragmentById(R.id.fPlayerStatus);
fPlayerStatus always returns null.
What am I doing wrong?
Read about how to start fragments ,attach/detach from activity , what does commit() do and there are few more basic functions which you should know when using fragments
http://developer.android.com/guide/components/fragments.html
Fragment Basics Tutorial
go through these web sites and you'll definately get through with fragments easily .
To make your fragments work here you have to do the following :
1.Add your fragment to your activity
write the following
FragmentManager fragmentManager = getFragmentManager()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.YOUR_FRAGMENT_ID_AS_DEFINED_IN_XML , object of your fragment class)
fragmentTransaction.commit();
____________END----------------------------------
There are many other useful methods in the APIs from FragmentTransaction , read them through the link above and you'll be abel to use them easily
Lemme know if it helped.
Your fragment has not been added to the FragmentManager in your Activity.
First do a FragmentTransaction with beginTransaction().add(...) on the getFragmentManager().
And don't forget to commit() it.
I don't Think you can use one Fragment for two Activities.
As i think your approach should be
Step 1
Create two fragment Layouts in your Activity_main
Step 2
then use fragment manager in your activity like below
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.frame,fragment)
fragmentTransaction.commit();
Basically this question has been asked many of times here and here.Solution given is not working for me. In some corrent answers were not posted by user.
I want to have nested fragments. My scenario is as below :
I have one MainActivity, ProductEnterFrag, and ProductListFrag,ProductDetailFrag.
I have add the ProductEnterFrag to MainActivity dynamically by the FragmentManager. Like this :
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.container, new ProductEnterFrag());
ft.commit();
ProductEnter layout is as below :
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
I have added the ProductListFrag to ProductEnterFrag like this :
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ProductListFrag(new ProductListFrag());
}
public void ProductListFrag(SherlockFragment frag) {
getChildFragmentManager().beginTransaction().add(R.id.fragContainer, frag).commit();
getChildFragmentManager().executePendingTransactions();`
}
ProductListFrag whose layout is, as below :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="product1" />
</LinearLayout>
Now on click of button, I want to add a another fragment say ProductDetailFrag,which should be another child fragment.
When I am trying to add ProductDetailFrag from ProductListFrag like this :
new ProductEnterFrag().ProductListFrag(new ProductDetailsFrag());
It is throwing me : java.lang.IllegalStateException: Activity has been destroyed
I am new in nested fragments. Please help me where I am doing wrong. I have stuck with this problem from last 2 days.
findViewById(R.id.team_detail_container) is failing to find the view. Is my problem with the xml or in the way I am constructing the FragmentActivity? How do I solve this?
To support a customised list for a fragment in the constructor of my fragment activity I have replaced
setContentView(R.layout.activity_team_list);
with
frag=(TeamListFragment)getSupportFragmentManager().findFragmentById(android.R.id.content);
if (frag==null) {
frag=new TeamListFragment();
getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag).commit();
So that my class now looks like this
public class TeamListActivity extends SherlockFragmentActivity implements
TeamListFragment.Callbacks {
private boolean mTwoPane;
private TeamListFragment frag=null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
frag=(TeamListFragment)getSupportFragmentManager().findFragmentById(android.R.id.content);
if (frag==null) {
frag=new TeamListFragment();
getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag).commit();
}
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
if (findViewById(R.id.team_detail_container) != null) {
Log.i("####", "Team Detail Container has been found! Yaay!");
mTwoPane = true;
((TeamListFragment) getSupportFragmentManager().findFragmentById(
R.id.team_list)).setActivateOnItemClick(true);
}
}
The if (findViewById(R.id.team_detail_container) != null) { condition is never met despite the fact that team_detail_container exists in the xml file that is used
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/team_list_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:orientation="horizontal"
android:showDividers="middle"
tools:context=".TeamListActivity" >
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/team_list"
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:paddingLeft="8dp"
android:paddingRight="8dp">
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:drawSelectorOnTop="false" />
<TextView android:id="#id/android:empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="No data"/>
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="?android:attr/listDivider"
/>
<FrameLayout
android:id="#+id/team_detail_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" />
</LinearLayout>
I know that this particular layout xml is being used as changes I make to the xml file are reflected in the app.
I also know that the condition is never met as I never get the log message Log.i("####", "Team Detail Container has been found! Yaay!"); and the behaviour get is that when an item is selected the list view is replaced with the detail fragments instead of the detail fragments being displayed next to the list view because the item selected conditions are not being met
#Override
public void onItemSelected(int id) {
if (mTwoPane) {
// mTwoPane is never set! Why?
Bundle arguments = new Bundle();
arguments.putInt(TeamDetailFragment.ARG_ITEM_ID, id);
TeamDetailFragment fragment = new TeamDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.team_detail_container, fragment).commit();
} else {
// In single-pane mode, simply start the detail activity
// for the selected item ID.
Intent detailIntent = new Intent(this, TeamDetailSwipeActivity.class);
detailIntent.putExtra(TeamDetailFragment.ARG_ITEM_ID, id);
startActivity(detailIntent);
}
}
The fragment doesn't get added to your layout tree immediately after committing the transaction. You'll have to wait till onViewCreated on the fragment was called. You could probably access the view within the onStart-Method of your Activity, but it would probably be a better idea to keep that logic within the fragment itself. The Activity shouldn't be concerned with what views are contained in a fragment.
I think the issue is you're looking for the Fragment from the Activity, but since you're not using setContentView, the Activity doesn't actually have a View to look through. Try getting the view from the Fragment instead using the getView() method.
I have a layout file containing a listview that I would like to fill with the help of a Fragment. But it continues to give me errors.
The layout file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ListView
android:id="#+id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true" >
</ListView>
<TableLayout
android:id="#+id/details"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:stretchColumns="1" >
<Button
android:id="#+id/create_patient_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/create_patient_button" />
</TableLayout>
</RelativeLayout>
My fragmentActivity:
public class BasicFragmentActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.create_patient_view);
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.list);
if (fragment == null) {
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.list, new BasicFragment());
ft.commit(); // Make sure you call commit or your Fragment will not be added.
// This is very common mistake when working with Fragments!
}
}
}
My ListFragment:
public class BasicFragment extends ListFragment {
private PatientAdapter pAdapter;
#Override
public void onActivityCreated(Bundle savedState) {
super.onActivityCreated(savedState);
pAdapter = new PatientAdapter(getActivity(), GFRApplication.dPatients);
setListAdapter(pAdapter);
}
}
The error:
java.lang.UnsupportedOperationException: addView(View) is not supported in AdapterView
findFragmentById(...) function takes ID of fragment(!) as parameter. But you call it with R.id.list which is ID of ListView (<ListView android:id="#+id/list" ...). It's wrong because ListView is NOT a fragment. It's the first problem.
The second problem is:
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.list, new BasicFragment());
in ft.add() function first parameter is ID of container in which you want to put your fragment. But you use R.id.list which is id of your ListView. It is wrong because ListView is not a container in which you can put fragments directly.
If you want put fragments into ListView items you can:
fill ListView with custom views.
declare <fragment ...> into custom view layout (XML). Or create fragment container in custom view layout (FrameLayout for example) and put there fragment at runtime (in getView() method).