I have a problem with calling activity from fragment class. More:
XML of adapter's layout:
<TextView
style="#style/LiHeadLogin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
android:onClick="openProfile"
android:id="#+id/genFrom" />
Code from main activity that calls fragment:
public void openProfile(View v) {
Fragment_Questions frau = new Fragment_Questions();
frau.openProfile(v);
}
Code from fragment class:
public void openProfile(View v) {
View row = (View) v.getParent();
TextView child2 = (TextView) row.findViewById(R.id.genFromlogin);
String child3 = child2.getText().toString();
Intent ini = getActivity().getIntent();
String c_username = ini.getStringExtra(MainActivity.KEY_USERNAME);
String c_password = ini.getStringExtra(MainActivity.KEY_PASSWORD);
Intent ini2 = new Intent(context, User.class);
ini2.putExtra(MainActivity.KEY_USERNAME, c_username);
ini2.putExtra(MainActivity.KEY_PASSWORD, c_password);
ini2.putExtra(MainActivity.KEY_USER, child3);
getActivity().startActivity(ini2);
}
Errors:
java.lang.IllegalStateException: Could not execute method for android:onClick
...
...
...
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Intent android.support.v4.app.FragmentActivity.getIntent()' on a null object reference
P.S.
1. App opens default activity
2. User calls a new activity with passing intent data
3. New activity calls fragment
The first (main) activity:
Intent intent_settings = getIntent();
String c_username = intent_settings.getStringExtra(MainActivity.KEY_USERNAME);
String c_password = intent_settings.getStringExtra(MainActivity.KEY_PASSWORD);
Intent intent_settings_1 = new Intent(this, NewFeed.class);
intent_settings_1.putExtra(MainActivity.KEY_USERNAME, c_username);
intent_settings_1.putExtra(MainActivity.KEY_PASSWORD, c_password);
intent_settings_1.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(intent_settings_1);
Okay, and you should know that all fragments are called by viewpager with tab layout.
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
Fragment_Home tab1 = new Fragment_Home();
return tab1;
case 1:
Fragment_Questions tab2 = new Fragment_Questions();
return tab2;
default:
return null;
}
}
You can only access the activity with getActivity() between calls to onAttach() and onDetach().
Fragment_Questions itself only seems to serve the purpose to start a new activity, so you could just move all the logic to the click listener of the activity and don't use the fragment at all.
If there's more about the fragment and you're actually planning to add it to the activity sometime in the future it still seems better to have this logic separated from the fragment. You only use getActivity() and magically context in there. You could just make it static and give the activity as parameter instead.
public static void openProfile(Activity activity, View v) {
View row = (View) v.getParent();
TextView child2 = (TextView) row.findViewById(R.id.genFromlogin);
String child3 = child2.getText().toString();
Intent ini = activity.getIntent();
String c_username = ini.getStringExtra(MainActivity.KEY_USERNAME);
String c_password = ini.getStringExtra(MainActivity.KEY_PASSWORD);
Intent ini2 = new Intent(activity, User.class);
ini2.putExtra(MainActivity.KEY_USERNAME, c_username);
ini2.putExtra(MainActivity.KEY_PASSWORD, c_password);
ini2.putExtra(MainActivity.KEY_USER, child3);
activity.startActivity(ini2);
}
You should add Fragment_Questions to Activity.
For example,In Activity layout:
<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"
tools:context=".MainActivity" >
<fragment
android:id="#+id/fragment_question"
android:name="com.example.view.Fragment_Questions"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
In Acitivity.java:
questionFragment = (Fragment_Questions) findViewById(fragment_question);
and then, you can user OnClick Event like this:
questionFragment.openProfile(v);
You are getting Null Pointer Exception because your fragment is not attached to Activity. You are just instantiating the fragment and then calling its openProfile(View v) method which is a wrong way to handle events. If you already attached fragment then get the instance of framgent using
questionFragment = (Fragment_Questions) findViewById(fragment_question);
You can read below article on how to communicate from Fragments to activity
https://developer.android.com/training/basics/fragments/communicating.html
As I have understanded the steps of the user interferance you have to replace getIntent() in the fragment with the intent that starts it which is intent_settings i think
Also make the that intent static in order to share it
And make if statment in order not to have null exception
if(theIntent.hasPutextra)
{getExtra.....}
Do you extends Fragment OR FragmetnActivity?
if you extend FragmetnActivity (as i think) then dont use getActivity()
Also add the code for the intent that started your current activity
Fragment_Questions frau = new Fragment_Questions();
frau.openProfile(v);
You just created new fragment you didnt attached it to the activity?
use FragmentManager.
if you trying to use fragment inside ViewPager use THIS guide
Related
My question is about Android/Java.
I wanna access to other views from my custom view.
My main.xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/mainLinearLayout1">
<org.javaforum.input
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textEmailAddress"
required=""
android:hint="Enter your E-Mail"
oninvalid="this.setCustomValidity('SO - Please enter a correct E-Mail!!!')"/>
<org.javaforum.input
android:layout_width="wrap_content"
android:layout_height="wrap_content"
inputType="submit"/>
</LinearLayout>
So when the second "input" view is clicked, I wanna check if there exists an attribute named "required" at the first "input" view.
I tried this in my input.java:
public class input extends TextView{
public input(Context context, AttributeSet attr) {
super(context, attr, getIdentifier(context,attr));
}
#Override
public void onFinishInflate() {
setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
LinearLayout layout = (LinearLayout)findViewById(R.id.mainLinearLayout1);
View v = null;
for(int i=0; i<layout.getChildCount(); i++) {//Error
//Code
}
}
});
}
}
But I get the following error:
java.lang.NullPointerException: Attempt to invoke virtual method 'int android.widget.LinearLayout.getChildCount()' on a null object reference
I don't understand why it's null. It should be already created, right?
So how can I get an LinearLayout reference of my main.xml at my custom view correctly?
To solve the null pointer exception, you will need to search for the other widget in the parent LinearLayout. You can use View.getParent() to identify the parent. Since the view you are looking for is a sibling of the current view, you will find it in the parent.
As for determining if a certain attribute is set, I recommend that the value be captured by its view and a method provided to present that value upon request. Say the value is your "required" value then capture that value locally and provide a method, getRequiredValue(), for instance, to expose it.
You can use
LinearLayout layout = (LinearLayout) getRootView().findViewById(R.id.mainLinearLayout1);
if you only call findViewById inside custom view it only lookup the child view.
This should be called in the Activity's onCreate instead of TextView's onFinishInflate.
First give the submit button an id eg btn_submit, then in onCreate
Button btn_submit = (Button)findViewById(R.id.btn_submit);
btn_submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
LinearLayout layout = (LinearLayout)findViewById(R.id.mainLinearLayout1);
View v = null;
for(int i=0; i<layout.getChildCount(); i++) {
//Code
}
}
});
Am trying to use transitions in my App but am facing this problem,
Cannot cast Int to android.view.View
Below is my code:
holder.newsRoot.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent newsIntent = new Intent(NewsAdapter.this.c, NewsDetails.class);
newsIntent.putExtra("newstitle",NewsTitle);
newsIntent.putExtra("detailednews",DetailedNews);
newsIntent.putExtra("newsdate",NewsDate);
newsIntent.putExtra("newsphoto",NewsPhoto);
ActivityOptionsCompat options= ActivityOptionsCompat.makeSceneTransitionAnimation(this,(View)news_image,"image_transit");
c.startActivity(newsIntent,options.toBundle());
}
});
Am trying to integrate it in the Adapter class, but this is the line where the problem is :
`ActivityOptionsCompat options= ActivityOptionsCompat.makeSceneTransitionAnimation(this,(View)news_image,"image_transit")`;
** problem is found on these words**
(View)news_image
My xml code of the ImageView.
<ImageView
android:id="#+id/news_image"
android:layout_width="80dp"
android:transitionName="image_transit"
android:layout_height="80dp"
android:src="#drawable/bbb"/>
PROBLEM: in android, you store the id's of your objects as int, but the int is the view id, not the view itself.
SOLUTION: in order to work with it you need to get the view use findViewById.
ImageView yourImageView = (ImageView) findViewById(R.id.news_image);
In your case you can also use it directly in the problematic method:
ActivityOptionsCompat options=
ActivityOptionsCompat.makeSceneTransitionAnimation(this,
findViewById(R.id.news_image),
"image_transit")`;
Because you placed it in the xml layout:
<ImageView android:id="#+id/news_image"
I have read through some posts on here regarding activity-fragment communication but my problem is unique; i will try state it as clear as possible for you to understand. In my app there is a Mainactivity and 2 fragments(we call these fragment1 and fragment2) which are in sliding tab layout. The main activity contains a navigation drawer, and fragment1 contains a TextView and other fragment2 contains EditText. Heres problem now, there option on drawer called share:- when it is clicked, i want to access string value in Textview of Fragment1 or value in EditText of Fragment2; depends on which fragment is active in tablayout. now i want to pass string value to text message argument of intent in order for it to be shared with whatever client the user chooses.
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_share) {
//Inside the onNavigationItemSelected
String value = " ";
Fragment currentFragment= getActiveFragment();
if(currentFragment instanceof SpeechToText){
value = ((SpeechToText)currentFragment).getText1();
}else if(currentFragment instanceof TTS){
//This one has the edittext
value = ((TTS)currentFragment).getText2();
}
//Then create the intent
//Intent shareIntent ...
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT,value);
shareIntent.putExtra(Intent.EXTRA_SUBJECT, "Message");
startActivity(Intent.createChooser(shareIntent, "Share via"));
}
I have this function from the post you provided to return current active fragment in tab layout.
public Fragment getActiveFragment() {
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
return null;
} String tag = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1).getName();
return getSupportFragmentManager().findFragmentByTag(tag);
}
I have implementation for methodForGettingTextViewValue() in SpeechToText fragment which is Fragment1:
public String getText1()
{
return resultTEXT.getText().toString();
}
I have implementation for methodForGettingEditTextValue() in TTS fragment which is Fragment2
public String getText2()
{
return return editText.getText().toString();
}
You need to keep track of the active fragment in your tab layout, then check the class of the fragment, and depending on which one it is, call the method that would return either the content of the TextView or that of the EditText.
To keep track of the current fragment, check out this question.
Once you have that part sorted, inside the onNavigationItemSelected implementation, before you create the Intent you'd do something like this, assuming currentFragment is being updated, and that you've implement the needed methods in each of the two fragments:
//Inside the onNavigationItemSelected
String value = "";
if(currentFragment instanceof MyCustomFragment1){
value = ((MyCustomFragment1)currentFragment).methodForGettingTextViewValue();
}else if(currentFragment instanceof MyCustomFragment2){
//This one has the edittext
value = ((MyCustomFragment2)currentFragment).methodForGettingEditTextValue();
}
//Then create the intent
//Intent shareIntent ...
In case it's not clear enough, let me insist that you'd need to implement methodForGettingEditTextValue and methodForGettingTextViewValue. The method should access the view by id, get the value and return it.
I have a class like this
class Message implements Serializable
{
public String message, sender;
public Message (String msg, String from)
{
// check here that msg and from are not null. If so, use a default value or throw an NullPointerException
message = msg;
sender = from;
}
// Just a utility method for printing out the Message to System.out
public String toString () { return sender+":"+message; }
}
I am defining this variable in main activity
Hashtable<String, ArrayList<Message>> table = new Hashtable<String, ArrayList<Message>>();
table.get(room_name).add(new Message("Hi", "Sender"));
Bundle bundle = new Bundle();
bundle.putSerializable("messages", table.get(sendTo));
And in fragment I am getting this data with this code
ArrayList<Message> extractedMessages = (ArrayList<Message>)getArguments().getSerializable("messages");
System.out.println(extractedMessages.size());
But my app is crashing,I am getting java nullpointer exception for extractedMessages.size()
How can I fix this ?
Solution is ::
Bundle.putParcelable/Bundle.getParcelable
Have a look at this answer.
Use those methods, putParcelable and getParcelable.
Also you can ::
Intent intent = new Intent(context, SecondActity.class);
intent.putIntegerArrayListExtra("arraylist",myArrayList); //myArrayList is ArrayList<Integer>
startActivity(intent);
To get the arrayList in second Activity.
ArrayList arrayList<Integer> = getIntent().getIntegerArrayListExtra("myArrayList")
{Edit} ---- You can use newInstance to pass the data from fragment to fragment
This is one of the way to achieve it, i use constructor to pass the data
FragmentOne.java
int myData=12;
FragmentManager manager = getActivity().getSupportFragmentManager();
Fragment frgObj=FragmentTwo.newInstance(myData);
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.container, frgObj,"FragmentTwo");
ft.addToBackStack(null);
ft.commit();
FragmentTwo.java
int myData;
public static FragmentTwo newInstance(int _myData){
FragmentTwo fragment = new FragmentTwo();
myData=_myData
return fragment;
}
{EDIT-3}
I have made a project for you download it from Here
Mount in in your editor and run it .... it has bunch of other stuffs
.... don't bother about it
Check how i am starting a fragment from activity ----> then
onClick of button how i am starting a fragment ---> there pass
the data with the constructor as i shown in edit2
ALSO REFER -- this -- StackOVERFLOW POST
I have the following layout defined in useful_numbers_item_fragment.xml:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="#+id/call_linear_layout">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/useful_nums_item_name"/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/useful_nums_item_value"/>
</LinearLayout>
<ImageButton
android:layout_width="0dp"
android:layout_height="wrap_content"
android:src="#drawable/call"
android:id="#+id/call_btn"
android:onClick="callNumber"/>
</LinearLayout>
I dynamically populate the two text views in a class called UNItemListFragment.java
in the onCreate method:
public void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
if (getArguments().containsKey(Constants.UNItem.GROUP_ID)) {
simpleCursorAdapter = new SimpleCursorAdapter(getActivity(), R.layout.useful_numbers_item_fragment, null,
new String[]{Constants.UNItem.NAME, Constants.UNItem.VALUE},
new int[]{R.id.useful_nums_item_name, R.id.useful_nums_item_value}, 0);
setListAdapter(simpleCursorAdapter);
getLoaderManager().initLoader(0, getArguments(), this);
}
}
For each number if i click on the button i want to make a phone call by
calling the callNumber method when the user clicks the button:
public void callNumber(View view) {
Intent callIntent = new Intent(Intent.ACTION_CALL);
TextView unItemVal = (TextView) findViewById(R.id.useful_nums_item_value);
String phoneNumber = unItemVal.getText().toString();
callIntent.setData(Uri.parse("tel:" + phoneNumber));
startActivity(callIntent);
}
It is ok when I click the first button in the list, but when I click on the other buttons
it continues calling the number defined in the first row...
Any idea how to resolve this?
The problem is that this line:
TextView unItemVal = (TextView) findViewById(R.id.useful_nums_item_value);
is executed on the activity, so the findViewById will always return the first item with that id, which is likely the first item in the list.
The best way to fix this would be to override the adapter and add a tag containing the phone number to the view. A quick way to fix this would be to tag along in the view hierarchy, like so:
public void callNumber(View view) {
if( view != null ) { // view is the button tapped
View parent = view.getParent(); // this should be the LinearLayout
if( parent instanceof LinearLayout ) {
TextView unItemVal = (TextView) ((LinearLayout)parent).findViewById(R.id.useful_nums_item_value);
if( unItemVal != null ) {
Intent callIntent = new Intent(Intent.ACTION_CALL);
String phoneNumber = unItemVal.getText().toString();
callIntent.setData(Uri.parse("tel:" + phoneNumber));
startActivity(callIntent);
}
}
}
}
This would find the parent for the button that was clicked, and then find the text-view containing the number within that ViewGroup.
Using findViewById() will return the first view in the activity or fragment with the specified id. If this is a ListView, it will correspond to the first row.
There are many ways to work around this problem. The quickest one (but certainly not the prettiest one, since it depends on the layout) would be to use findViewById() relative to the LinearLayout that contains the list item. Assuming that view is the ImageButton, it would be somthing like:
((View)view.getParent()).findViewById(R.id.useful_nums_item_value)
A more elegant solution would be to set a tag in the adapter's getView(), containing the data you need (in this case, the phone number to call).