Question

I have a custom EditText MomentumEditText that I have in a layout in xml (fragment_edit_text.xml):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.frazerm.momentum.MomentumEditText
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/writing_edittext"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>

I can successfully inflate and display the layout in a fragment, but trying to get the MomentumEditText using View.findViewById(R.id.writing_edittext) returns null.

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View root = inflater.inflate(R.layout.fragment_edit_text, container, true);
    MomentumEditText editText = (MomentumEditText) root.findViewById(R.id.writing_edittext);
}

I have also tried to get the MomentumEditText from onStart(), but it still returns null.

Edit = I tried replacing the custom EditText in the xml with a plain EditText, and findViewById() works! here is MomentumEditText:

package com.frazerm.momentum;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.widget.EditText;

public class MomentumEditText extends EditText  {

boolean moveCursorDisabled = true;
boolean deleteCharsDisabled = true;

private static Paint linePaint;
private static Paint marginPaint;
MomentumEditText thisEditText = this;

Editable currentText;

public MomentumEditText(Context context, AttributeSet attrs) {
    super(context);

    setCursorVisible(true);
    this.setGravity(Gravity.TOP);
    TextWatcher inputTextWatcher = new TextWatcher() {
        CharSequence textToAdd = "";
        boolean charWasDeleted = false;
        public void beforeTextChanged(CharSequence s, int start, int count, int after)  {
            if (moveCursorDisabled) {
                if( count > after ) {
                    textToAdd = s.subSequence(start + after, start + count);
                    charWasDeleted = true;
                }
            }
        }

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

        }

        @Override
        public void afterTextChanged(Editable s)    {
            if (moveCursorDisabled) {
                if (charWasDeleted == true) {
                    charWasDeleted = false;
                    s.append(textToAdd);
                }
                else    {
                    thisEditText.setSelection( thisEditText.getText().length() );
                }
            }
        }

    };
    this.addTextChangedListener(inputTextWatcher);

}

//disables ability to move the cursor to other parts of the text
@Override
public boolean onTouchEvent(MotionEvent event)
{
    if (deleteCharsDisabled)    {
        final float eventX = event.getX();
        if( getSelectionStart() != eventX )
        {
            super.onTouchEvent(event);
            thisEditText.setSelection( thisEditText.getText().length() );
            return true;
        }
        return super.onTouchEvent(event);
    }
    return super.onTouchEvent(event);
}

@Override
protected void onDraw(Canvas canvas) {
    linePaint = new Paint();
    linePaint.setColor(0x77777777);
    //linePaint.setStyle(Style.STROKE);

    marginPaint = new Paint();
    marginPaint.setColor(0x99FF4444);
    //marginPaint.setStyle(Style.STROKE);

    Rect bounds = new Rect();
    int firstLineY = getLineBounds(0, bounds);
    int lineHeight = getLineHeight();
    int totalLines = Math.max(getLineCount(), getHeight() / lineHeight);

    for (int i = 0; i < totalLines; i++) {
        int lineY = firstLineY + i * lineHeight + dip(2);
        canvas.drawLine(0, lineY, bounds.right, lineY, linePaint);
    }


    canvas.drawLine( (float) dip(64), (float) 0, (float) dip(64), getHeight(), marginPaint );

    super.onDraw(canvas);
    setPadding(dip(64), 0, 0, 0);
}

public void setCursorMoveAllowed(boolean allowed)   {
    moveCursorDisabled = !allowed;
    setCursorVisible(allowed);
    return;
}

public void setBackspaceAllowed(boolean allowed)    {
    deleteCharsDisabled = !allowed;
    return;
}

public boolean superTouchEvent(MotionEvent event)   {
    return super.onTouchEvent(event);
}

public int dip ( int dip )  {
    float d = this.getResources().getDisplayMetrics().density;
    int pixels = (int)(dip * d);        
    return pixels;

}

}
Was it helpful?

Solution

Because you are extending a current view you need to override all the constructors that can be used. Try:

public class MomentumEditText extends EditText  {

    public MomentumEditText(Context context) {
        super(context);
        init();
    }

    public MomentumEditText(Context context, AttributeSet attrs) {
        super(context, attrs); // This is the constructor used by XML (you were missing the super call)
        init();
    }

    public MomentumEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defstyle);
        init();
    }

    private void init(){
         setCursorVisible(true);
         // your other code
    }
}

Reference: http://developer.android.com/reference/android/widget/EditText.html (Public Constructors)

OTHER TIPS

Try setting attach to root false, since you are the root!

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

    MomentumEditText editText = (MomentumEditText) root.findViewById(R.id.writing_edittext);

    return root;
}

Try moving this line of code into your onActivityCreated method instead:

MomentumEditText editText = (MomentumEditText) findViewById(R.id.writing_edittext);

I'm guessing that fragment_edit_text.xml is the layout file you have shown in your question?

If yes, check if there is no other layout with the same name in some folders that specify some configurations (like language, density, etc).

For example you may have:

/layout/fragment_edit_text.xml

and

/layout-land/fragment_edit_text.xml

but only have your custom view within the layout-land directory, therefore it will compile ok but when in portrait mode your findViewById will return null

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top