Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6074045
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 23, 20262026-05-23T10:20:18+00:00 2026-05-23T10:20:18+00:00

I’m writing an app that requires a TimePicker-based preference (two, actually) and I swiped

  • 0

I’m writing an app that requires a TimePicker-based preference (two, actually) and I swiped some (Apache-licensed) code from the Android Programming Tutorials book. I’ve modified it to work a little better, but there’s one thing puzzling me.

I haven’t tried it on an actual device yet but on emulators it now takes into account system settings for 24-hour time display, clears focus on the TimePicker dialog so that the time is read even when edited manually instead of using the arrow keys, and – the problematic part – displays the selected time in the PreferenceScreen.

The problem is that I’ve tried this in emulators for API levels 3, 4, 7 and 10 and it only works completely correctly in 10. In the emulators for the earlier versions, if I put a checkbox in the PreferenceScreen with two TimePreferences, the TextViews in the two TimePreferences switch positions every time the checkbox is toggled. So if I click the checkbox the first time the app starts, the start time looks like 10pm and the stop time looks like 8am (even though when I click on the preference, the appropriate time shows up in the TimePicker).

Is there a better way to do this? Preferably an elegant way so that the entire class is self-contained and I don’t need to create layouts in XML files that are applicable only to the class? Or is there a way to work around/fix this behavior? I’d also like to avoid using setSummary so that there’s still opportunity to add a summary to the preference. Most of my experimentation has been inside onCreateView with the layout code but I can’t get anything to work completely right. This seems to happen whether I use RelativeLayout or LinearLayout.

The full code is as follows:

package test.android.testproject2;

//imports...

public class TimePreference extends DialogPreference {
    private int lastHour=0;
    private int lastMinute=0;
    private boolean is24HourFormat;
    private TimePicker picker=null;
    private TextView timeDisplay;

    public TimePreference(Context ctxt) {
        this(ctxt, null);
    }

    public TimePreference(Context ctxt, AttributeSet attrs) {
        this(ctxt, attrs, 0);
    }

    public TimePreference(Context ctxt, AttributeSet attrs, int defStyle) {
        super(ctxt, attrs, defStyle);

        is24HourFormat = DateFormat.is24HourFormat(ctxt);
        setPositiveButtonText("Set");
        setNegativeButtonText("Cancel");
    }

    @Override
    public String toString() {
        if(is24HourFormat) {
            return ((lastHour < 10) ? "0" : "")
                    + Integer.toString(lastHour)
                    + ":" + ((lastMinute < 10) ? "0" : "")
                    + Integer.toString(lastMinute);
        } else {
            int myHour = lastHour % 12;
            return ((myHour == 0) ? "12" : ((myHour < 10) ? "0" : "") + Integer.toString(myHour))
                    + ":" + ((lastMinute < 10) ? "0" : "") 
                    + Integer.toString(lastMinute) 
                    + ((lastHour >= 12) ? " PM" : " AM");
        }
    }

    @Override
    protected View onCreateDialogView() {
        picker=new TimePicker(getContext().getApplicationContext());
        return(picker);
    }

    @Override
    protected void onBindDialogView(View v) {
        super.onBindDialogView(v);
        picker.setIs24HourView(is24HourFormat);
        picker.setCurrentHour(lastHour);
        picker.setCurrentMinute(lastMinute);
    }

    @Override
    protected View onCreateView (ViewGroup parent) {
         View prefView = super.onCreateView(parent);
         LinearLayout layout = new LinearLayout(parent.getContext());
         LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.FILL_PARENT, 2);
         layout.addView(prefView, lp);
         timeDisplay = new TextView(parent.getContext());
         timeDisplay.setGravity(Gravity.BOTTOM | Gravity.RIGHT);
         timeDisplay.setText(toString());
         LinearLayout.LayoutParams lp2 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.FILL_PARENT, 1);
         layout.addView(timeDisplay, lp2);
         return layout;
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        super.onDialogClosed(positiveResult);

        if (positiveResult) {
            picker.clearFocus();
            lastHour=picker.getCurrentHour();
            lastMinute=picker.getCurrentMinute();

            String time=String.valueOf(lastHour)+":"+String.valueOf(lastMinute);

            if (callChangeListener(time)) {
                persistString(time);
                timeDisplay.setText(toString());
            }
        }
    }

    @Override
    protected Object onGetDefaultValue(TypedArray a, int index) {
        return(a.getString(index));
    }

    @Override
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
        String time=null;

        if (restoreValue) {
            if (defaultValue==null) {
                time=getPersistedString("00:00");
            }
            else {
                time=getPersistedString(defaultValue.toString());
            }
        }
        else {
            if (defaultValue==null) {
                time="00:00";
            }
            else {
                time=defaultValue.toString();
            }
            if (shouldPersist()) {
                persistString(time);
            }
        }

        String[] timeParts=time.split(":");
        lastHour=Integer.parseInt(timeParts[0]);
        lastMinute=Integer.parseInt(timeParts[1]);;
    }
}

An example preferences layout is below:

<?xml version="1.0" encoding="UTF-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceCategory android:title="@string/preferences_time_title">
        <test.android.testproject2.TimePreference
            android:key="preferences_start_time"
            android:showDefault="true"
            android:defaultValue="08:00"
            android:summary="When to start"
            android:title="@string/preferences_start_time"/>
        <test.android.testproject2.TimePreference
            android:key="preferences_stop_time"
            android:showDefault="true"
            android:defaultValue="22:00"
            android:summary="When to stop"
            android:title="@string/preferences_stop_time"/>
    </PreferenceCategory>
    <PreferenceCategory android:title="@string/preferences_options_title">
        <CheckBoxPreference
            android:key="preferences_enabled"
            android:defaultValue="false"
            android:title="@string/preferences_enabled"/>
    </PreferenceCategory>
</PreferenceScreen>

Screenshots:

Default settings

Checked settings

This happens on emulators for APIs 3, 4 and 7. I’ve also tried it on 10 and it works correctly.

Update: It works correctly on an emulator with API 8 as well (2.2/Froyo).

Update 2: I’ve rewritten the onCreateView method as follows. It still fails the same way, but it’s more efficient to render and I believe it behaves closer to the requirements specified in the Android documentation.

    @Override
    protected View onCreateView (ViewGroup parent) {
         ViewGroup prefView = (ViewGroup) super.onCreateView(parent);
         View widgetLayout;
         int childCounter = 0;
         do {
             widgetLayout = prefView.getChildAt(childCounter);
             childCounter++;
         } while (widgetLayout.getId() != android.R.id.widget_frame); 
         timeDisplay = new TextView(widgetLayout.getContext());
         timeDisplay.setText(toString());
         ((ViewGroup) widgetLayout).addView(timeDisplay);
         return prefView;
    }

My next step is to start some logging in onCreateView, onBindView and getView and see how they’re called and what’s going on inside the views. If anyone comes up with any ideas in the meantime, please let me know!

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-23T10:20:19+00:00Added an answer on May 23, 2026 at 10:20 am

    I’ve figured it out and fixed it. It now works in every level of the API from Cupcake (1.5 – level 3) to Gingerbread (2.3.3 – level 10). Code is below. Please note that the original code is Apache-licensed as specified in the question. I hereby dedicate all of my modifications to the public domain.

    package test.android.testproject2;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.preference.DialogPreference;
    import android.text.format.DateFormat;
    import android.util.AttributeSet;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
    import android.widget.TimePicker;
    
    public class TimePreference extends DialogPreference {
        protected int lastHour=0;
        protected int lastMinute=0;
        protected boolean is24HourFormat;
        protected TimePicker picker=null;
        protected TextView timeDisplay;
    
        public TimePreference(Context ctxt) {
            this(ctxt, null);
        }
    
        public TimePreference(Context ctxt, AttributeSet attrs) {
            this(ctxt, attrs, 0);
        }
    
        public TimePreference(Context ctxt, AttributeSet attrs, int defStyle) {
            super(ctxt, attrs, defStyle);
    
            is24HourFormat = DateFormat.is24HourFormat(ctxt);
            setPositiveButtonText("Set");
            setNegativeButtonText("Cancel");
        }
    
        @Override
        public String toString() {
            if(is24HourFormat) {
                return ((lastHour < 10) ? "0" : "")
                        + Integer.toString(lastHour)
                        + ":" + ((lastMinute < 10) ? "0" : "")
                        + Integer.toString(lastMinute);
            } else {
                int myHour = lastHour % 12;
                return ((myHour == 0) ? "12" : ((myHour < 10) ? "0" : "") + Integer.toString(myHour))
                        + ":" + ((lastMinute < 10) ? "0" : "") 
                        + Integer.toString(lastMinute) 
                        + ((lastHour >= 12) ? " PM" : " AM");
            }
        }
    
        @Override
        protected View onCreateDialogView() {
            picker=new TimePicker(getContext().getApplicationContext());
            return(picker);
        }
    
        @Override
        protected void onBindDialogView(View v) {
            super.onBindDialogView(v);
            picker.setIs24HourView(is24HourFormat);
            picker.setCurrentHour(lastHour);
            picker.setCurrentMinute(lastMinute);
        }
    
        @Override
        public void onBindView(View view) {
            View widgetLayout;
            int childCounter = 0;
            do {
                widgetLayout = ((ViewGroup) view).getChildAt(childCounter);
                childCounter++;
            } while (widgetLayout.getId() != android.R.id.widget_frame); 
            ((ViewGroup) widgetLayout).removeAllViews();
            timeDisplay = new TextView(widgetLayout.getContext());
            timeDisplay.setText(toString());
            ((ViewGroup) widgetLayout).addView(timeDisplay);
            super.onBindView(view);
        }
    
        @Override
        protected void onDialogClosed(boolean positiveResult) {
            super.onDialogClosed(positiveResult);
    
            if (positiveResult) {
                picker.clearFocus();
                lastHour=picker.getCurrentHour();
                lastMinute=picker.getCurrentMinute();
    
                String time=String.valueOf(lastHour)+":"+String.valueOf(lastMinute);
    
                if (callChangeListener(time)) {
                    persistString(time);
                    timeDisplay.setText(toString());
                }
            }
        }
    
        @Override
        protected Object onGetDefaultValue(TypedArray a, int index) {
            return(a.getString(index));
        }
    
        @Override
        protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
            String time=null;
    
            if (restoreValue) {
                if (defaultValue==null) {
                    time=getPersistedString("00:00");
                }
                else {
                    time=getPersistedString(defaultValue.toString());
                }
            }
            else {
                if (defaultValue==null) {
                    time="00:00";
                }
                else {
                    time=defaultValue.toString();
                }
                if (shouldPersist()) {
                    persistString(time);
                }
            }
    
            String[] timeParts=time.split(":");
            lastHour=Integer.parseInt(timeParts[0]);
            lastMinute=Integer.parseInt(timeParts[1]);;
        }
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this
I am writing an app with both english and french support. The app requests
link Im having trouble converting the html entites into html characters, (&# 8217;) i
That's pretty much it. I'm using Nokogiri to scrape a web page what has
I have just tried to save a simple *.rtf file with some websites and
For some reason, after submitting a string like this Jack’s Spindle from a text
I have a string like this: La Torre Eiffel paragonata all&#8217;Everest What PHP function
I've got a string that has curly quotes in it. I'd like to replace
I have a French site that I want to parse, but am running into
We're building an app, our first using Rails 3, and we're having to build

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.