Search code examples
javaandroidandroid-fragmentsmaster-detail

Android Master/Detail flow - manipulating Detail fragment Views in Activity


So I am new to Android development, and trying to wrap my head around the Master/Detail flow design. As such, I'm using the default classes Eclipse creates for you - so ScreenDetailActivity, ScreenDetailFragment, ScreenListActivity, and ScreenListFragment. One of my Detail fragments uses a layout that contains a series of checks and fields for entering data, and a button that is supposed to make the Activity class using the fragment pass that data to a calculator class, which then performs some basic calculations with the data. For example, found in the calculation_layout.xml file used by one of the Detail fragment in question:

<EditText android:id="@+id/edit_value"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:inputType="numberDecimal|numberSigned"
      android:hint="@string/background_value" />

<Button android:layout_width="wrap_content"
    android:layout_height="wrap_content" 
    android:text="@string/button_singleCalc"
    android:onClick="calculate" />

I think I have the the Button's calculate function working (i.e. the app doesn't crash when the calculate is empty or does trivial things); it's implemented in both ScreenListActivity and ScreenDetailActivity, since either could be using the fragment.

However, whenever I try to access the EditText objects in the Detail fragment, the app crashes. I'm trying something like this:

public void calculate(View view){
    //Retrieve all the information, and set the values in the Calculator
    EditText editText = (EditText) findViewById(R.id.edit_value);
    String number = editText.getText().toString();
    double angle = Double.parseDouble(number);

    Calculator.longCalc();
}

And inflating the layout in my ScreenDetailFragment like this, not unlike how the default method generated by Eclipse works (where mItem is basically an instance of a little class containing information on which fragment should be displazed):

public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // The returned view
        View rootView;
        // If mItem is non-null...
        if (mItem != null) {
            if (mItem.title == "Calculation") {
                // If the title is Calculation, use the calculation layout
                rootView = inflater.inflate(R.layout.calculation_layout, container, false);
            } else {
                // Otherwise, show the dummy content as text in a TextView
                rootView = inflater.inflate(R.layout.fragment_screen_detail, container, false);
                ((TextView) rootView.findViewById(R.id.screen_detail)).setText(mItem.title);
            }
        } else {
            rootView = inflater.inflate(R.layout.fragment_screen_detail, container, false);
        }

        return rootView;
    }

The result, as said earlier, is a crash.

I assume that what I am supposed to do is somehow access rootView from the Activity, but I don't really know how to do that safely and effectively.

Can someone give me some pointers here?

UPDATE:

I have tried implementing OnClickListener, setting it up as such when that particular layout is inflated:

((Button)rootView.findViewById(R.id.button_calc)).setOnClickListener(this);

and implementing the onClick(View) function as such:

public void onClick(View view) {
        //Retrieve all the information, and set the values in the Calculator
        view = (View) view.getParent();
        EditText editText = (EditText) layout.findViewById(R.id.edit_phiD);
        String number = editText.getText().toString();

        Calculator.angle = Double.parseDouble(number) * 2.0 * Math.PI/360.0;

        Calculator.longCalc();
    }

However, the error persists. It also persists if I recast the ViewParent to a LinearLayout, a ViewGroup, or if I use view straight as is comes. To be clear, I am trying to get at the parent layout of the button that was clicked, so that I can go back down into that layout's other child Views and access their states.


Solution

  • You don't need to go through your activity in order to achieve this. Remove the onclick line and add an id for the button in your layout:

    <Button android:id="@+id/calc_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" 
    android:text="@string/button_singleCalc" />
    

    Then, simply add an OnClickListener to your button within your Fragment. Something like that:

    private View mRootView;
    private  EditText mEditText;
    
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // If mItem is non-null...
        if (mItem != null) {
            if (mItem.title == "Calculation") {
                // If the title is Calculation, use the calculation layout
                mRootView = inflater.inflate(R.layout.calculation_layout, container, false);
                mEditText = (EditText) mRootView.findViewById(R.id.edit_phiD);    
                ((Button)mRootView.findViewById(R.id.calc_button)).setOnClickListener(this);         
            } else {
                // Otherwise, show the dummy content as text in a TextView
                mRootView = inflater.inflate(R.layout.fragment_screen_detail, container, false);
                ((TextView) mRootView .findViewById(R.id.screen_detail)).setText(mItem.title);
            }
        } else {
            mRootView = inflater.inflate(R.layout.fragment_screen_detail, container, false);
        }
    
        return mRootView;
    }
    

    (Your fragment needs to implement OnClickListener for this). Then you'll get a callback on your Fragment, and here's what you do there:

    public void onClick(View v){
        //Retrieve all the information, and set the values in the Calculator
        String number = mEditText.getText().toString();
        double angle = Double.parseDouble(number);
    
        Calculator.longCalc();
    }