karansky
karansky

Reputation: 558

How to handle navigation drawer's event in another activity?

I have a main activity with a lot of fragments. I have implemented the navigation drawer inside the main activity so that when I am viewing the fragments, I can open the navigation drawer as well. Inside the main_activity.xml layout file (refer below), I have used <include layout="@layout/navigation_drawer"/> to include the layout of the navigation drawer. Inside the navigation drawer, I have a lot of buttons and texts that redirect the user to different fragments.

Currently, I am handling all the onClick events of the navigation drawer inside the main activity. However, this makes my code inside the main activity very long and very hard to manage (in terms of readability and whether it is easy to edit). How to handle the onClick events in another class that specializes in handling the navigation drawer's event? What is the best way to achieve this?

main_activity.xml

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer"
    android:layout_height="match_parent"
    android:layout_width="match_parent">

    <!-- The main content view -->
    <FrameLayout
        android:id="@+id/fragmentContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!-- The navigation drawer -->
    <LinearLayout
        android:id="@+id/drawerContent"
          android:layout_width="250dp"
          android:layout_height="match_parent"
          android:layout_gravity="start"
          android:orientation="vertical">

        <include layout="@layout/navigation_drawer"/>

    </Linear Layout>

</android.support.v4.widget.DrawerLayout>

MainActivity class

public class MainActivity extends FragmentActivity implements View.OnClickListener, DrawerLayout.DrawerListener {

    Button button1;
    TextView text1;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.main_activity);

        button1 = (Button)findViewById(R.id.button1);
        text1 = (TextView)findViewById(R.id.text1);

        button1.setOnClickListener(this);
        text1.setOnClickListener(this);
    }

    public void onClick(View v){
        //I handle all onClick events of navigation drawer here.
        //I want to move all of these to another class. 
        //If possible, I would like to move the onClick method and declaration of Button and TextView variables too.
    }
}

Upvotes: 0

Views: 1262

Answers (2)

Gaetano Dati
Gaetano Dati

Reputation: 97

I suggest another operation: MVP architecture.

By using this kind of architecture you separate views from logics using a presenter.

The goal is to have more classes which contain small pieces of code so that's all unit testable and maintenable too.

Act this way:

  1. Create a Presenter Interface which contains a init() method and all the methods you need, passing all arguments (but not the views) inside the methods themselves
  2. Create a PresenterImplementation class which implements this interface
  3. Create an ActivityView Interface
  4. Implement this interface in your Activity so that when PresenterImplementation logic has been executed, in the same PresenterImplementation class you can call the view.

Here's a basic example, you can modify it to fit your needs.

MyActivityPresenter.java

public interface MyActivityPresenter {
void init();

/**
 * This method is for example only
 * @param intent You can pass whatever you want as argument, but don't pass views
 *               because It would be formally uncorrect
 */
void onTextViewClicked(Intent intent);

}

MyActivityPresenterImpl.java

public class MyActivityPresenterImpl implements MyActivityPresenter {

private Activity activity;
private MyActivityPresenterView view;

public MyActivityPresenterImpl(Activity activity, MyActivityPresenterView view) {
    this.activity = activity;
    this.view = view;
}

@Override
public void init() {
    //if(some condition or nothing at all){
        view.initViews();
    //}
}

@Override
public void onTextViewClicked(Intent intent) {
    //Do controls in Presenter Implementation
    if(intent != null){
        Fragment fragment = new SomeFragment();

        Bundle bundle = intent.getExtras();

        if(bundle != null){
            fragment.setArguments(bundle);
        }

        view.loadFragment(fragment);

    }
}

}

MyAppBaseView.java

public interface MyAppBaseView {
//Just created in order to be extended from every interface and to not rewrite everytime from scratch each method
void loadFragment(Fragment fragment);

}

MyActivityView.java

public interface MyActivityView extends MyAppBaseView {
void initViews();

}

MyActivity.java

public class MyActivity extends AppCompatActivity implements View.OnClickListener,MyActivityView {

private TextView textView;
private Intent intent;

private MyActivityPresenter presenter;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.something);
    presenter = new MyActivityPresenterImpl(this,this);
    presenter.init();

    this.intent = getIntent();

}

@Override
public void initViews() {
    textView = findViewById(R.id.text_view_title);
    textView.setOnClickListener(this);
}

@Override
public void loadFragment(Fragment fragment) {
    //Transaction
}

@Override
public void onClick(View v) {
    presenter.onTextViewClicked(intent);
}

}

This is only for example.

Forma mentis should be to separate logic from views. So that all gets more readable, testable and maintainable.

Hope it helps.

Upvotes: 0

Dharmesh Dhameliya
Dharmesh Dhameliya

Reputation: 174

Create a class which implement View.OnClickListener interface and pass newly created class object to widget setonclicklistner method public class MainActivity extends FragmentActivity implements View.OnClickListener, DrawerLayout.DrawerListener {

Button button1;
TextView text1;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main_activity);

    button1 = (Button)findViewById(R.id.button1);
    text1 = (TextView)findViewById(R.id.text1);

    button1.setOnClickListener(new ClickHander());
}}

public class ClickHander implements  View.OnClickListener
{
    @Override
    public void onClick(View v) {

    }
}

Upvotes: 1

Related Questions