How to use a button in a fragment

0

I have a button in my fragment

fragment_main

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="@+id/fragMain"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_marginTop="16dp"
tools:context="makerapp.android.minhastarefas.MainActivity.ListItensFragment">



<!-- Exibe nome da lista atual -->
<LinearLayout
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:weightSum="1">

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="54dp">

        <Button
            style="?android:attr/buttonStyleSmall"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/stringVolta"
            android:id="@+id/anterior" />

    </RelativeLayout>

</LinearLayout>


<View
    android:layout_width="match_parent"
    android:layout_height="1dip"
    android:background="@color/md_grey_300"/>

<!-- Lista de itens -->
<makerapp.android.minhastarefas.ui.DynamicListView
    android:id="@+id/itens_listview"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1"
    android:divider="@color/md_grey_300"
    android:dividerHeight="1dp"
    android:choiceMode="singleChoice"
    android:headerDividersEnabled="true"/>

<!-- Layout a ser exibido quando a lista estiver vazia -->
<FrameLayout
    android:id="@android:id/empty"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:drawablePadding="16dp"
        android:drawableTop="@drawable/ic_empty_list"
        android:fontFamily="sans-serif-light"
        android:gravity="center"
        android:text="@string/empty_list_text"
        android:textAppearance="?android:textAppearanceMedium"
        android:textColor="@color/secondary_text_color"
        android:textSize="20dp"
        android:textStyle="italic" />

</FrameLayout>

<!-- Layout destinado a publicidade-->
<FrameLayout
    android:id="@+id/ad_framelayout"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content">
    <LinearLayout
        android:orientation="horizontal"
        android:id="@+id/ad_linear_layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    </LinearLayout>
</FrameLayout>

and wanting to access this button in the MainActivity class

MainActivity

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Button btAnterior = (Button)findViewById(R.id.anterior);

    btAnterior.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.e("TAG","ta aki");
        }
    });
}

This way you're giving this error.

java.lang.RuntimeException: Unable to start activity ComponentInfo{makerapp.android.minhastarefas/makerapp.android.minhastarefas.MainActivity}: java.lang.NullPointerException

How do I get the event to click this button in this class?

    
asked by anonymous 04.02.2015 / 20:29

3 answers

3

To notify Activity so that it has no more coupling, use the Observer / Listener pattern.

1. Create an interface that has all the events that can occur in Fragment and that depend on other class (es).

public interface FragmentListener {
    public void metodo(); // Metodo que sera chamado
}

2. Implement the interface in your Activity or any other class you want to use:

public SuaActivity extends Activity implements FragmentListener {
    @Override
    public void metodo() {
        // Implementação
    }
}

3. Create a property to save an object that implements this interface in its Fragment :

public class SeuFragment extends Fragment {
    private FragmentListener mListener;

    // Getters e Setters omitidos
}

4. Use the interface when the button is clicked:

btAnterior.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if(mListener != null) mListener.metodo();
    }
});

5. Pass the implementation of this interface to Fragment :

// Se a Activity implementar, voce pode usar o metodo onAttach do Fragment para setar
public void onAttach(Activity a) {
    super.onAttach(a);

    if(a instanceof FragmentListener) {
        mListener = (FragmentListener) a;
    }
}

// Ou com um setter
public void setFragmentListener(FragmentListener listener) {
    mListener = listener;
}

6. Release the interface instance when Fragment is destroyed, thus avoiding Memory Leak:

public void onDestroy() {
    super.onDestroy();
    mListener = null;
}

// ou
public void onDestroyView() {
    super.onDestroyView();
    mListener = null;
}

// ou quando for dettached
public void onDetach() {
    super.onDetach();
    mListener = null;
}
    
04.02.2015 / 20:56
0

you can expose btPrevious as follows. In its fragment you can write something of the genre:

private View view;
private TextView btAnterior;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    ...
    this.view = inflater.inflate(...);
    this.btAnterior = (Button)findViewById(R.id.anterior);
    ...
}

public TextView getBtAnterior() {
    return this.btAnterior;
}

In your MainActivity, you can access btPrevious as follows:

private SparseArray<Fragment> fragments = new SparseArray<Fragment>();
private ListItensFragment fragmentListItens;

@Override
public void onAttachFragment(Fragment fragment) {
    super.onAttachFragment(fragment);
    this.fragments.put(fragment.getId(), fragment);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    this.fragmentListItens = (ListItensFragment)this.fragments.get(R.id.fragmentListItens);
    this.fragmentListItens.getBtAnterior().setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.e("TAG","ta aki");
        }
    });
    ...
}
    
04.02.2015 / 21:00
0

Just to update if anyone else needs it. I solved this problem by doing so:

Within the Fragment class (before):

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_dom, container, false);
}

Within the Fragment class (After):

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_dom, container, false);
    listView = (ListView) view.findViewById(R.id.ID_ListView_test);
    // Inflate the layout for this fragment
    return view;
}

I get what is returned by default from the fragment class and set it to a "view" variable. And I use this variable to access the methods I would have in an activity class, such as findViewById. In the case of the Button, you do the same thing I did with the listview and then use the normal bt.setOnClickListner as if you were in an activity. I do not know if it's the right one, but that's what worked for me.

    
19.04.2018 / 22:53