Date e Time PickerDialog. Material Design Android - Parte 16

Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba grátis conteúdos Android sem precedentes! Você receberá um email de confirmação. Somente depois de confirma-lo é que eu poderei lhe enviar os conteúdos semanais exclusivos. Os artigos em PDF são entregues somente para os inscritos na lista.

Email inválido.
Blog /Android /Date e Time PickerDialog. Material Design Android - Parte 16

Date e Time PickerDialog. Material Design Android - Parte 16

Vinícius Thiengo
(10154) (13)
Go-ahead
"O método consciente de tentativa e erro é mais bem-sucedido que o planejamento de um gênio isolado."
Peter Skillman
Prototipagem Android
Capa do curso Prototipagem Profissional de Aplicativos
TítuloAndroid: Prototipagem Profissional de Aplicativos
CategoriasAndroid, Design, Protótipo
AutorVinícius Thiengo
Vídeo aulas186
Tempo15 horas
ExercíciosSim
CertificadoSim
Acessar Curso
Quer aprender a programar para Android? Acesse abaixo o curso gratuito no Blog.
Lendo
TítuloCraftsmanship Limpo: Disciplinas, Padrões e ética
CategoriaDesenvolvimento Web
Autor(es)Robert C. Martin
EditoraAlta Books
Edição
Ano2023
Páginas416
Conteúdo Exclusivo
Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba gratuitamente conteúdos Android sem precedentes!
Email inválido

Opa, blz?

Nesse vídeo dou continuidade a série de vídeos sobre o Material Design no Android, porém dessa vez abordando as entidades DatePickerDialog e TimePickerDialog da lib MaterialDateTimePicker para Android. Ambas as classes são utilizadas para simular uma feature de agendamento de test driver para os carros da APP da série.

Muito simples de utilizar e com um nível de customização aceitável (tendo em mente que o Material Design deve ser seguido sem desvios) a lib perdeu um pouco na questão de suporte a APIs anteriores ao Android 4.0 (a principio a lib tem suporte a partir da API 14). Note que na implementação no vídeo, os scripts mais interessantes são baseados em lógica de programação e não apenas em sintaxe, sendo assim, dependendo de sua necessidade (permitir seleção de dia e hora a partir de uma já determinada, por exemplo) você terá de criar a lógica para então trabalhar a resposta (seleção) da data ou horário nos DatePickerDialog e TimePickerDialog. No final do vídeo quase passei direto, mas falei sobre como alterar o tema, as cores principais e como colocar um título no TimePickerDialog. Sem mais delongas vou deixar você assistir ao vídeo.

Obs. : No ultimo vídeo foi informado que esse vídeo seria sobre o Google Analytics, porém por problemas de atualização com um delay muito longo e possível perda de conteúdo importante na explicação da lib, esse vídeo foi adiado para, provavelmente, a próxima vídeo aula.

Para acessar o código do projeto entre no GitHub: https://github.com/viniciusthiengo/tc-material-design

Link para acessar todos os vídeos da série Material Design no Android:

Série Material Design no Android

Seguem os links das páginas apresentadas no vídeo:

Página de Pickers componentes no site do Material Design Android

Página da lib MaterialDateTimePicker no GitHub

Vlw

Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba grátis conteúdos Android sem precedentes!
Email inválido

Relacionado

Lib Fresco Para Carregamento de Imagens (com GIFs e WebPs Animados). Material Design Android - Parte 12Lib Fresco Para Carregamento de Imagens (com GIFs e WebPs Animados). Material Design Android - Parte 12Android
Buscas Com SearchView e SearchRecentSuggestions. Material Design Android - Parte 13Buscas Com SearchView e SearchRecentSuggestions. Material Design Android - Parte 13Android
AppWidget. Material Design Android - Parte 14AppWidget. Material Design Android - Parte 14Android
APP Invites Para Compartilhamento. Material Design Android - Parte 15APP Invites Para Compartilhamento. Material Design Android - Parte 15Android

Compartilhar

Comentários Facebook

Comentários Blog (13)

Para código / script, coloque entre [code] e [/code] para receber marcação especifica.
Forneça seu nome válido.
Forneça seu email válido.
Forneça o comentário.
Enviando, aguarde...
laube.vinicius (1) (0)
08/01/2017
Fala Thiengo, tudo certo??

Gostaria de saber se tem como verificar se o dia selecionado é uma segunda feira ou seja é um outro dia?
Consegui isso com o dia atual mas não quando seleciono um dia qualquer.
Responder
Vinícius Thiengo (1) (0)
08/01/2017
Laube, tudo bem?

Tente utilizando o Calendar do Java, exatamente como utilizado no link a seguir: http://stackoverflow.com/a/6789467/2578331

Veja se assim funciona para ti. Abraço.
Responder
Tarciso Torres (1) (0)
12/12/2015
Vinicius essa lib ta dando esse problema: Error:Failed to resolve: com.android.support:support-v4:23.1.1

quando sincronizo o gradle da esse erro.

segue a baixo a minha configuração do gradle.

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        applicationId "ts.com.celulasdapaz"
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.0'
    compile 'com.wdullaer:materialdatetimepicker:2.1.0'
    compile 'com.github.scottyab:showhidepasswordedittext:0.1'
Responder
Vinícius Thiengo (0) (0)
13/12/2015
Fala Tarciso, blz?
Atualize o
compile 'com.android.support:appcompat-v7:23.1.0'
Para
compile 'com.android.support:appcompat-v7:23.1.1'

Pois a principio o que está acontencendo é que sua lib:
compile 'com.wdullaer:materialdatetimepicker:2.1.0'
Está ja com a versão mais atual da lib supportv4, que está presente somente a partir da v7.23.1.1. Tente essa mudança para ver se vai sem problemas. Abraço
Responder
tarciso Torres (0) (0)
15/12/2015
Vinícius obrigado pela ajuda mas não deu certo.

Então coloquei uma versão anterior e consegui fazer o gradle reconhecer.

Agora ele esta dando outro problema, onde era para aparecer o mês está aparecendo nesse formato "2015 M12" ao invés de aparecer Dezembro.

Tem alguma ideia pq está acontecendo isso?
Responder
Vinícius Thiengo (0) (0)
19/12/2015
Fala Tarciso, conseguiu ai?
Ainda não encontrei aqui, dei uma pesquisada nas issues (https://github.com/wdullaer/MaterialDateTimePicker/issues ), mas nada ainda.
Responder
agsalles (1) (0)
19/10/2015
Conhece alguma lib q funciona na versão 9 ?
Responder
Vinícius Thiengo (0) (0)
20/10/2015
Agsalles, blz?
Não lembro de alguma, dê uma olhada aqui (https://android-arsenal.com/ ) para ver se encontra. E outra, tem de ser de date e time? Pois tem essa da square (https://github.com/square/android-times-square ). Abraço
Responder
Jefferson Clark (1) (0)
03/08/2015
Boa noite Thiengo, no example de Date e Time PickerDialog voce esta usando em apenas um campo de data e hora , mais ser na mesma activity voce estivesse usando dois Campo que iria receber data e hora com valores diferente , como manda esse valores diferente nos campos da activity , tentei fazer um teste aqui quando eu preencho o primeiro campo automaticamente ele ja enviar o valor do primeiro campo para o segundo , e quando eu altero o valor do segundo campo ele alterar tambem o valor do primeiro campo, como fazer os campos receber os valores diferente sem repetir automatico e nem repetindo os metodos do codigo. Obrigado pela sua atenção mais uma vez.
Responder
Vinícius Thiengo (1) (0)
06/08/2015
Fala Jefferson, blz?
Tem várias formas de fazer isso, uma delas é: vc vai ter dois campos diferentes que receberão valores distintos, porém ambos os valores vão vir da mesma estrutura de DatePicker, logo, se seguir o exemplo do vídeo, alguma entidade terá de trabalhar o onClickListener para poder abrir o DatePicker, é ai  que entra a flag que vai permitira que seu código não somente preencha o campo correto (EditText ou TextView) como tb pegue os valores do campo correto para poder já abrir o DatePicker com os valores atuais já escolhidos. Imagine que colocamos o listener de clique em cada um dos campos (qualquer view aceita o listener de clique), logo se o primeiro campo receber o clique setamos a flag (que pode ser uma variavel de instancia do tipo inteiro) como 1 e então no método scheduleTestDrive() o script pode pegar o valor desse campo e ir refatorando ele (quebrando a string e transformando os pedaços em inteiros), dessa forma iniciando o DatePicker com os valores daquele campo atual clicado. No método onTimeSet() teria novamente um if...else para saber se a flag era 1 e então prencher os dados no campo primeiro ou no campo segundo se a flag for 2. Jefferson, dessa forma com flags pode ser um pouco chato, mas vejo sendo a maneira mais simples, teste ai e veja se supri sua demanda. Abraço
Responder
Jefferson Clark (1) (0)
07/08/2015
Tentei seguir a explicação mais agora nao esta replicando o valor, quando eu coloco o primeiro valor ele esta correto, mais quando vou colocar o valor no segundo campo ele alterar o primeiro, estou mandando o codigo e as alteracao que eu apliquei , Grato desde ja.

import android.content.DialogInterface;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;

import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout;
import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.List;

public class BancodeHoras extends AppCompatActivity implements DatePickerDialog.OnDateSetListener, TimePickerDialog.OnTimeSetListener, DialogInterface.OnCancelListener {

    TextView hr1, hr2;
    private ImageButton click1;
    ImageButton horario1,horario2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bancode_horas);
        hr1 = (TextView) findViewById(R.id.time_primeiro);
        hr2 = (TextView) findViewById(R.id.time_segundo);
        horario1 = (ImageButton) findViewById(R.id.imageView);
        horario2 = (ImageButton) findViewById(R.id.imageView2);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        horario1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                scheduleTestDrive(v);
            }
        });
        horario2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                scheduleTestDrive2(v);
            }
        });


    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                return true;

            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_bancode_horas, menu);
        return true;
    }

    private int year, month, day, hour, minute;
    private int flag = 0;
    public void scheduleTestDrive(View view){
        initDateTimeData();
        Calendar cDefault = Calendar.getInstance();
        cDefault.set(year, month, day);

        DatePickerDialog datePickerDialog = DatePickerDialog.newInstance(
                this,
                cDefault.get(Calendar.YEAR),
                cDefault.get(Calendar.MONTH),
                cDefault.get(Calendar.DAY_OF_MONTH)
        );

        Calendar cMin = Calendar.getInstance();
        Calendar cMax = Calendar.getInstance();
        cMax.set( cMax.get(Calendar.YEAR), 11, 31 );
        datePickerDialog.setMinDate(cMin);
        datePickerDialog.setMaxDate(cMax);

        List daysList = new LinkedList<>();
        Calendar[] daysArray;
        Calendar cAux = Calendar.getInstance();

        while( cAux.getTimeInMillis() <= cMax.getTimeInMillis() ){
            if( cAux.get( Calendar.DAY_OF_WEEK ) != 1 && cAux.get( Calendar.DAY_OF_WEEK ) != 7 ){
                Calendar c = Calendar.getInstance();
                c.setTimeInMillis( cAux.getTimeInMillis() );

                daysList.add( c );
            }
            cAux.setTimeInMillis( cAux.getTimeInMillis() + ( 24 * 60 * 60 * 1000 ) );
        }
        daysArray = new Calendar[ daysList.size() ];
        for( int i = 0; i < daysArray.length; i++ ){
            daysArray[i] = daysList.get(i);
        }

        datePickerDialog.setSelectableDays( daysArray );
        datePickerDialog.setOnCancelListener(this);
        datePickerDialog.show( getFragmentManager(), "DatePickerDialog" );
    }

    public void scheduleTestDrive2(View view){
        initDateTimeData();
        Calendar cDefault = Calendar.getInstance();
        cDefault.set(year, month, day);

        DatePickerDialog datePickerDialog = DatePickerDialog.newInstance(
                this,
                cDefault.get(Calendar.YEAR),
                cDefault.get(Calendar.MONTH),
                cDefault.get(Calendar.DAY_OF_MONTH)
        );


        Calendar cMin = Calendar.getInstance();
        Calendar cMax = Calendar.getInstance();
        cMax.set( cMax.get(Calendar.YEAR), 11, 31 );
        datePickerDialog.setMinDate(cMin);
        datePickerDialog.setMaxDate(cMax);

        List daysList = new LinkedList<>();
        Calendar[] daysArray;
        Calendar cAux = Calendar.getInstance();

        while( cAux.getTimeInMillis() <= cMax.getTimeInMillis() ){
            if( cAux.get( Calendar.DAY_OF_WEEK ) != 1 && cAux.get( Calendar.DAY_OF_WEEK ) != 7 ){
                Calendar c = Calendar.getInstance();
                c.setTimeInMillis( cAux.getTimeInMillis() );

                daysList.add( c );
            }
            cAux.setTimeInMillis( cAux.getTimeInMillis() + ( 24 * 60 * 60 * 1000 ) );
        }
        daysArray = new Calendar[ daysList.size() ];
        for( int i = 0; i < daysArray.length; i++ ){
            daysArray[i] = daysList.get(i);
        }

        datePickerDialog.setSelectableDays( daysArray );
        datePickerDialog.setOnCancelListener(this);
        datePickerDialog.show( getFragmentManager(), "DatePickerDialog" );
    }



    private void initDateTimeData(){
        if( year == 0 ){
            Calendar c = Calendar.getInstance();
            year = c.get(Calendar.YEAR);
            month = c.get(Calendar.MONTH);
            day = c.get(Calendar.DAY_OF_MONTH);
            hour = c.get(Calendar.HOUR_OF_DAY);
            minute = c.get(Calendar.MINUTE);
        }
    }

    @Override
    public void onCancel(DialogInterface dialog) {
        year = month = day = hour = minute = 0;
        hr1.setText("");
        hr2.setText("");
    }


    @Override
    public void onDateSet(DatePickerDialog datePickerDialog, int i, int i1, int i2) {
        Calendar tDefault = Calendar.getInstance();
        tDefault.set(year, month, day, hour, minute);

        year = i;
        month = i1;
        day = i2;

        TimePickerDialog timePickerDialog = TimePickerDialog.newInstance(
                this,
                tDefault.get(Calendar.HOUR_OF_DAY),
                tDefault.get(Calendar.MINUTE),
                true
        );
        timePickerDialog.setOnCancelListener(this);
        timePickerDialog.show(getFragmentManager(), "timePickerDialog");
        timePickerDialog.setTitle("Horário Test Drive");

        timePickerDialog.setThemeDark(true);
        SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");

        if (flag == FLAG_START_DATE) {
            hr1.setText(format.format(tDefault.getTime()));
        } else if (flag == FLAG_END_DATE) {
            hr2.setText(format.format(tDefault.getTime()));
        }
    }
    public static final int FLAG_START_DATE = 0;
    public static final int FLAG_END_DATE = 1;

    @Override
    public void onTimeSet(RadialPickerLayout radialPickerLayout, int i, int i1) {
        if( i < 9 || i > 18 ){
            onDateSet(null, year, month, day);
            Toast.makeText(this, "Somente entre 9h e 18h", Toast.LENGTH_SHORT).show();
            return;
        }
        hour = i;
        minute = i1;
        if (flag == FLAG_START_DATE) {
            hr1.setText((day < 10 ? "0" + day : day) + "/" +
                    (month + 1 < 10 ? "0" + (month + 1) : month + 1) + "/" +
                    year + " às " +
                    (hour < 10 ? "0" + hour : hour) + "h" +
                    (minute < 10 ? "0" + minute : minute));

        } else if (flag == FLAG_END_DATE) {
            hr2.setText((day < 10 ? "0" + day : day) + "/" +
                    (month + 1 < 10 ? "0" + (month + 1) : month + 1) + "/" +
                    year + " às " +
                    (hour < 10 ? "0" + hour : hour) + "h" +
                    (minute < 10 ? "0" + minute : minute));
        }

    }

}
XML:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android "
    xmlns:tools="http://schemas.android.com/tools "
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto "
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context="com.mikepenz.materialdrawer.app.BancodeHoras">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        android:elevation="20dp" />

    <TextView android:text="Banco de Horas" android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tt"
        android:layout_below="@+id/toolbar"
        android:layout_gravity="center"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" />

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/editText2"
        android:layout_below="@+id/tt"
        android:layout_marginTop="36dp"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Large Text"
        android:id="@+id/time_primeiro"
        android:layout_below="@+id/imageView"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Large Text"
        android:id="@+id/time_segundo"
        android:layout_below="@+id/imageView2"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true" />

    <ImageButton
        android:layout_width="50dp"
        android:layout_height="wrap_content"
        android:id="@+id/imageView"
        android:onClick="acaohr1"
        android:src="@drawable/timer"
        android:layout_below="@+id/editText2"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:text="HR1" />

    <ImageButton
        android:layout_width="50dp"
        android:layout_height="wrap_content"
        android:id="@+id/imageView2"
        android:layout_below="@+id/editText2"
        android:src="@drawable/timer"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="false"
        android:layout_alignParentStart="false"
        android:text="HR2" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Gravar"
        android:id="@+id/gravar_bancodehoras"
        android:layout_below="@+id/time_segundo"
        android:layout_alignRight="@+id/imageView2"
        android:layout_alignEnd="@+id/imageView2"
        android:layout_marginTop="59dp" />

</RelativeLayout>
Responder
Vinícius Thiengo (0) (0)
08/08/2015
Fala Jefferson, blz?
Não vi em nenhuma parte do código o valor da variavel de instancia "flag" ser alterado, ele permanece o mesmo sempre. O valor dele deve ser alterado nos clickListeners dos buttons:

horario1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                flag =  FLAG_START_DATE;
                scheduleTestDrive(v);
            }
        });
        horario2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                flag =  FLAG_END_DATE;
                scheduleTestDrive2(v);
            }
        });

Tente assim e veja se passa. Abraço
Responder
Jefferson Clark (0) (0)
09/08/2015
Perfeito, resolvido
Obrigado por tira minhas duvidas Thiengo, sucesso !
Responder