4

I have several classes. First class extends from FragmentActivity, second class is adapter extends from BaseExpandableListAdapter. And Model Class.

First class:

public class CloseInformationTaskActivityList extends FragmentActivity implements ExpandableListView.OnChildClickListener {

private DAOFactory dao;

private ExpandListAdapter expAdapter;
private ExpandableListView expandList;


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

    Bundle b = getIntent().getExtras();
    //task with all information passed in intent by reference
    PRTarea task = (PRTarea) b.getSerializable("Task");

    dao = new DAOFactory(this.getApplicationContext());

    List<PRParametros> parametrosList = dao.getParametrosDAO().getParamsByTaskId(task.getId());

    if (parametrosList.size() > 0) {
        setContentView(R.layout.activity_task_parameters_list);

        expandList = (ExpandableListView) findViewById(R.id.paramsExpandableListView);
        ArrayList<Group> expListItems = setParamsGroups(parametrosList);
        expAdapter = new ExpandListAdapter(CloseInformationTaskActivityList.this, expListItems, this);
        expandList.setOnChildClickListener(this);
        expandList.setAdapter(expAdapter);

    } else {
        setContentView(R.layout.activity_no_param_error);
    }

    // Set up the action bar.
    final ActionBar actionBar = getActionBar();

    // Specify that the Home/Up button should not be enabled, since there is no hierarchical
    // parent.
    assert actionBar != null;
    actionBar.setDisplayUseLogoEnabled(false);
    actionBar.setHomeButtonEnabled(true);
    actionBar.setDisplayHomeAsUpEnabled(false);
    actionBar.setTitle(R.string.task_information_title);
    actionBar.setIcon(R.drawable.ic_arrow_back_white_24dp);
}

private ArrayList<Group> setParamsGroups(List<PRParametros> parametrosList) {
    ArrayList<Group> paramGroupList = new ArrayList<>();
    ArrayList<Child> ch_list = null;
    Group grupo;

    String holdIdGroup = "0";

    //secure check
    if (parametrosList != null && parametrosList.size() > 0) {
        for (int i = 0; i < parametrosList.size(); i++) {
            PRParametros parametro = parametrosList.get(i);
            String idGrupo = parametro.getIdGrupo();
            if (!idGrupo.equals(holdIdGroup)) {
                holdIdGroup = idGrupo;
                grupo = new Group();
                ch_list = new ArrayList<>();

                grupo.setName(dao.getGruposParametrosDAO().getGrupoById(idGrupo).getDescripcion());
                grupo.setItems(ch_list);

                paramGroupList.add(grupo);

            }
            Child child = new Child();
            child.setName(parametro.getNombre());

            if(parametro.getIdTipo().equals("12")){
                if(parametro.getValor() != null){
                    paramValue = dao.getListaParametrosDAO().getValueParamById(Integer.valueOf(parametro.getValor()));
                }
            }

            child.setValue(paramValue);
            child.setType(Integer.valueOf(parametro.getIdTipo()));
            child.setParamId(Integer.valueOf(parametro.getId()));

            if (ch_list != null) {
                ch_list.add(child);
            }

        }
    }

    return paramGroupList;
}


@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            finish();
            return true;
        case R.id.btn_save_param:
            saveParameters();
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

private void saveParameters() {
    Toast.makeText(getApplicationContext(),"Save parameters click", Toast.LENGTH_SHORT).show();

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.save_parameters, menu);
    return super.onCreateOptionsMenu(menu);
}


@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {

    Child child = (Child) parent.getExpandableListAdapter().getChild(groupPosition,childPosition);
    int itemType = child.getType();

    switch (itemType){
        case 12:
            onCreateDialogSingleChoice(child, v);
            break;
        case 9:
            openDateDialog(child, v);
            break;
    }

    return false;
}




/**
 * Open popup with single choice, refresh model data of child
 * and assign selected value to textView
 *
 * @param child model with data
 * @param view to asign selected value
 */
public void onCreateDialogSingleChoice(final Child child, final View view) {
    final AlertDialog.Builder builder = new AlertDialog.Builder(this);

    List<PRListaParametros> listaParametros = dao.getListaParametrosDAO().getListParamsById(child.getParamId());
    List<String> values = new ArrayList<>();

    for(int i = 0; i < listaParametros.size(); i++){
       values.add(listaParametros.get(i).getDescripcion());
    }

    final String[] items = values.toArray(new String[listaParametros.size()]);
    final TextView label = (TextView) ((RelativeLayout) view).getChildAt(1);

    builder.setTitle(R.string.task_information_param_popup_title);
    builder.setSingleChoiceItems(items, 75, new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {

            label.setText(items[which]);
            child.setValue(items[which]);
            dialog.dismiss();

        }
    });
    builder.setNegativeButton(R.string.task_information_param_popup_negative_button,new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            label.setText("");
        }
    });
    builder.show();
}
}

Second class:

/**
* Adapter for expandable list with parameters
*/
public class ExpandListAdapter extends BaseExpandableListAdapter {

private Context mContext;
private ArrayList<Group> groups;
private LayoutInflater mInflater;

public ExpandListAdapter(Context mContext, ArrayList<Group> groups) {
    this.mContext = mContext;
    this.groups = groups;

    mInflater = (LayoutInflater) mContext
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public Object getChild(int groupPosition, int childPosition) {
    ArrayList<Child> chList = groups.get(groupPosition).getItems();
    return chList.get(childPosition);
}   

@Override
public boolean areAllItemsEnabled() {
    return super.areAllItemsEnabled();
}

@Override
public View getChildView(int groupPosition, final int childPosition,
                         final boolean isLastChild, View convertView, ViewGroup parent) {

    final Child child = (Child) getChild(groupPosition, childPosition);


    final ViewHolder holder;
    int itemType = child.getType();

    holder = new ViewHolder();

    if (itemType >= 1 && itemType <= 7) {
        convertView = mInflater.inflate(R.layout.layout_edit_text_close_information, null);

        holder.txtLabel = (TextView) convertView.findViewById(R.id.txt_task_detail_info_param);
        holder.editText = (EditText) convertView.findViewById(R.id.txt_task_detail_info_param_input);

        holder.editText.addTextChangedListener(new TextWatcher() {
            @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) {
                //refresh data in model
                child.setValue(holder.editText.getText().toString());

            }

        });

    }else if(itemType == 8){
        convertView = mInflater.inflate(R.layout.layout_boolean_close_information, null);

        holder.txtLabel = (TextView) convertView.findViewById(R.id.txt_task_detail_info_param_boolean_title);
        holder.booleanSwitch = (Switch) convertView.findViewById(R.id.param_boolean_switch);

        holder.booleanSwitch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                String switchValue = "false";
                if(holder.booleanSwitch.isChecked()){
                    switchValue = "true";
                }
                child.setValue(switchValue);
                //mParamListener.onParameterViewClick(v, child);
            }
        });
    }else {
        convertView = mInflater.inflate(R.layout.layout_text_view_close_information, null);

        holder.txtLabel = (TextView) convertView.findViewById(R.id.txt_task_detail_info_param_text_view);
        holder.txtClickWithValue = (TextView) convertView.findViewById(R.id.txt_task_detail_info_param_click_text_view);

    }
    convertView.setTag(holder);

    if (itemType >= 1 && itemType <= 7) {
        holder.txtLabel.setText(child.getName());
        holder.editText.setText(child.getValue());

        switch (itemType){
            case 1:
                holder.editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_CLASS_NUMBER);
                holder.editText.setKeyListener(DigitsKeyListener.getInstance("0123456789"));
                break;
            case 2:
                holder.editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_CLASS_NUMBER);
                holder.editText.setKeyListener(DigitsKeyListener.getInstance("0123456789."));
                break;
            case 6:
                holder.editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_CLASS_NUMBER);
                holder.editText.setKeyListener(DigitsKeyListener.getInstance("0123456789."));

                if(!holder.editText.getText().toString().isEmpty()){
                    if(!isValidIp(holder.editText.getText().toString())){
                        holder.editText.setError("IPv 4 no valido");
                    }
                }
                break;
            case 7:
                holder.editText.setInputType(InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS);
                if(!holder.editText.getText().toString().equals("")){
                    if(!isValidIp(holder.editText.getText().toString())){
                        holder.editText.setError("IPv 6 no valido");
                    }
                }
                holder.editText.addTextChangedListener(new TextWatcher() {
                    @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(!isValidIp(holder.editText.getText().toString())){
                            holder.editText.setError("IPv 6 no valido");
                        }
                    }
                });
                break;
        }

    }else if(itemType == 8) {
        boolean value = Boolean.valueOf(child.getValue());

        holder.txtLabel.setText(child.getName());
        if(value){
            holder.booleanSwitch.setTextOn(mContext.getResources().getString(R.string.task_information_param_boolean_switch_on));
            holder.booleanSwitch.setChecked(true);
        }else{
            holder.booleanSwitch.setTextOff(mContext.getResources().getString(R.string.task_information_param_boolean_switch_off));
            holder.booleanSwitch.setChecked(false);
        }
    }else {
        holder.txtLabel.setText(child.getName());
        holder.txtClickWithValue.setText(child.getValue());
    }

    return convertView;
}

@Override
public void registerDataSetObserver(DataSetObserver observer) {
    super.registerDataSetObserver(observer);
    //call notifyDataSetChanged() for refresh data model in view
}

public static class ViewHolder {
    public TextView txtLabel;
    public EditText editText;
    public TextView txtClickWithValue;
    public Switch booleanSwitch;
}

@Override
public long getChildId(int groupPosition, int childPosition) {
    return childPosition;
}

@Override
public int getChildrenCount(int groupPosition) {
    ArrayList<Child> chList = groups.get(groupPosition).getItems();
    return chList.size();
}

@Override
public Object getGroup(int groupPosition) {
    return groups.get(groupPosition);
}

@Override
public int getGroupCount() {
    return groups.size();
}

@Override
public long getGroupId(int groupPosition) {
    return groupPosition;
}

@Override
public View getGroupView(int groupPosition, boolean isExpanded,
                         View convertView, ViewGroup parent) {
    Group group = (Group) getGroup(groupPosition);
    if (convertView == null) {
        LayoutInflater inf = (LayoutInflater) mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inf.inflate(R.layout.activity_task_parameters_group, null);
    }
    TextView groupTitle = (TextView) convertView.findViewById(R.id.param_group_name);
    groupTitle.setText(group.getName());

    TextView groupCount = (TextView) convertView.findViewById(R.id.param_group_count);

    int countParam = getChildrenCount(groupPosition);
    if(countParam > 1){
        groupCount.setText(getChildrenCount(groupPosition) + " " +
                mContext.getResources().getString(R.string.task_information_param_group_count_title));
    }else{
        groupCount.setText(getChildrenCount(groupPosition) + " " +
                mContext.getResources().getString(R.string.task_information_param_group_count_title_single));
    }

    if (isExpanded) {
        convertView.setBackgroundResource(R.color.group_param_expanded);
    } else {
        convertView.setBackgroundResource(0);
    }
    return convertView;
}

@Override
public int getChildType(int groupPosition, int childPosition) {
    return super.getChildType(groupPosition, childPosition);
}

@Override
public boolean hasStableIds() {
    return true;
}

@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
    return true;
}

 /**
 * @param ip the ip
 * @return check if the ip is valid ipv4 or ipv6
 */
private static boolean isValidIp(final String ip) {
    return InetAddressUtils.isIPv4Address(ip) || InetAddressUtils.isIPv6Address(ip);
}
}

Model Class

/**
* Model of each parameters
*/
public class Child {

private String name;
private String value;
private int type;
private int paramId;

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getValue() {
    return value;
}

public void setValue(String value) {
    this.value = value;
}

public int getType() {
    return type;
}

public void setType(int type) {
    this.type = type;
}

public int getParamId() {
    return paramId;
}

public void setParamId(int paramId) {
    this.paramId = paramId;
}
}

XML View of each child by type, possible type is EditText, TextView, Switch, popup list with single choice.

<?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="60dp">

<TextView
    android:id="@+id/txt_task_detail_info_param"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:ellipsize="end"
    android:maxLines="1"
    android:minWidth="150dp"
    android:focusable="false"
    android:clickable="false"
    android:padding="20dp"
    android:textSize="14sp"
    android:layout_toLeftOf="@+id/txt_task_detail_info_param_input"
    android:layout_alignParentLeft="true" />

    <EditText
    android:id="@+id/txt_task_detail_info_param_input"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:minWidth="150dp"
    android:maxWidth="200dp"
    android:ellipsize="end"
    android:maxLines="1"
    android:textSize="14sp"
    android:layout_centerVertical="true"
    android:layout_alignParentRight="true" />

</RelativeLayout>

Layout have action bar with save button:

 |------------------Save button--|
 | <ExpandableList>            | |
 |  group1                     | |
 |   child1: textView EditText | |
 |   child2: textView Switch   | |
 |  group2                     | |
 |   child1: textView TextView | |
 |-------------------------------| 

I am trying to get values of child view for save it in database, before i need check each field by type for valid data.

Currently i am checking the values in adapter and works well. Possibly not the right way...

But how to get value of each view by type only clicking save button in FragmentActivity in action bar??

I am trying onChildClick but click event by editText not working. Thanks!

SOLVED

Now I have resolved, but I think is not the right way for do it.

In model class Child i created new field with View.

private View view;

and assigned complete View by type (editText,TextView, etc) in adapter getChildView for example:

child.setView(holder.editText);

and finally use in FragmentActivity

private void checkParameters() {

    boolean validated = true;
    int groupCount = expandList.getExpandableListAdapter().getGroupCount();

    for (int i = 0; i < groupCount; i++) {
        int childCount = expandList.getExpandableListAdapter().getChildrenCount(i);
        for (int j = 0; j < childCount; j++) {
            Child child = (Child) expandList.getExpandableListAdapter().getChild(i, j);

             //secure check
            if (child.getView() != null) {
                int itemType = child.getType();
                //only editText
                if (itemType >= 1 && itemType <= 7) {
                    EditText ed = (EditText) child.getView();
                    //do something
                }
            }               
        }
    }
  }

Anyone know how to do this more efficiently???

Fonexn
  • 189
  • 4
  • 15
  • IMHO, having widgets like `EditText` inside any `AdapterView` is a bad design. If somebody held a gun to my head and tried forcing me to do it, I'd consider letting them pull the trigger. That being said, if I were somehow convinced to write something like this, I would use listeners on the widgets (e.g., `TextWatcher` on the `EditText`) and update my model objects (or a copy of those model objects, if you need to do validation first) in real time based upon user input. – CommonsWare Apr 15 '15 at 11:47
  • 1
    BTW, I forgot to mention, but the only example that I have that is in the area of what you are seeking is [my RateList sample](https://github.com/commonsguy/cw-omnibus/tree/master/Selection/RateList), which puts `RatingBar` widgets in each row. As you will see in the sample, I hook up listeners to update model data as the user taps on the `RatingBar` widgets. That's so that row recycling works -- we do not want to lose the user's ratings just because the user scrolled the list. A more elaborate example would save the changed ratings somewhere persistent (e.g., database). – CommonsWare Apr 15 '15 at 13:16
  • Thank you. At the moment, I update the data model in the listener of EditText - afterTextChanged. child.setValue(holder.editText.getText().toString()); I was thinking might have a way more efficient... – Fonexn Apr 15 '15 at 14:19

0 Answers0