Android TimePicker AM/PM button not invoking onTimeChanged

前端 未结 11 1115
半阙折子戏
半阙折子戏 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:12

    I would like to share my solution as well since the other workarounds posted here doesn't work for me. But I am able to figure it out. This line:

        View amPmView  = ((ViewGroup)tp.getChildAt(0)).getChildAt(2);
    

    Doesn't seem to return the picker wheel for AM_PM.

        NumberPicker amPmView  = (NumberPicker ((ViewGroup)tp.getChildAt(0)).getChildAt(3);
    

    Neither this as well, since this one returns a TextView. It seems it seems it is the label designated on the picker.

    But using the latter, getting the 4th child element returns me the picker wheel for AM_PM. Here is what I got so far:

        NumberPicker amPmView = (NumberPicker)((ViewGroup) mTimePicker.getChildAt(0)).getChildAt(4);
        amPmView.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() 
        {
            @Override
            public void onValueChange(NumberPicker picker, int oldVal, int newVal) 
            {
                Log.i(NoteApplication.TAG, "AM_PM selected...");
            }
        });
    

    Now I am able to detect changes in AM_PM. I hope this help some other people who can't retrieve it via getChildAt(2) or getChildAt(3) as described by other answers.

    Also take note that this is the case for the class TimePicker, I haven't tried this yet on a TimePickerDialog so I am not sure for that one. I am testing at min sdk 8 targeting api 22.

    HTH

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

    With API 25 Nougat, code of Velval / Hisham is the only one that works but not in landscape mode. I changed the code and it works fine :) :

    public class AMPMTimePicker extends TimePicker {
    
    private static final String TAG = "AMPMTimePicker";
    private OnTimeChangedListener onTimeChangedListener;
    
    public AMPMTimePicker(Context context) {
        super(context);
    }
    
    public AMPMTimePicker(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    
    public AMPMTimePicker(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public AMPMTimePicker(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();
    }
    
    @SuppressWarnings("deprecation")
    private void init() {
        try {
            ViewGroup amPmView;
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    
                // LinearLayout (LOLLIPOP)
                // GridLayout (M-LANDSCAPE)
                // LinearLayout (M-PORTRAIT)
                ViewGroup v1 = (ViewGroup) getChildAt(0);
    
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
    
                    // FrameLayout (LOLLIPOP-LANDSCAPE)
                    // FrameLayout - id:time_header (LOLLIPOP-PORTRAIT)
                    ViewGroup v2 = (ViewGroup) v1.getChildAt(0);
    
                    // FrameLayout - id:TimeHeader (LOLLIPOP-LANDSCAPE)
                    // LinearLayout (LOLLIPOP-PORTRAIT)
                    ViewGroup v3 = (ViewGroup) v2.getChildAt(0);
    
                    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
                        ViewGroup v4 = (ViewGroup) v3.getChildAt(0); // LinearLayout (LOLLIPOP)
                        amPmView = (ViewGroup) v4.getChildAt(3); // LinearLayout - id:ampm_layout (LOLLIPOP)
                    } else { // PORTRAIT
                        amPmView = (ViewGroup) v3.getChildAt(3); // LinearLayout - id:ampm_layout (LOLLIPOP)
                    }
                } else { // M and after
                    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
                        ViewGroup v2 = (ViewGroup) v1.getChildAt(1); // RelativeLayout (M)
                        amPmView = (ViewGroup) v2.getChildAt(1); // LinearLayout - id:ampm_layout (M)
                    } else {
                        ViewGroup v2 = (ViewGroup) v1.getChildAt(0); // RelativeLayout - id:time_header (M)
                        amPmView = (ViewGroup) v2.getChildAt(3); // LinearLayout - id:ampm_layout (M)
                    }
                }
    
                View am = amPmView.getChildAt(0); // AppCompatCheckedTextView - id:am_label
                View pm = amPmView.getChildAt(1); // AppCompatCheckedTextView - id:pm_label
    
                View.OnTouchListener listener = new View.OnTouchListener() {
                    @Override
                    public boolean onTouch(View v, MotionEvent event) {
                        int hour;
                        int minute;
                        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
                            hour = getCurrentHour();
                            minute = getCurrentMinute();
                        } else {
                            hour = getHour();
                            minute = getMinute();
                        }
                        hour = (hour >= 12) ? hour - 12 : hour + 12;
                        onTimeChangedListener.onTimeChanged(AMPMTimePicker.this, hour, minute);
                        return false;
                    }
                };
                am.setOnTouchListener(listener);
                pm.setOnTouchListener(listener);
            }
        } catch (Exception e) {
            Log.e(TAG, "TimePicker is not defined for this Android version : " + e.getMessage());
        }
    }
    }
    
    0 讨论(0)
  • 2021-02-05 13:20

    Had the same issue when creating the TimePicker in code and none of the provided solutions worked for me. Below was what I ended up doing. Tested on API levels 18, 21 and 23

    final TimePicker tp = new TimePicker(getContext());
    tp.setOnTimeChangedListener(this);
    try {
        ViewGroup amPmView;
        ViewGroup v1 = (ViewGroup)tp.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.OnClickListener listener = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tp.setCurrentHour((tp.getCurrentHour() + 12) % 24);
            }
        };
        View am = amPmView.getChildAt(0);
        View pm = amPmView.getChildAt(1);
        am.setOnClickListener(listener);
        pm.setOnClickListener(listener);
    } catch (Exception e) {
        // DO nothing... just ignore the workaround if this fails.
    }
    
    0 讨论(0)
  • 2021-02-05 13:21

    this link shows that onTimeChanged(); is getting called which triggers the event dispatcher.

    If you're not getting the events you need (even though it appears to be sending) you have have to

    • extend the default TimerPicker,

    • override mAmPmButton.setOnClickListener,

    • and include your version in the view.


    mAmPmButton.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                requestFocus();
                if (mIsAm) {
    
                    // Currently AM switching to PM
                    if (mCurrentHour < 12) {
                        mCurrentHour += 12;
                    }                
                } else {
    
                    // Currently PM switching to AM
                    if (mCurrentHour >= 12) {
                        mCurrentHour -= 12;
                    }
                }
                mIsAm = !mIsAm;
                mAmPmButton.setText(mIsAm ? mAmText : mPmText);
                onTimeChanged();
            }
        });
    
    0 讨论(0)
  • 2021-02-05 13:26

    i make this method thats return true if the TimePicker select AM and false if the TimePicker select PM. note: the suppresLint is for Api 8 don't work .getvalue() statement

    Saludos!! :)

    @SuppressLint("NewApi")
    private boolean isAM(TimePicker timePicker){
        NumberPicker numberPickerAmPm  = (NumberPicker)((ViewGroup) timePicker.getChildAt(0)).getChildAt(3);
        if(numberPickerAmPm.getValue()==0){
            //sendToast("es am");
            return true;
        }else{
           //sendToast("es pm");
            return false;
        }
    
    }
    
    0 讨论(0)
  • 2021-02-05 13:30

    Here's a quick project that I threw together that supports Android 4.0+. Basically, it shows a TextView that is always in sync with the TimePicker, regardless of which vertical spinner is being manipulated by the user.

    https://gist.github.com/danialgoodwin/5694256

    0 讨论(0)
提交回复
热议问题