I am new to android. And I am trying to create an app where i have three imagebuttons on top in a horizontal line and fragment in below portion which can change with click of button (same like tinder android app). I have tried using two different fragments, one with three image buttons and other the below one). Then I also tried using gridview for images and then fragment in the below portion. I have also tried simply using images and dynamically changing fragments. I have got different errors resulting in crashes. What I want to know is how can I achieve my objective in most efficient way?
EDIT : Codes are following when I am using just images without gridview or fragments for imagebuttons.
package com.psycho.ayush.sahanubhooti_20;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.view.View;
import android.widget.ImageButton;
import android.widget.Toast;
public class MainActivity extends FragmentActivity {
ImageButton ngosButton, profileButtton, donateButton;
NGOsFragment ngosFragment;
ProfileFragment profileFragment;
DonateFragment donateFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ngosButton = (ImageButton)findViewById(R.id.ngoButton);
profileButtton = (ImageButton)findViewById(R.id.profileButton);
donateButton = (ImageButton)findViewById(R.id.donateButton);
ngosButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentTransaction fragTrans = getSupportFragmentManager().beginTransaction();
fragTrans.add(R.id.fragment_container, ngosFragment);
fragTrans.addToBackStack(null);
fragTrans.commit();
}
});
}
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:id="#+id/fragment_container"
tools:context="com.psycho.ayush.sahanubhooti_20.MainActivity">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/ngoButton"
android:src="#drawable/ngo"
android:background="#android:color/transparent" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/profileButton"
android:layout_gravity="center_horizontal|top"
android:src="#drawable/profile"
android:background="#android:color/transparent" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/donateButton"
android:layout_gravity="right|top"
android:src="#drawable/donate"
android:background="#android:color/transparent" />
</FrameLayout>
Rest I have three fragments(NGOsFragment, DonateFragment and ProfileFragment), which I have not changed. I have not added onclicklistener for rest of button in here.
07-25 21:18:09.111 23385-23407/com.psycho.ayush.sahanubhooti_20 I/OpenGLRenderer: Initialized EGL, version 1.4
07-25 21:18:09.111 23385-23407/com.psycho.ayush.sahanubhooti_20 W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
07-25 21:18:18.321 23385-23385/com.psycho.ayush.sahanubhooti_20 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.psycho.ayush.sahanubhooti_20, PID: 23385
java.lang.NullPointerException: Attempt to write to field 'android.support.v4.app.FragmentManagerImpl android.support.v4.app.Fragment.mFragmentManager' on a null object reference
at android.support.v4.app.BackStackRecord.doAddOp(BackStackRecord.java:418)
at android.support.v4.app.BackStackRecord.add(BackStackRecord.java:408)
at com.psycho.ayush.sahanubhooti_20.MainActivity$1.onClick(MainActivity.java:30)
at android.view.View.performClick(View.java:4756)
at android.view.View$PerformClick.run(View.java:19761)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5253)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
set on click listener on all the buttons and set the below code to set the different fragments on the frame layout. The frame layout id is the resource id of the frame layout you set in the activity and Fragment class is the fragment you created to be called on the click of the image buttons.
getSupportFragmentManager().beginTransaction().replace(R.id.frame layout id, Fragment class name).commit()
Related
I'm writing a simple Android App using AIDE (Android IDE). I gave one of my layout elements an ID, but when I try to access the element using findViewById(), I get an error tht says: "Unknown member 'id' of 'com.mycompany.mailscomunes.R'. I haven't seen this error outside of AIDE.
This is the Java code:
package com.mycompany.mailscomunes;
import android.app.*;
import android.os.*;
import android.content.Intent;
import android.provider.ContactsContract;
public class MainActivity extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
findViewById(R.id.one);
}
}
And this is the relevant XML:
<TextView
android:text="#string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/one"/>
Remove these lines:
import android.app.*;
import android.os.*;
You're literally importing the entire Android framework, which includes layout files, which has ID's in them.
And you're not including your own ID file (called "R.java").
So remove those two lines, and include this one:
import com.mycompany.mailscomunes.R;
The root of an activity xml should be of Layout type.
<?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">
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="Text"/>
</LinearLayout>
Goto your project and delete the build folder and do a rebuild. I had the same problem and is fixed
I am trying to develop a very simple Android app for rapid data collection, where an activity displays a fragment containing a form with a number of RadioGroup elements. I would like to have the user be able to quickly tap out the radio selections, then be able to swipe the form to the right to dispose of the fragment, record the data, and bring up another empty form.
What I can't figure out is how to set up the "swipe and replace" feature. I'm thinking of something similar to the ViewPager support class, except no scrolling backwards and an unlimited number of pages. What classes can I use to achieve this kind of behavior? Here's my stripped-down code:
fragment_record.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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/mainScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" >
<LinearLayout
android:id="#+id/mainLinearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Group 1"
android:id="#+id/textView" />
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="#+id/Group1">
<!-- Radio Buttons /-->
</RadioGroup>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Group 2"
android:id="#+id/textView2" />
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="#+id/Group2">
<!-- Radio Buttons /-->
</RadioGroup>
</LinearLayout>
</ScrollView>
RecordFragment.java:
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class RecordFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_record, container, false);
return view;
}
}
activity_record.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/fragment_container" >
</FrameLayout>
RecordActivity.java
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.View;
public class RecordActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_record);
if (findViewById(R.id.fragment_container) != null) {
if (savedInstanceState != null) return;
RecordFragment theFragment = new RecordFragment();
theFragment.setArguments(getIntent().getExtras());
getFragmentManager().beginTransaction().add(R.id.fragment_container, theFragment).commit();
}
}
}
Ok, the simple answer to this was delivered obiter dicta in the tech talk a month or two ago where Google showed the preview of Android Studio 2.0. One of the presenters said 'we see a lot of people out there using Fragments in places where they should be using ViewGroups.' I was one of those people too.
A wizard is a complex problem: you are usually building something incrementally, so there is state, dependencies, and flow. It's hard to make really generic because what is being built is completely different. Also, it's a clear anti pattern to partially construct the target object leaving a bunch of nullable fields to be filled in as the process grinds on.
If each group can contain a part, then you can assemble the parts and build the target from the parts. There's no shame in it if those parts are not necessarily organic domain objects: if you are modeling the process of obtaining a job, there can be an Application (the thing the user has to fill out) and the CV or Submission (what is built in the form to represent a specific request for consideration).
I am having problem with implementing barcodefragmentlibv2 into my project. As a name says and from previous experience I know that I can add it into fragment. However, I am still getting NullPointerException error when I am trying to get this fragment to work with my app.
This is a part of a code responsible for barcode fragment:
import android.support.v4.app.Fragment;
//...
public class CameraFragment extends Fragment implements IScanResultHandler {
BarcodeFragment fragment;
public static CameraFragment newInstance() {
CameraFragment fragment = new CameraFragment();
return fragment;
}
public CameraFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.include_qrfragment, container, false);
fragment = (BarcodeFragment)getActivity().getSupportFragmentManager().findFragmentById(R.id.sample);
fragment.setScanResultHandler(this);
return view;
}
//...
}
Error appears in line:
fragment.setScanResultHandler(this);
I've also tried replacing
getActivity().getSupportFragmentManager().findFragmentById(R.id.sample);
to
getFragmentManager().findFragmentById(R.id.sample);
but the result is this same.
Below are layout files:
fragment_camera
<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" tools:context=".CameraFragment">
<include
android:layout_width="match_parent"
android:layout_height="match_parent"
layout="#layout/include_qrfragment" />
<TextView
android:id="#+id/status_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:layout_margin="15dp"
android:background="#99FFFFFF"
android:gravity="center"
android:padding="10dp"
android:text="#string/msg_default_status"
android:textAppearance="?android:attr/textAppearanceMedium" />
<View
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
include_qrfragment
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/sample"
android:name="com.abhi.barcode.frag.libv2.BarcodeFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
At the beginning I've mentioned that from my own experience that this is possible. The truth is that I've built app utilizing this feature some time ago using eclipse and now I am using Android Studio - maybe there is a problem?
EDIT 1:
This is the whole error's stack trace:
06-22 23:05:56.804 30578-30578/myapp.com.test E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
at myapp.com.test.CameraFragment.onCreateView(CameraFragment.java:34)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1789)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:955)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1138)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:740)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1501)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:458)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3683)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)
The problem seems to lie in this line:
fragment = (BarcodeFragment)getActivity().getSupportFragmentManager().findFragmentById(R.id.sample);
Your fragment is not yet appended to the activity as getActivity() is null at this point.
Perhaps you should move that particular code to onActivityCreated
You should only inflate the layout at the CreateView, like this:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.your_layout, null);
}
The rest of your code, you should put it in the onActivityCreated as #waqaslam said.
You are getting a null pointer because there is no layout inflated yet.
I have read your responses, and now I am assuming you have tried or moved code of getActivity().getSupportFragmentManager().findFragmentById into onActivityCreated.
The only suspect I see without loading up your project is the GUI ID itself. You named it sample or R.id.sample, which is a suspect in some projects. It is possible that you have another UI element having the same name/ID. If so, that UI cannot be converted to a fragment. My suggestion is to change the name of the ID (with unique name), and use it with findFragmentById().
FIXED
I outsourced the Bluetooth scanning to a separate thread which was a failure. :D Having fixed this the code now works. Thanks for all support!
ORIGINAL QUESTION
I'm having troubles with exchanging dynamically added fragments (I use the support library and my minimal API version is 8 (Android 2.2)). In my XML which can be seen below file I have a FrameLayout which contains the fragment.
<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" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".BluetoothConnectionManager">
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/frmlFragmentContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"/>
<android.support.v7.widget.Toolbar
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/tbBottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:background="#color/hafnertec"
android:layout_alignParentBottom="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView android:id="#+id/lblMode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/lblMode"
android:layout_centerInParent="true"/>
<ImageButton android:id="#+id/btnRefresh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_action_refresh"
android:layout_alignParentRight="true"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_alignRight="#id/lblMode"
android:clickable="false"
android:longClickable="false"
android:onClick="updateData"/>
</RelativeLayout>
</android.support.v7.widget.Toolbar>
</RelativeLayout>
For exchanging the fragments i use a SupportFragmentManager. Furthermore, I also instantiate the two fragments in the onCreate() method. In addition, the fragment for discovering Bluetooth devices is added to the frame layout which works fine.
#Override
protected void onCreate(Bundle savedInstanceState)
{
...
// fetch a FragmentManager used for exchanging the fragments
this.fmFragmentExchanger = this.getSupportFragmentManager();
this.btDiscoveryFragment = new BluetoothDiscoveryFragment();
this.btConnectorFragment = new BluetoothConnectorFragment();
if (this.findViewById(R.id.frmlFragmentContainer) != null)
{
this.fmFragmentExchanger.beginTransaction().add(R.id.frmlFragmentContainer, this.btDiscoveryFragment).disallowAddToBackStack().commit();
}
...
}
Moreover, I've taken care that the fragments extend the Fragment class provided by the support library:
import android.support.v4.app.Fragment;
public class BluetoothDiscoveryFragment extends Fragment implements ...
{
// see: https://developer.android.com/training/basics/fragments/creating.html
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Nullable Bundle savedInstanceState)
{
return inflater.inflate(R.layout.fragment_connection_bluetooth_device, container, false);
}
Here is my code for exchanging the fragments:
this.fmFragmentExchanger.beginTransaction().replace(R.id.frmlFragmentContainer, this.btConnectorFragment).disallowAddToBackStack().commit();
The class for discovering Bluetooth devices makes use of a BroadcastReceiver which is "connected" with the activity. On stopping the discovery process or when it has finished I unregister this BroadcastReceiver.
However, on exchanging the fragments nothing happens and after some time I get an error caused by SIGABRT:
12-31 15:09:51.621 9790-9795/com.hafnertec.afdbluetooth I/dalvikvm﹕ Wrote stack traces to '/data/anr/traces.txt'
12-31 15:09:53.945 9790-9790/com.hafnertec.afdbluetooth A/libc﹕ Fatal signal 6 (SIGABRT) at 0x000001bd (code=0), thread 9790 (ec.afdbluetooth)
Here you can see the file /data/anr/traces.txt: trace file
I'm running the tests on a Samsung Galaxy S I9000 with Android 4.4.4 (CM SNAPSHOT M12). During the activity's onCreate() method I add the btDiscoveryFragment instance which works fine:
this.fmFragmentExchanger.beginTransaction().add(R.id.frmlFragmentContainer, this.btDiscoveryFragment).disallowAddToBackStack().commit();
Furthermore, adding the instance btConnectorFragment using .add() works. However, it logically causes the btConnectorFragment to be overlayed over the btDiscoveryFragment.
I think you have a typo, causing btDiscoveryFragment to be null:
this.fmFragmentExchanger = this.getSupportFragmentManager();
//add this line
this.btDiscoveryFragment = new BluetoothDiscoveryFragment();
//remove this duplicated line
//this.btConnectorFragment = new BluetoothConnectorFragment();
this.btConnectorFragment = new BluetoothConnectorFragment();
When I want to create a XML file in Android SDK installed ECLIPSE for the purpose of SharedPreferences Activity layout... I do not see that dialog box to appear where I can choose from.
Following are my files.
MainActivity.java
package com.preferences_activity;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button b1 = (Button) findViewById(R.id.button1);
b1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
}
});
}
}
Preferences.java
package com.preferences_activity;
import android.os.Bundle;
import android.preference.PreferenceActivity;
public class Preferences extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
main_activity.xml
<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"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="16dp"
android:text="#string/button1" />
</RelativeLayout>
preferences_activity.xml
<?xml version="1.0" encoding="UTF-8"?>
In the preferences_activity.xml, this is what I get when I create a xml file.
But I wanted to choose a type called preferences while creating a xml file. preferences layout is one of the type of resource available in the dialog box. Others are like: Layout, Values, Menu, AppWidget Provider Searchable, Animation.
If I had a option to choose a preferences layout option while creating a xml file I would be getting the following code:
<?xml version="1.0" encoding="UTF-8"?>
<PreferencesScreen
xmlns:android="http://schemas.android.com/apk/res/android">
</PreferenceScreen>
My Question is again: Where can I get that dialog box from while creating xml file where I can choose the resource type?
I am sorry if this question sounds funny. But I am struggling with it for few days in a row.
Thank you all.
For future Visitors:
I was struggling because I was using eclipse app instead of the one that was under adt-bundle. If you use the app under the adt-bundle, that has a logo with {} and light green background than you will have an options to choose a layout or any sorts of resources while creating an xml file. Pls, one more thing to note, I was having hard time to find a wizard for creating a xml file ( I could do it manually with right clicking the project and other and choosing xml file).. but I m talking about the wizard on the menu bar, you should be able to see it if you use this app under adt-bundle instead of regular eclipse. My answer may not be that likable, but sharing for future android beginners.