Search code examples
javaandroidgridviewandroid-fragmentswordsearch

Creating a wordsearch android app. Using fragments to implement user interface


I am quite new to coding, especially Java, so if I miss anything fundamentally obvious, I apologise. Answering in layman's terms would be helpful.

I am trying to create a wordsearch app. A very simple version of the game, nothing fancy. I have made a gridview to house the images of letters and where work selections are to be made, this is the top fragment. The bottom fragment contains the letters being searched for.

This is the code for the top fragment containing the gridview. This works in a standalone app, with each letter being selectable and multiple selections being able to be made. However when trying to put it into a fragment i = new ImageView(TopWordsearchFragment.this); TopWordsearchFragment throws the error "ImageView(android.content.Context) in ImageView cannot be applied to (com.example.sebastian.multipleselectiongrid.TopWordSearchFragment"

This is my first problem

package com.example.sebastian.multipleselectiongrid;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Checkable;
import android.widget.FrameLayout;
import android.widget.GridView;
import android.widget.ImageView;

public class TopWordsearchFragment extends Fragment {

GridView mGrid;

TopSectionListener activityCommander;

public interface TopSectionListener{
    public void searchWordsearchWords();
}

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    try{
        activityCommander = (TopSectionListener)activity;
    }catch(ClassCastException e){
        throw new ClassCastException(activity.toString());
    }
}

@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.grid_1, container, false);


    mGrid = (GridView) view.findViewById(R.id.myGrid);
    mGrid.setAdapter(new ImageAdapter());
    mGrid.setChoiceMode(GridView.CHOICE_MODE_MULTIPLE_MODAL);
    mGrid.setMultiChoiceModeListener(new MultiChoiceModeListener());

    return view;
}

public class ImageAdapter extends BaseAdapter {

    public View getView(int position, View convertView, ViewGroup parent) {
        CheckableLayout l;
        ImageView i;

        if (convertView == null) {
            i = new ImageView(TopWordsearchFragment.this);
            i.setScaleType(ImageView.ScaleType.FIT_XY);
            i.setLayoutParams(new GridView.LayoutParams(85, 85));
            l = new CheckableLayout(TopWordsearchFragment.this);
            l.setLayoutParams(new GridView.LayoutParams(
                    GridView.LayoutParams.WRAP_CONTENT,
                    GridView.LayoutParams.WRAP_CONTENT));
            l.addView(i);
        } else {
            l = (CheckableLayout) convertView;
            i = (ImageView) l.getChildAt(0);
        }


        i.setImageResource(mThumbIds[position]);
        return l;
    }

    public final int getCount() {
        return mThumbIds.length;
    }

    public final Object getItem(int position) {
        return null;
    }

    public final long getItemId(int position) {
        return 0;
    }

    private Integer[] mThumbIds = {
            R.drawable.letter_j, R.drawable.letter_s, R.drawable.letter_o, R.drawable.letter_l, R.drawable.letter_u, R.drawable.letter_t, R.drawable.letter_i, R.drawable.letter_s,
            R.drawable.letter_s, R.drawable.letter_u, R.drawable.letter_n, R.drawable.letter_a, R.drawable.letter_r, R.drawable.letter_u, R.drawable.letter_u, R.drawable.letter_a,
            R.drawable.letter_n, R.drawable.letter_e, R.drawable.letter_p, R.drawable.letter_t, R.drawable.letter_u, R.drawable.letter_n, R.drawable.letter_e, R.drawable.letter_t,
            R.drawable.letter_s, R.drawable.letter_o, R.drawable.letter_n, R.drawable.letter_i, R.drawable.letter_e, R.drawable.letter_i, R.drawable.letter_s, R.drawable.letter_u,
            R.drawable.letter_r, R.drawable.letter_c, R.drawable.letter_e, R.drawable.letter_v, R.drawable.letter_t, R.drawable.letter_r, R.drawable.letter_e, R.drawable.letter_r,
            R.drawable.letter_a, R.drawable.letter_h, R.drawable.letter_t, R.drawable.letter_r, R.drawable.letter_a, R.drawable.letter_e, R.drawable.letter_s, R.drawable.letter_n,
            R.drawable.letter_m, R.drawable.letter_m, R.drawable.letter_e, R.drawable.letter_r, R.drawable.letter_c, R.drawable.letter_u, R.drawable.letter_r, R.drawable.letter_y
    };
}

public class CheckableLayout extends FrameLayout implements Checkable {
    private boolean mChecked;

    public CheckableLayout(Context context) {
        super(context);
    }

    @SuppressWarnings("deprecation")
    public void setChecked(boolean checked) {
        mChecked = checked;
        setBackgroundDrawable(checked ? getResources().getDrawable(
                R.drawable.blue) : null);
    }

    public boolean isChecked() {
        return mChecked;
    }

    public void toggle() {
        setChecked(!mChecked);
    }

}

public class MultiChoiceModeListener implements
        GridView.MultiChoiceModeListener {
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        return true;
    }

    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return true;
    }

    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        return true;
    }

    public void onDestroyActionMode(ActionMode mode) {
    }

    public void onItemCheckedStateChanged(ActionMode mode, int position,
                                          long id, boolean checked) {

    }

}



}

My second problem is the fragments will not appear. The BottomSectionFragment doesnt display any coding errors, and throws one error once I run it (Ill show below). This is after commenting out the above TopSectionFragment and removing that fragment from the activity_main.xml file.

This is the MainActivity.Java file

package com.example.sebastian.multipleselectiongrid;


import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
    }

}

Below is the BottomSectionFragment.Java file

package com.example.sebastian.multipleselectiongrid;


import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.app.Activity;

public class BottomSectionFragment extends Fragment {

   TextView word1;
   TextView word2;
   TextView word3;
   TextView word4;
   TextView word5;
   TextView word6;
   TextView word7;
   TextView word8;


    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.bottom_section_fragment, container, false);

        word1 = (TextView) view.findViewById(R.id.word1);
        word2 = (TextView) view.findViewById(R.id.word2);
        word3 = (TextView) view.findViewById(R.id.word3);
        word4 = (TextView) view.findViewById(R.id.word4);
        word5 = (TextView) view.findViewById(R.id.word5);
        word6 = (TextView) view.findViewById(R.id.word6);
        word7 = (TextView) view.findViewById(R.id.word7);
        word8 = (TextView) view.findViewById(R.id.word8);

        return view;

    }
}

When I run this code together, I receive the error FATAL EXCEPTION: main java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.sebastian.multipleselectiongrid/com.example.sebastian.multipleselectiongrid.MainActivity}: android.view.InflateException: Binary XML file line #8: Error inflating class fragment

and throws three causes: Caused by: android.view.InflateException: Binary XML file line #8: Error inflating class fragment

Caused by: android.app.Fragment$InstantiationException: Trying to instantiate a class com.example.sebastian.multipleselectiongrid.BottomSectionFragment that is not a Fragment

Caused by: java.lang.ClassCastException

and points to the line setContentView(R.layout.activity_main); in each three cases.

As I said, I am new to coding, and the answer might be glaringly obvious, or I am attacking this problem in the wrong way. So any helpful information or suggestions would be much appreciated.

EDIT: Thanks for the answers. I managed to fix problem 2. In my MainActivity class, if I extended ActionBarActivity rather than just Activity, it works fine. I checked the xml files and they are coded exactly how @Kumiho suggested.

As for problem 1, I couldn't solve the problem of using this particular code within a fragment, so instead I have left it in the MainActivity (With appropriate edits). And the two are working together as I hoped. Now to implement functionality.

Again, thanks a lot.


Solution

    1. You are trying to put a Fragment into an ImageView. This is not how it works. There are viewGroups and views. Views are just views which do not contain any other views while viewGroups are like containers which can contain other views or viewGroups. Fragment is so to say something between an activity and a viewGroup. what you need is the Context. You can get it by "asking" your fragment to give you the activity by calling getActivity().
    2. Is your Fragment declared in the layout file of your Activity? If not, you need a container for it and you need to add it programmaticaly by getting the fragmentManager of your Activity and putting the fragment to it:

      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.viewgroup_activity_layout);
      
          if (savedInstanceState == null) {
              getFragmentManager().beginTransaction()
                  .add(R.id.container_for_your_fragment, new MyFragment())
                  .commit();
          }
      

    container_for_your_fragment needs to be declared in viewgroup_activity_layout.xml and needs to be a viewgroup.

    The other way to make a fragment visible is to declare it in the layout of an activity:

    ...
    <fragment android:name="com.example.my.FragmentClass"
            android:id="@+id/fragment_id"            
            android:layout_width="match_parent"
            android:layout_height="match_parent" 
            ... (further parameters if needed)
    
    />
    ...
    

    Further informations you will find here.

    Good luck.