Android TimePicker AM/PM button not invoking onTimeChanged

前端 未结 11 1116
半阙折子戏
半阙折子戏 2021-02-05 12:38

I\'m having some issues implementing a TimePicker in my application that allows the user to change the time of a database record prior to inserting it.

The problem is th

相关标签:
11条回答
  • 2021-02-05 13:31

    I've also faced the same problem using API 21, and the problem hasn't been solved yet.

    I replaced the TimePicker view for a TimePickerDialog and it worked.

    The following code sets a TextView with the time picked from the TimePickerDialog. You can replace the tv.setText() with any logic :

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final TextView tv = (TextView)findViewById(R.id.textView);
    
        Calendar calendar = Calendar.getInstance();
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int minute = calendar.get(Calendar.MINUTE);
        TimePickerDialog timePickerDialog = new TimePickerDialog(this,
                new TimePickerDialog.OnTimeSetListener() {
                    @Override
                    public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
                        tv.setText(String.format(Locale.getDefault(),"Hour: %d, Minute: %d ",hourOfDay,minute));
                    }
        }, hour, minute, true);
        timePickerDialog.show();
    }
    
    0 讨论(0)
  • 2021-02-05 13:32

    I have tested the code. Yes, you are right, TimePicker AM/PM button not invoking onTimeChanged method which it should.

    Actually, Its a bug. It has been reported to google. You can find it here
    http://code.google.com/p/android/issues/detail?id=18982

    Please vote, comment & Star the bug report to raise its priority and to get it fixed by development team as soon as possible.

    0 讨论(0)
  • 2021-02-05 13:34

    Velval solution is the only solution that works and compatiple with different Android vesrions. I tried it on api 17 and 23. but it has an issue that it prevent original on click listener on Android 6. so here is what worked with me. to use touch instead of click:

    public class MyTimePicker extends TimePicker {
    
        private OnTimeChangedListener onTimeChangedListener;
    
        public MyTimePicker(Context context) {
            super(context);
            //  init();
        }
    
        public MyTimePicker(Context context, AttributeSet attrs) {
            super(context, attrs);
            //init();
        }
    
        public MyTimePicker(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            // init();
        }
    
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        public MyTimePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            // Stop ScrollView from getting involved once you interact with the View
            if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
                ViewParent p = getParent();
                if (p != null)
                    p.requestDisallowInterceptTouchEvent(true);
            }
            return false;
        }
    
        @Override
        public void setOnTimeChangedListener(OnTimeChangedListener onTimeChangedListener) {
            super.setOnTimeChangedListener(onTimeChangedListener);
            this.onTimeChangedListener = onTimeChangedListener;
        }
    
        @Override
        protected void onFinishInflate() {
            super.onFinishInflate();
            init();
        }
    
        private void init() {
    
            try {
                ViewGroup amPmView;
                ViewGroup v1 = (ViewGroup) getChildAt(0);
                ViewGroup v2 = (ViewGroup) v1.getChildAt(0);
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
                    ViewGroup v3 = (ViewGroup) v2.getChildAt(0);
                    amPmView = (ViewGroup) v3.getChildAt(3);
                } else {
                    amPmView = (ViewGroup) v2.getChildAt(3);
                }
                View.OnTouchListener listener = new View.OnTouchListener() {
                    @Override
                    public boolean onTouch(View v, MotionEvent event) {
                        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
                            onTimeChangedListener.onTimeChanged(MyTimePicker.this, getCurrentHour(), getCurrentMinute());
                        } else {
                            int hour = getCurrentHour();
                            if (hour >= 12) {
                                hour -= 12;
                            } else {
                                hour += 12;
                            }
                            onTimeChangedListener.onTimeChanged(MyTimePicker.this, hour, getCurrentMinute());
                        }
    
                        return false;
                    }
    
                };
                View am = amPmView.getChildAt(0);
                View pm = amPmView.getChildAt(1);
    
                am.setOnTouchListener(listener);
                pm.setOnTouchListener(listener);
            } catch (Exception e) {
                // DO nothing... just ignore the workaround if this fails.
            }
    
    
        }
    }
    
    0 讨论(0)
  • 2021-02-05 13:37

    I found this answer, but it didn't work for me, so I thought I would update.

    In 3.2 (and above?), the time picker does not have a button for am/pm. Instead it has a NumberPicker. The following code worked for me. The last bit is there because I needed to limit the time selected to no earlier than the 'min' date and no greater than the 'max' date, so I had to check the date selected in the matching DatePicker control:

            NumberPicker amPmView  = (NumberPicker)((ViewGroup)tp.getChildAt(0)).getChildAt(3);
            amPmView.setOnValueChangedListener(new OnValueChangeListener() { 
                @Override
                public void onValueChange(NumberPicker arg0, int arg1, int arg2) {
                    if(arg0.getValue()== 1){ 
                        if (tp.getCurrentHour() < 12)
                            tp.setCurrentHour(tp.getCurrentHour() + 12); 
                    } 
                    else{ 
                        if (tp.getCurrentHour() >= 12) 
                            tp.setCurrentHour(tp.getCurrentHour() - 12); 
                    } 
    
                    int year = dp.getYear();
                    int month = dp.getMonth();
                    int dayOfMonth = dp.getDayOfMonth();
                    int hourOfDay = tp.getCurrentHour();
                    int minute = tp.getCurrentMinute();
    
                    if (year == min.get(Calendar.YEAR) && month == min.get(Calendar.MONTH) && dayOfMonth == min.get(Calendar.DAY_OF_MONTH)){
                        if ((hourOfDay < min.get(Calendar.HOUR_OF_DAY))||
                            (hourOfDay == min.get(Calendar.HOUR_OF_DAY) && (minute < min.get(Calendar.MINUTE)))){
                            tp.setCurrentHour(min.get(Calendar.HOUR_OF_DAY));
                            tp.setCurrentMinute(min.get(Calendar.MINUTE));
                        }
                    }else if (year == max.get(Calendar.YEAR) && month == max.get(Calendar.MONTH) && dayOfMonth == max.get(Calendar.DAY_OF_MONTH)){
                        if ((hourOfDay > max.get(Calendar.HOUR_OF_DAY))||
                            (hourOfDay == max.get(Calendar.HOUR_OF_DAY) && (minute > max.get(Calendar.MINUTE)))){
                            tp.setCurrentHour(max.get(Calendar.HOUR_OF_DAY));
                            tp.setCurrentMinute(max.get(Calendar.MINUTE));
                        }
                    }
                } 
            }); 
    
    0 讨论(0)
  • 2021-02-05 13:37

    Please use the below code it is working fine for me.

    final TimePicker tp=(TimePicker)findViewById(R.id.timePicker1);
        View amPmView  = ((ViewGroup)tp.getChildAt(0)).getChildAt(2);
        if(amPmView instanceof Button)
        {
            amPmView.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    Log.d("OnClickListener", "OnClickListener called");
                    if(v instanceof Button)
                    {
                        if(((Button) v).getText().equals("AM"))
                        {
                            ((Button) v).setText("PM");
                             if (tp.getCurrentHour() < 12) {
                                 tp.setCurrentHour(tp.getCurrentHour() + 12);
                                }  
    
                        }
                        else{
                            ((Button) v).setText("AM");
                             if (tp.getCurrentHour() >= 12) {
                                 tp.setCurrentHour(tp.getCurrentHour() - 12);
                                }
                        }
                    }
    
                }
            });
        }
    
    0 讨论(0)
提交回复
热议问题