Tecnologías Móviles

clase 10

Ejercicio de la clase anterior

 

 

 

 

 

SERVICE

 

 

 

 

 

 

Settings

Ejercicio de la clase anterior

...

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.2.1'
    compile 'com.android.support:design:23.2.1'
    compile 'org.apache.commons:commons-io:1.3.2'
    compile 'com.android.support:support-v4:23.2.1'
    compile 'com.android.support:preference-v7:23.3.0'
    compile 'com.android.support:preference-v14:23.3.0'
}

build.gradle (app)

Ejercicio de la clase anterior

public class MainActivity extends AppCompatActivity {

    ...

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            //startActivity(new Intent(this, SettingsActivity.class));
            SettingsFragment settings = new SettingsFragment();
            if(isPort) {
                FragmentTransaction transaction = manager.beginTransaction();
                transaction.replace(R.id.container, settings);
                transaction.addToBackStack("settings");
                transaction.commit();
            } else {
                FragmentTransaction transaction = manager.beginTransaction();
                transaction.replace(R.id.listContainer, settings);
                transaction.replace(R.id.formContainer, null);
                transaction.addToBackStack("settings");
                transaction.commit();
            }
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

MainActivity

Ejercicio de la clase anterior

public class SettingsFragment extends PreferenceFragmentCompat {

    ...

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Load the preferences from an XML resource
        addPreferencesFromResource(R.xml.settings);

        // Bind the summaries of EditText/List/Dialog/Ringtone preferences
        // to their values. When their values change, their summaries are
        // updated to reflect the new value, per the Android Design
        // guidelines.
        bindPreferenceSummaryToValue(findPreference("interval"), getString(R.string.seconds));
        bindPreferenceSummaryToValue(findPreference("url"));
    }
    private static void bindPreferenceSummaryToValue(Preference preference) {
        bindPreferenceSummaryToValue("", preference, "");
    }

    private static void bindPreferenceSummaryToValue(Preference preference, String suffix) {
        bindPreferenceSummaryToValue("", preference, suffix);
    }

    private static void bindPreferenceSummaryToValue(String preffix, Preference preference) {
        bindPreferenceSummaryToValue(preffix, preference, "");
    }
    public interface OnExtendedPreferenceChaneListener extends Preference.OnPreferenceChangeListener {
        public void setPreffix(String preffix);
        public void setSuffix(String suffix);
    }

}

SettingsFragment

Ejercicio de la clase anterior

public class SettingsFragment extends PreferenceFragmentCompat {

    ...

    private static void bindPreferenceSummaryToValue(String preffix, Preference preference, 
                                                                            String suffix) {
        // Set the listener to watch for value changes.
        OnExtendedPreferenceChaneListener sBindPreferenceSummaryToValueListener = 
                new OnExtendedPreferenceChaneListener() {
            String mPreffix="";
            String mSuffix="";
            public void setPreffix(String preffix) {
                mPreffix=preffix+" ";
            }
            public void setSuffix(String suffix) {
                mSuffix = " "+suffix;
            }
            public boolean onPreferenceChange(Preference preference, Object value) {
                String stringValue = value.toString();
                if (preference instanceof ListPreference) {
                    // For list preferences, look up the correct display value in
                    // the preference's 'entries' list.
                    ListPreference listPreference = (ListPreference) preference;
                    int index = listPreference.findIndexOfValue(stringValue);

                    // Set the summary to reflect the new value.
                    preference.setSummary(
                            index >= 0
                                    ? mPreffix+listPreference.getEntries()[index]+mSuffix
                                    : null);

                } else {
                ...

SettingsFragment

Ejercicio de la clase anterior

public class SettingsFragment extends PreferenceFragmentCompat {

    ...

    private static void bindPreferenceSummaryToValue(String preffix, Preference preference, 
                                                                            String suffix) {
        // Set the listener to watch for value changes.
        OnExtendedPreferenceChaneListener sBindPreferenceSummaryToValueListener = 
                new OnExtendedPreferenceChaneListener() {
                ...
                } else {
                    // For all other preferences, set the summary to the value's
                    // simple string representation.
                    preference.setSummary(mPreffix+stringValue+mSuffix);
                }
                return true;
            }
        };

        sBindPreferenceSummaryToValueListener.setPreffix(preffix);
        sBindPreferenceSummaryToValueListener.setSuffix(suffix);

        preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);

        // Trigger the listener immediately with the preference's
        // current value.
        sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
                PreferenceManager
                        .getDefaultSharedPreferences(preference.getContext())
                        .getString(preference.getKey(), ""));
    }

}

SettingsFragment

Ejercicio de la clase anterior

public class ApiClientService extends Service implements SharedPreferences.OnSharedPreferenceChangeListener {

    ...

    protected void setTimer() {
        Integer sec = Integer.valueOf(mPreferences.getString("interval","5"));
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                mBinder.resolvePending();
                mBinder.findUsers();
            }
        }, 0, sec * 1000);
    }

    protected void setUrl() {
        mUrl = mPreferences.getString("url", "http://tm5-agmoyano.rhcloud.com/");
    }

    public void onCreate() {
        ...
        mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        setTimer();
        setUrl();
        mPreferences.registerOnSharedPreferenceChangeListener(this);
    }

    ...
}

ApiClientService

Ejercicio de la clase anterior

public class ApiClientService extends Service implements SharedPreferences.OnSharedPreferenceChangeListener {

    ...

    public void onDestroy() {
        timer.cancel();
        mPreferences.unregisterOnSharedPreferenceChangeListener(this);
    }

    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        if (key.equals("interval")) {
            setTimer();
        }
        if (key.equals("url")) {
            setUrl();
        }
    }

    ...
}

ApiClientService

Menúes

  • Options menu and app bar
    Opciones generales de la aplicación, ej: Buscar, Configuraciones, etc.
  • Context menu and contextual action mode
    Menú flotante que aparece cuando se hace un click largo sobre un elemento. Provee acciones que afectan a los elementos seleccionados.
  • Popup menu
    Provee una lista de items que se despliegan a partir del elemento que invocó el menú. No debe proveer acciones que afecten al elemento seleccionado, sino pueden proveer acciones extendidas de un comando, o acciones que se relacionan al elemento seleccionado
     

Menúes

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/new_game"
          android:icon="@drawable/ic_new_game"
          android:title="@string/new_game"
          android:showAsAction="ifRoom"/>
    <item android:id="@+id/help"
          android:icon="@drawable/ic_help"
          android:title="@string/help" />
</menu>
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/file"
          android:title="@string/file" >
        <!-- "file" submenu -->
        <menu>
            <item android:id="@+id/create_new"
                  android:title="@string/create_new" />
            <item android:id="@+id/open"
                  android:title="@string/open" />
        </menu>
    </item>
</menu>

Menúes

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.game_menu, menu);
    return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle item selection
    switch (item.getItemId()) {
        case R.id.new_game:
            newGame();
            return true;
        case R.id.help:
            showHelp();
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

Options menu and app bar

Menúes

Options menu and app bar

Para modificar el menú en runtime se debe implementar el método onPrepareOptionsMenu()

 

Dentro del método se pueden agregar, eliminar y deshabilitar elementos.

 

Para avisar que el menú debería cambiarse, hay que llamar al método invalidateOptionsMenu()

Menúes

Contextual action mode

Vistas individuales

private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {

    // Called when the action mode is created; startActionMode() was called
    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        // Inflate a menu resource providing context menu items
        MenuInflater inflater = mode.getMenuInflater();
        inflater.inflate(R.menu.context_menu, menu);
        return true;
    }

    // Called each time the action mode is shown. Always called after onCreateActionMode, but
    // may be called multiple times if the mode is invalidated.
    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return false; // Return false if nothing is done
    }

    // Called when the user selects a contextual menu item
    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_share:
                shareCurrentItem();
                mode.finish(); // Action picked, so close the CAB
                return true;
            default:
                return false;
        }
    }

    // Called when the user exits the action mode
    @Override
    public void onDestroyActionMode(ActionMode mode) {
        mActionMode = null;
    }
};

Menúes

Contextual action mode

Menú contextual para vistas individuales

someView.setOnLongClickListener(new View.OnLongClickListener() {
    // Called when the user long-clicks on someView
    public boolean onLongClick(View view) {
        if (mActionMode != null) {
            return false;
        }

        // Start the CAB using the ActionMode.Callback defined above
        mActionMode = getActivity().startActionMode(mActionModeCallback);
        view.setSelected(true);
        return true;
    }
});

Menúes

Contextual action mode

GridView y ListView

ListView listView = getListView();
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {

    @Override
    public void onItemCheckedStateChanged(ActionMode mode, int position,
                                          long id, boolean checked) {
        // Here you can do something when items are selected/de-selected,
        // such as update the title in the CAB
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        // Respond to clicks on the actions in the CAB
        switch (item.getItemId()) {
            case R.id.menu_delete:
                deleteSelectedItems();
                mode.finish(); // Action picked, so close the CAB
                return true;
            default:
                return false;
        }
    }

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        // Inflate the menu for the CAB
        MenuInflater inflater = mode.getMenuInflater();
        inflater.inflate(R.menu.context, menu);
        return true;
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {
        // Here you can make any necessary updates to the activity when
        // the CAB is removed. By default, selected items are deselected/unchecked.
    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        // Here you can perform updates to the CAB due to
        // an invalidate() request
        return false;
    }
});

Menúes

Popup menu

public void showMenu(View v) {
    PopupMenu popup = new PopupMenu(this, v);

    // This activity implements OnMenuItemClickListener
    popup.setOnMenuItemClickListener(this);
    popup.inflate(R.menu.actions);
    popup.show();
}

@Override
public boolean onMenuItemClick(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.archive:
            archive(item);
            return true;
        case R.id.delete:
            delete(item);
            return true;
        default:
            return false;
    }
}
<ImageButton
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:src="@drawable/ic_overflow_holo_dark"
    android:contentDescription="@string/descr_overflow_button"
    android:onClick="showPopup" />

Ejercicio

Basado en el ejercicio de la clase anterior, realizar los siguientes puntos:

  • Agregar al menú general, una acción de búsqueda. Cuando se haga click sobre dicha acción, se debe mostrar un Fragment que contenga un EditText y un ListView. Mientras se escribe en el EditText (addTextChangedListener) se debe modificar el contenido de la lista.
     
  • Quitar el boton eliminar dentro de los items del listado de usuarios.
     
  • Generar un menú contextual para el ListView que contiene el listado de usuarios, y que permita eliminar varios usuarios al mismo tiempo. 

Tecnologías Móviles - Clase 10

By Agustin Moyano

Tecnologías Móviles - Clase 10

  • 653