theTypan
theTypan

Reputation: 5887

Dynamically generating edittext in listview

In my fragment i want to display images selected from gallery and display them in a list view. Each list view item will consist of an ImageView for the image and an EditText for the caption. I am getting a nullpointerexception at caption.setText(mAllCaptions.get(position)) where I want to give a default caption such as Photo 1 from an ArrayList of captions named mAllCaptions. Any ideas

list_item_selected_image.xml

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/selected_imageImageView"/>

<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/selected_imageCaptionEditText"
    android:background="@color/white"
    android:hint="@string/add_caption"
    android:textColorHint="@color/input_hint"
    android:textColor="@color/dark_grey"
    android:layout_marginTop="5dp"
    android:layout_marginBottom="5dp"
    android:padding="10dp"/>

    </LinearLayout>

Inner class SelectedImagesAdapter

private class SelectedImagesAdapter extends ArrayAdapter<String>{


    public SelectedImagesAdapter(ArrayList<String> imagesArray){

        super(getActivity(),0,imagesArray);

        for (int i = 0; i < imagesArray.size(); i++) {

            int j = ++i;
            String defaultCaption  = "Photo " + j;
            mAllCaptions.add(defaultCaption);
        }
        notifyDataSetChanged();

    }//end constructor

    @Override
    public int getCount(){

        return mAllCaptions.size();
    }


    @Override
    public View getView(int position, View convertView, ViewGroup parent){

        //if we arent given a view inflate one
        //if there's no recycled view passed in inflate one

        if(convertView == null)
            convertView = getActivity()
                    .getLayoutInflater()
                    .inflate(R.layout.list_item_selected_image, null);

        //configure the view for this image
        String imagePath = getItem(position);
        Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
        //get the screen width  at run time
        int screenWidth = DeviceDimensionsHelper.getDisplayWidth(getActivity());
        //load resized bitmap into an ImageView

        ImageView imageView = (ImageView)convertView.findViewById(R.id.selected_imageImageView);

        imageView.setImageBitmap(BitmapScaler.scaleToFitWidth(bitmap, screenWidth));

        EditText caption  =  (EditText)convertView.findViewById(R.id.selected_imageCaptionEditText);

        caption.setText(mAllCaptions.get(position));
        caption.setId(position);

        //update adapter once we finish editing
        caption.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {

                if (!hasFocus){
                    final int position = v.getId();
                    final EditText Caption = (EditText) v;
                    mAllCaptions.set(position, Caption.getText().toString());

                }


            }
        });

        return convertView;//return view object to the list view

    }
}//end private class ImagesAdapter

Error Log

java.lang.NullPointerException
at com.photos.android.photos.PhotosFragment$SelectedImagesAdapter.getView(PhotosFragment.java: 278)
at android.widget.AbsListView.obtainView(AbsListView.java: 2259)
at android.widget.ListView.makeAndAddView(ListView.java: 1813)
at android.widget.ListView.fillDown(ListView.java: 688)
at android.widget.ListView.fillDown(ListView.java: 667)
at android.widget.ListView.fillFromTop(ListView.java: 759)
at android.widget.ListView.layoutChildren(ListView.java: 1666)
at android.widget.AbsListView.onLayout(AbsListView.java: 2110)
at android.view.View.layout(View.java: 13947)
at android.view.ViewGroup.layout(ViewGroup.java: 4472)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java: 1687)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java: 1545)
at android.widget.LinearLayout.onLayout(LinearLayout.java: 1450)
at android.view.View.layout(View.java: 13947)
at android.view.ViewGroup.layout(ViewGroup.java: 4472)
at android.support.v4.view.ViewPager.onLayout(ViewPager.java: 1627)
at android.view.View.layout(View.java: 13947)
at android.view.ViewGroup.layout(ViewGroup.java: 4472)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java: 1687)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java: 1545)
at android.widget.LinearLayout.onLayout(LinearLayout.java: 1450)
at android.view.View.layout(View.java: 13947)
at android.view.ViewGroup.layout(ViewGroup.java: 4472)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java: 1687)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java: 1545)
at android.widget.LinearLayout.onLayout(LinearLayout.java: 1450)
at android.view.View.layout(View.java: 13947)
at android.view.ViewGroup.layout(ViewGroup.java: 4472)
at android.widget.FrameLayout.onLayout(FrameLayout.java: 460)
at android.view.View.layout(View.java: 13947)
at android.view.ViewGroup.layout(ViewGroup.java: 4472)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java: 1687)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java: 1545)
at android.widget.LinearLayout.onLayout(LinearLayout.java: 1450)
at android.view.View.layout(View.java: 13947)
at android.view.ViewGroup.layout(ViewGroup.java: 4472)
at android.widget.FrameLayout.onLayout(FrameLayout.java: 460)
at android.view.View.layout(View.java: 13947)
at android.view.ViewGroup.layout(ViewGroup.java: 4472)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java: 1687)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java: 1545)
at android.widget.LinearLayout.onLayout(LinearLayout.java: 1450)
at android.view.View.layout(View.java: 13947)
at android.view.ViewGroup.layout(ViewGroup.java: 4472)
at android.widget.FrameLayout.onLayout(FrameLayout.java: 460)
at android.view.View.layout(View.java: 13947)
at android.view.ViewGroup.layout(ViewGroup.java: 4472)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java: 1883)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java: 1704)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java: 1011)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java: 4244)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java: 725)
at android.view.Choreographer.doCallbacks(Choreographer.java: 555)
at android.view.Choreographer.doFrame(Choreographer.java: 525)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java: 711)
at android.os.Handler.handleCallback(Handler.java: 615)
at android.os.Handler.dispatchMessage(Handler.java: 92)
at android.os.Looper.loop(Looper.java: 213)
at android.app.ActivityThread.main(ActivityThread.java: 4793)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java: 511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java: 789)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java: 556)
at dalvik.system.NativeStart.main(Native Method)

Upvotes: 0

Views: 60

Answers (1)

theTypan
theTypan

Reputation: 5887

The solution i had given earlier brought me some problems because edittext values were being interchanged on scrolling, i.e when the ListView redrwas itself, so here is the final solution with no bugs thanks to this link

 //custom adapter as inner class
private class SelectedImagesAdapter extends BaseAdapter{

    private LayoutInflater mInflater;
    int size = 0;

    public SelectedImagesAdapter() {
        mInflater = (LayoutInflater)getActivity()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        this.size = mPhotosPathList.size();

        int j = 1;
        for (int i = 0; i < size; i++) {

            String defaultCaption = "Photo " + j;
            etStrings.add(defaultCaption);
            j++;
        }


    }//end constructor

    @Override
    public int getCount() {


        return size;
    }

    @Override
    public Object getItem(int position) {
        return position;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }


    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {

        //if we arent given a view inflate one
        //if there's no recycled view passed in inflate one
        final ViewHolder holder;
        if (convertView == null) {

            holder = new ViewHolder();
            convertView = mInflater.inflate(R.layout.list_item_selected_image, null);
            holder.caption = (EditText)
                    convertView.findViewById(R.id.selected_imageCaptionEditText);

            holder.photo = (ImageView)
                    convertView.findViewById(R.id.selected_imageImageView);
            convertView.setTag(holder);

            holder.mWatcher = new EditTextWatcher();
            holder.caption.addTextChangedListener(holder.mWatcher);

        }else {

            holder = (ViewHolder)convertView.getTag();

        }

        holder.mWatcher.setActive(false);
        holder.caption.setText(etStrings.get(position));
        holder.mWatcher.setPosition(position);
        holder.mWatcher.setActive(true);

        Bitmap bitmap = BitmapFactory.decodeFile(mPhotosPathList.get(position));
        //get the screen width  at run time
        int screenWidth = DeviceDimensionsHelper.getDisplayWidth(getActivity());
        //load resized bitmap into an ImageView
        holder.photo.setImageBitmap(BitmapScaler.scaleToFitWidth(bitmap, screenWidth));


        return convertView;//return view object to the list view

    }
}//end private class ImagesAdapter

class ViewHolder {
    EditText caption;
    ImageView photo;
    public EditTextWatcher mWatcher;

}

class EditTextWatcher implements TextWatcher{


    private int mPosition;
    private boolean mActive;

    void setPosition(int position){
        mPosition = position;
    }
    void setActive(boolean active){
        mActive = active;
    }
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

    }

    @Override
    public void afterTextChanged(Editable s) {
        if(mActive){
            etStrings.set(mPosition, s.toString());

        }
    }
}

Upvotes: 1

Related Questions