/** {@inheritDoc} */
  @Override
  protected void onFinishInflate() {
    super.onFinishInflate();

    setDrawingCacheEnabled(true);
    setAlwaysDrawnWithCacheEnabled(true);

    mMinFieldHeight =
        mContext.getResources().getDimensionPixelSize(R.dimen.editor_min_line_item_height);
    mFields = (ViewGroup) findViewById(R.id.editors);
    mExpansionView = (ImageView) findViewById(R.id.expansion_view);
    mExpansionViewContainer = findViewById(R.id.expansion_view_container);
    mExpansionViewContainer.setOnClickListener(
        new OnClickListener() {
          @Override
          public void onClick(View v) {
            // Save focus
            final View focusedChild = getFocusedChild();
            final int focusedViewId = focusedChild == null ? -1 : focusedChild.getId();

            // Reconfigure GUI
            mHideOptional = !mHideOptional;
            onOptionalFieldVisibilityChange();
            rebuildValues();

            // Restore focus
            View newFocusView = findViewById(focusedViewId);
            if (newFocusView == null || newFocusView.getVisibility() == GONE) {
              // find first visible child
              newFocusView = TextFieldsEditorView.this;
            }
            newFocusView.requestFocus();
          }
        });
  }
  @Override
  public void setEnabled(boolean enabled) {
    super.setEnabled(enabled);

    if (mFieldEditTexts != null) {
      for (int index = 0; index < mFieldEditTexts.length; index++) {
        mFieldEditTexts[index].setEnabled(!isReadOnly() && enabled);
      }
    }
    mExpansionView.setEnabled(!isReadOnly() && enabled);
  }
  /** Restores the visibility of the child EditTexts, and mHideOptional. */
  @Override
  protected void onRestoreInstanceState(Parcelable state) {
    SavedState ss = (SavedState) state;
    super.onRestoreInstanceState(ss.getSuperState());

    mHideOptional = ss.mHideOptional;

    int numChildren = Math.min(mFieldEditTexts.length, ss.mVisibilities.length);
    for (int i = 0; i < numChildren; i++) {
      mFieldEditTexts[i].setVisibility(ss.mVisibilities[i]);
    }
  }
  /** {@inheritDoc} */
  @Override
  protected void onFinishInflate() {
    super.onFinishInflate();

    setDrawingCacheEnabled(true);
    setAlwaysDrawnWithCacheEnabled(true);

    mMinFieldHeight =
        mContext.getResources().getDimensionPixelSize(R.dimen.editor_min_line_item_height);
    mFields = (ViewGroup) findViewById(R.id.editors);
    mExpansionView = (ImageView) findViewById(R.id.expansion_view);
    mExpansionViewContainer = findViewById(R.id.expansion_view_container);
    mExpansionViewContainer.setOnClickListener(
        new OnClickListener() {
          @Override
          public void onClick(View v) {
            // Save focus
            final View focusedChild = getFocusedChild();
            final int focusedViewId = focusedChild == null ? -1 : focusedChild.getId();
            // GPBYY-50 add(start)
            InputMethodManager imm =
                (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
            if (imm != null && v != null) {
              imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
            }
            // GPBYY-50 add(end)
            // Reconfigure GUI
            mHideOptional = !mHideOptional;
            onOptionalFieldVisibilityChange();
            rebuildValues();

            // Restore focus
            View newFocusView = findViewById(focusedViewId);
            if (newFocusView == null || newFocusView.getVisibility() == GONE) {
              // find first visible child
              newFocusView = TextFieldsEditorView.this;
            }
            newFocusView.requestFocus();
          }
        });
  }
  /** Restores the visibility of the child EditTexts, and mHideOptional. */
  @Override
  protected void onRestoreInstanceState(Parcelable state) {
    SavedState ss = (SavedState) state;
    super.onRestoreInstanceState(ss.getSuperState());

    mHideOptional = ss.mHideOptional;

    /** M: New Feature @{ */
    /* Original Code
    int numChildren = Math.min(mFieldEditTexts.length, ss.mVisibilities.length);
    for (int i = 0; i < numChildren; i++) {
        mFieldEditTexts[i].setVisibility(ss.mVisibilities[i]);
    }
    */
    if (null != mFieldEditTexts) {
      int numChildren = Math.min(mFieldEditTexts.length, ss.mVisibilities.length);
      for (int i = 0; i < numChildren; i++) {
        mFieldEditTexts[i].setVisibility(ss.mVisibilities[i]);
      }
    }
    /** @} */
  }
  @Override
  public void setValues(
      DataKind kind, ValuesDelta entry, EntityDelta state, boolean readOnly, ViewIdGenerator vig) {
    super.setValues(kind, entry, state, readOnly, vig);
    // Remove edit texts that we currently have
    if (mFieldEditTexts != null) {
      for (EditText fieldEditText : mFieldEditTexts) {
        mFields.removeView(fieldEditText);
      }
      mFieldEditTexts = null;
    }
    if (localGroupsSelectors != null) {
      for (View view : localGroupsSelectors) {
        mFields.removeView(view);
      }
      localGroupsSelectors = null;
    }
    boolean hidePossible = false;

    int fieldCount = kind.fieldList.size();
    if (LocalGroup.CONTENT_ITEM_TYPE.equals(kind.mimeType))
      localGroupsSelectors = new LocalGroupsSelector[fieldCount];
    else mFieldEditTexts = new EditText[fieldCount];
    for (int index = 0; index < fieldCount; index++) {
      final EditField field = kind.fieldList.get(index);
      if (LocalGroup.CONTENT_ITEM_TYPE.equals(kind.mimeType)) {
        final LocalGroupsSelector localGroupsSelector =
            new LocalGroupsSelector(mContext, entry, field.column);
        localGroupsSelector.setOnGroupSelectListener(
            new OnGroupSelectListener() {
              @Override
              public void onGroupChanged() {
                setDeleteButtonVisible(localGroupsSelector.getGroupId() > -1);
              }
            });
        // Show the delete button if we have a non-null value
        setDeleteButtonVisible(localGroupsSelector.getGroupId() > -1);
        localGroupsSelectors[index] = localGroupsSelector;
        mFields.addView(localGroupsSelector);
      } else {
        final EditText fieldView = new EditText(mContext);
        /*Begin: Modified by bxinchun for change the layout 2012/07/24*/
        /*Begin: Modified by xiepengfei for change the layout 2012/05/02*/
        LinearLayout.LayoutParams params =
            new LinearLayout.LayoutParams(
                LayoutParams.MATCH_PARENT,
                field.isMultiLine() ? LayoutParams.WRAP_CONTENT : mMinFieldHeight);
        params.bottomMargin = 10;
        fieldView.setLayoutParams(params);
        /*End: Modified by xiepengfei for change the layout 2012/05/02*/
        /*End: Modified by bxinchun for change the layout 2012/07/24*/

        // Set either a minimum line requirement or a minimum height (because {@link TextView}
        // only takes one or the other at a single time).
        if (field.minLines != 0) {
          fieldView.setMinLines(field.minLines);
        } else {
          fieldView.setMinHeight(mMinFieldHeight);
        }
        fieldView.setTextAppearance(getContext(), android.R.style.TextAppearance_Medium);
        fieldView.setGravity(Gravity.TOP);
        /*Begin: Modified by xiepengfei for change the layout 2012/05/02*/
        fieldView.setBackgroundResource(R.drawable.edit_editor_background);
        fieldView.setTextSize(20);
        fieldView.setTextColor(Color.BLACK);
        /*End: Modified by xiepengfei for change the layout 2012/05/02*/
        mFieldEditTexts[index] = fieldView;
        fieldView.setId(vig.getId(state, kind, entry, index));
        if (field.titleRes > 0) {
          fieldView.setHint(field.titleRes);
        }
        int inputType = field.inputType;
        fieldView.setInputType(inputType);
        if (inputType == InputType.TYPE_CLASS_PHONE) {
          PhoneNumberFormatter.setPhoneNumberFormattingTextWatcher(mContext, fieldView);
        }

        // Show the "next" button in IME to navigate between text fields
        // TODO: Still need to properly navigate to/from sections without text fields,
        // See Bug: 5713510
        fieldView.setImeOptions(EditorInfo.IME_ACTION_NEXT);

        // Read current value from state
        final String column = field.column;
        final String value = entry.getAsString(column);
        fieldView.setText(value);

        // Show the delete button if we have a non-null value
        setDeleteButtonVisible(value != null);

        // Prepare listener for writing changes
        fieldView.addTextChangedListener(
            new TextWatcher() {
              @Override
              public void afterTextChanged(Editable s) {
                // Trigger event for newly changed value
                onFieldChanged(column, s.toString());
              }

              @Override
              public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

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

        fieldView.setEnabled(isEnabled() && !readOnly);

        if (field.shortForm) {
          hidePossible = true;
          mHasShortAndLongForms = true;
          fieldView.setVisibility(mHideOptional ? View.VISIBLE : View.GONE);
        } else if (field.longForm) {
          hidePossible = true;
          mHasShortAndLongForms = true;
          fieldView.setVisibility(mHideOptional ? View.GONE : View.VISIBLE);
        } else {
          // Hide field when empty and optional value
          final boolean couldHide = (!ContactsUtils.isGraphic(value) && field.optional);
          final boolean willHide = (mHideOptional && couldHide);
          fieldView.setVisibility(willHide ? View.GONE : View.VISIBLE);
          hidePossible = hidePossible || couldHide;
        }

        mFields.addView(fieldView);
      }
    }

    // When hiding fields, place expandable
    setupExpansionView(hidePossible, mHideOptional);
    mExpansionView.setEnabled(!readOnly && isEnabled());
  }
  @Override
  public void setValues(
      DataKind kind,
      ValuesDelta entry,
      RawContactDelta state,
      boolean readOnly,
      ViewIdGenerator vig) {
    super.setValues(kind, entry, state, readOnly, vig);
    // Remove edit texts that we currently have
    if (mFieldEditTexts != null) {
      for (EditText fieldEditText : mFieldEditTexts) {
        mFields.removeView(fieldEditText);
      }
    }
    boolean hidePossible = false;

    int fieldCount = kind.fieldList.size();
    mFieldEditTexts = new EditText[fieldCount];
    for (int index = 0; index < fieldCount; index++) {
      final EditField field = kind.fieldList.get(index);
      final EditText fieldView = new EditText(mContext);
      fieldView.setLayoutParams(
          new LinearLayout.LayoutParams(
              LayoutParams.MATCH_PARENT,
              field.isMultiLine() ? LayoutParams.WRAP_CONTENT : mMinFieldHeight));
      // Set either a minimum line requirement or a minimum height (because {@link TextView}
      // only takes one or the other at a single time).
      if (field.minLines != 0) {
        fieldView.setMinLines(field.minLines);
      } else {
        fieldView.setMinHeight(mMinFieldHeight);
      }
      fieldView.setTextAppearance(getContext(), android.R.style.TextAppearance_Medium);
      fieldView.setGravity(Gravity.TOP);
      mFieldEditTexts[index] = fieldView;
      fieldView.setId(vig.getId(state, kind, entry, index));

      if (field.titleRes > 0) {
        fieldView.setHint(field.titleRes);
      }
      /** M:AAS @ { update fieldView's hint text */
      if (Phone.CONTENT_ITEM_TYPE.equals(kind.mimeType)) {
        int type = SimUtils.isAdditionalNumber(entry) ? 1 : 0;
        ExtensionManager.getInstance()
            .getContactDetailExtension()
            .updateView(
                fieldView,
                type,
                ContactDetailExtension.VIEW_UPDATE_HINT,
                ExtensionManager.COMMD_FOR_AAS);
      }
      /** M: @ } */

      /** M: New Feature xxx @{ */
      /* original code int inputType = field.inputType; */
      final int inputType = field.inputType;
      /** @} */
      fieldView.setInputType(inputType);
      if (inputType == InputType.TYPE_CLASS_PHONE) {
        /** M: New Feature xxx @{ */
        /*
         * original code
         * PhoneNumberFormatter.setPhoneNumberFormattingTextWatcher
         * (mContext, fieldView);
         */
        // add by mediatek
        ExtensionManager.getInstance()
            .getContactDetailExtension()
            .setViewKeyListener(fieldView, ContactPluginDefault.COMMD_FOR_OP01);
        PhoneNumberFormatter.setPhoneNumberFormattingTextWatcher(mContext, fieldView, null);
        /** @} */
      }

      // Show the "next" button in IME to navigate between text fields
      // TODO: Still need to properly navigate to/from sections without text fields,
      // See Bug: 5713510
      fieldView.setImeOptions(EditorInfo.IME_ACTION_NEXT);

      // Read current value from state
      final String column = field.column;
      final String value = entry.getAsString(column);

      /*
       * Bug Fix by Mediatek Begin.
       *   Original Android's code:
       *     xxx
       *   CR ID: ALPS00244669
       *   Descriptions:
       */
      Log.i(TAG, "setValues setFilter");
      fieldView.setFilters(new InputFilter[] {new InputFilter.LengthFilter(FIELD_VIEW_MAX)});
      /*
       * Bug Fix by Mediatek End.
       */

      fieldView.setText(value);

      // Show the delete button if we have a non-null value
      setDeleteButtonVisible(value != null);

      // Prepare listener for writing changes
      fieldView.addTextChangedListener(
          new TextWatcher() {
            /** M: New Feature xxx @{ */
            int location = 0;

            /** @} */
            @Override
            public void afterTextChanged(Editable s) {
              // Trigger event for newly changed value
              /** M: New Feature Easy Porting @{ */
              /* original code onFieldChanged(column, s.toString()); */
              String phoneText = s.toString();
              phoneText =
                  ExtensionManager.getInstance()
                      .getContactDetailExtension()
                      .TextChanged(
                          inputType, s, phoneText, location, ContactPluginDefault.COMMD_FOR_OP01);
              onFieldChanged(column, phoneText);
              /** @} */
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

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

      fieldView.setEnabled(isEnabled() && !readOnly);

      if (field.shortForm) {
        hidePossible = true;
        mHasShortAndLongForms = true;
        fieldView.setVisibility(mHideOptional ? View.VISIBLE : View.GONE);
      } else if (field.longForm) {
        hidePossible = true;
        mHasShortAndLongForms = true;
        fieldView.setVisibility(mHideOptional ? View.GONE : View.VISIBLE);
      } else {
        // Hide field when empty and optional value
        final boolean couldHide = (!ContactsUtils.isGraphic(value) && field.optional);
        final boolean willHide = (mHideOptional && couldHide);
        fieldView.setVisibility(willHide ? View.GONE : View.VISIBLE);
        hidePossible = hidePossible || couldHide;
      }

      mFields.addView(fieldView);
    }

    // When hiding fields, place expandable
    setupExpansionView(hidePossible, mHideOptional);
    mExpansionView.setEnabled(!readOnly && isEnabled());
  }