Android Open Source - EditText-ErrorPopup-Scroll-View My Edit Text






From Project

Back to project page EditText-ErrorPopup-Scroll-View.

License

The source code is released under:

Apache License

If you think the Android project EditText-ErrorPopup-Scroll-View listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.catglo.errorpopupinascrollviewtest;
/*  w  w w . j av  a 2s .  c  o  m*/
import android.content.Context;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.PopupWindow;
import android.widget.ScrollView;
import android.widget.TextView;

public class MyEditText extends EditText {

  private CharSequence mError;
  private boolean mErrorWasChanged;
  private ErrorPopup mPopup;

  public MyEditText(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    // TODO Auto-generated constructor stub
  }
  
  public MyEditText(Context context, AttributeSet attrs) {
    super(context, attrs);
    // TODO Auto-generated constructor stub
  }
  
  public MyEditText(Context context) {
    super(context);
    // TODO Auto-generated constructor stub
  }

  @Override
  public void setError(CharSequence error){
      error = TextUtils.stringOrSpannedString(error);

        mError = error;
        
        if (error == null) {
            if (mPopup != null) {
                if (mPopup.isShowing()) {
                    mPopup.dismiss();
                }

                mPopup = null;
            }
        } else {
            if (isFocused()) {
                showError();
            }
        }
  }
  
  
   /**
     * Returns the Y offset to make the pointy top of the error point
     * at the middle of the error icon.
     */
    private int getErrorX() {
        /*
         * The "25" is the distance between the point and the right edge
         * of the background
         */
        final float scale = getResources().getDisplayMetrics().density;

        Drawable[] dr = getCompoundDrawables();
       // final Drawables dr = mDrawables;
        return getWidth() - mPopup.getWidth()
                - getPaddingRight()
               //   - (dr != null ? dr[0].mDrawableSizeRight : 0) / 2 + (int) (25 * scale + 0.5f);
                - (dr != null ? 50 : 0) / 2 + (int) (25 * scale + 0.5f);
    }

    /**
     * Returns the Y offset to make the pointy top of the error point
     * at the bottom of the error icon.
     */
    private int getErrorY() {
        /*
         * Compound, not extended, because the icon is not clipped
         * if the text height is smaller.
         */
        int vspace = getBottom() - getTop() -
                     getCompoundPaddingBottom() - getCompoundPaddingTop();

        Drawable[] dr = getCompoundDrawables();
      //  final Drawables dr = mDrawables;
        int icontop = getCompoundPaddingTop()
//                + (vspace - (dr != null ? dr.mDrawableHeightRight : 0)) / 2;
                  + (vspace - (dr != null ? 50 : 0)) / 2;

        /*
         * The "2" is the distance between the point and the top edge
         * of the background.
         */

        //return icontop + (dr != null ? dr.mDrawableHeightRight : 0)
        return icontop + (dr != null ? 50 : 0)     
                - getHeight() - 2;
    }
    
    
  private void showError() {
        
        if (mPopup == null) {
            LayoutInflater inflater = LayoutInflater.from(getContext());
            final TextView err = (TextView) new TextView(getContext());
            err.setBackgroundColor(Color.WHITE);
            
            
            final float scale = getResources().getDisplayMetrics().density;
            mPopup = new ErrorPopup(err, (int) (200 * scale + 0.5f),(int) (50 * scale + 0.5f));
            mPopup.setFocusable(false);
            // The user is entering text, so the input method is needed.  We
            // don't want the popup to be displayed on top of it.
            mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
        }

        TextView tv = (TextView) mPopup.getContentView();
        chooseSize(mPopup, mError, tv);
        tv.setText(mError);

        mPopup.showAsDropDown(this, getErrorX(), getErrorY());
        mPopup.fixDirection(mPopup.isAboveAnchor());
    }
  
   private void chooseSize(PopupWindow pop, CharSequence text, TextView tv) {
        int wid = tv.getPaddingLeft() + tv.getPaddingRight();
        int ht = tv.getPaddingTop() + tv.getPaddingBottom();

        /*
         * Figure out how big the text would be if we laid it out to the
         * full width of this view minus the border.
         */
        int cap = getWidth() - wid;
        if (cap < 0) {
            cap = 200; // We must not be measured yet -- setFrame() will fix it.
        }

        Layout l = new StaticLayout(text, tv.getPaint(), cap,
                                    Layout.Alignment.ALIGN_NORMAL, 1, 0, true);
        float max = 0;
        for (int i = 0; i < l.getLineCount(); i++) {
            max = Math.max(max, l.getLineWidth(i));
        }

        /*
         * Now set the popup size to be big enough for the text plus the border.
         */
        pop.setWidth(wid + (int) Math.ceil(max));
        pop.setHeight(ht + l.getHeight());
    }
  
  private void hideError() {
    // TODO Auto-generated method stub
    
  }
  
  
  @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();

        if (mError != null) {
            hideError();
        }
    }
  
  @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect);
        
        if (focused) {
            if (mError != null) {
                showError();
            }
        } else {
            if (mError != null) {
                hideError();
            }
        }
    }

  

  private static class ErrorPopup extends PopupWindow {
        private boolean mAbove = false;
        private final TextView mView;
        private ScrollView scrollView=null;
        
        ErrorPopup(TextView v, int width, int height) {
            super(v, width, height);
            mView = v;
            scrollView = searchForScrollView(v);
        }

        private ScrollView searchForScrollView(View v) {
      View parent = (View)v.getParent();
      if (parent==null) return null;
      if (parent instanceof ScrollView){
        return (ScrollView)parent;
      }
      return searchForScrollView(v);
    }

    void fixDirection(boolean above) {
            mAbove = above;

//            if (above) {
//                mView.setBackgroundResource(android.R.drawable.);
//            } else {
//                mView.setBackgroundResource(com.android.internal.R.drawable.popup_inline_error);
//            }
        }

        
        @Override
        public void update(int x, int y, int w, int h, boolean force) {
            if (scrollView != null){
              Rect scrollBounds = new Rect();
              scrollView.getHitRect(scrollBounds);
              if (mView.getLocalVisibleRect(scrollBounds)==false) {
                  return;
              }
            }
        super.update(x, y, w, h, force);

            boolean above = isAboveAnchor();
            if (above != mAbove) {
                fixDirection(above);
            }
        }
    }
}




Java Source Code List

com.catglo.errorpopupinascrollviewtest.MainActivity.java
com.catglo.errorpopupinascrollviewtest.MyEditText.java
com.catglo.errorpopupinascrollviewtest.NonFocusingScrollView.java