Android为什么偏好会自动更改位置?

时间:2011-01-09 04:30:39

标签: android android-emulator

我有一个preferences.xml文件,其中包含一些复选框偏好设置,自定义时间选择器偏好设置和自定义SeekBar偏好设置。在我的2.2模拟器中一切正常。我尝试在1.6模拟器中运行它,每次调整其中一个滑块(SeekBar首选项)或更改其他首选项时,SeekBar首选项都会更改位置。就像它们只是随意乱扔一样。谁知道我怎么能阻止这个? 这使我无法进行分组,因为他们总是在改变位置。

我有这个用于我的偏好活动:

public class MySettings extends PreferenceActivity {    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);
    }   
}

这是我的滑块:

public class PreferenceSlider extends Preference implements OnSeekBarChangeListener
{  
    public static int maximum    = 100; 
    public static int interval   = 1;  
    private float oldValue = 50; 
    private TextView monitorBox;   
    private float beforeTouch = 50;

    public PreferenceSlider(Context context) 
    {  
        super(context); 
    }  

    public PreferenceSlider(Context context, AttributeSet attrs) 
    {  
        super(context, attrs); 
    }  

    public PreferenceSlider(Context context, AttributeSet attrs, int defStyle) 
    {  
        super(context, attrs, defStyle); 
    }    

    @Override 
    protected View onCreateView(ViewGroup parent)
    {     
        LinearLayout layout = new LinearLayout(getContext());      
        LinearLayout.LayoutParams params1 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);   
        params1.gravity = Gravity.LEFT;   
        params1.weight  = 1.0f;         
        LinearLayout.LayoutParams params2 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);   
        params2.gravity = Gravity.LEFT;   
        LinearLayout.LayoutParams params3 = new LinearLayout.LayoutParams(30, LinearLayout.LayoutParams.WRAP_CONTENT);   
        params3.gravity = Gravity.LEFT; 

        layout.setPadding(15, 5, 10, 5);   
        layout.setOrientation(LinearLayout.VERTICAL);      
        TextView view = new TextView(getContext());   
        view.setText(getTitle());   
        view.setTextSize(18);   
        view.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD);   
        view.setGravity(Gravity.LEFT);   
        view.setLayoutParams(params1);       
        SeekBar bar = new SeekBar(getContext());   
        bar.setMax(maximum);   
        bar.setProgress((int)this.oldValue);  
        //bar.
        //bar.setLayoutParams(params2);   
        bar.setOnSeekBarChangeListener(this);      
        this.monitorBox = new TextView(getContext());   
        this.monitorBox.setTextSize(12);   
        this.monitorBox.setTypeface(Typeface.MONOSPACE, Typeface.ITALIC);   
        this.monitorBox.setLayoutParams(params3);   
        this.monitorBox.setPadding(2, 5, 0, 0);   
        this.monitorBox.setText(bar.getProgress()+"");         
        layout.addView(view);   
        layout.addView(bar);   
        layout.addView(this.monitorBox);   
        layout.setId(android.R.id.widget_frame);         
        return layout;  
    }  

    @Override 
    public void onProgressChanged(SeekBar seekBar, int progress,boolean fromTouch) 
    {      
        progress = Math.round(((float)progress)/interval)*interval;      
        if(!callChangeListener(progress)){
            seekBar.setProgress((int)this.oldValue);     
            return;     }        
        seekBar.setProgress(progress);    
        this.oldValue = progress;    
        this.monitorBox.setText(progress+"");    
        updatePreference(progress);      
        //notifyChanged(); 
    } 

    @Override 
    public void onStartTrackingTouch(SeekBar seekBar) 
    { 
        beforeTouch = seekBar.getProgress();
    }

    @Override 
    public void onStopTrackingTouch(SeekBar seekBar) 
    { 
        if(beforeTouch != seekBar.getProgress())
        {
            notifyChanged();
        }
    }  

    @Override  
    protected Object onGetDefaultValue(TypedArray ta,int index)
    {    
        int dValue = (int)ta.getInt(index,50);       
        return validateValue(dValue); 
    }     

    @Override    
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) 
    {          
        int temp = restoreValue ? getPersistedInt(50) : (Integer)defaultValue;
        if(!restoreValue)        
            persistInt(temp);           
        this.oldValue = temp;    
    }      

    private int validateValue(int value)
    {           
        if(value > maximum)     
            value = maximum;    
        else if(value < 0)     
            value = 0;    
        else if(value % interval != 0)     
            value = Math.round(((float)value)/interval)*interval;               
        return value;      
    }         

    private void updatePreference(int newValue)
    {    
        SharedPreferences.Editor editor =  getEditor();  
        editor.putInt(getKey(), newValue);  
        editor.commit(); } 
    }

然后preferences.xml就像这样:

<com.myprogram.PreferenceSlider                  
    android:key="ringerVolume"              
    android:defaultValue="50"                
    android:title="Ringer Volume"/>

<com.myprogram.PreferenceSlider                  
    android:key="notificationVolume"                
    android:defaultValue="50"                
    android:title="Notification Volume"/>

1 个答案:

答案 0 :(得分:2)

你不应该担心android 1.6,至少这意味着你的代码中有一些污垢,这在2.2中是不可见的,但可能在其他一些版本中,甚至更新版本。

无论如何,在这里最重要的是,我看到这是2011年的一个问题,但现在似乎已经重新开放了,而且在这一点上,我不会继续使用基于此代码的活动,这是相当过时的,所以除此之外没有完美的工作,现在这是最好的时刻,对于一些重新分解。

正如您所看到的那样here 自API级别11以来不推荐使用addPreferencesFromResource ,这意味着75%的设备会像旧的东西一样看待它,而有些新设备可能会在某一天看到它甚至在某种“我告诉你”的基础上提出错误。

没有替代方法,因为几年前Android团队想要的是,不是功能上的变化,而是使用Fragments完全不同的方法

具体来说,您需要创建一些PreferenceFragment个对象来从资源文件加载首选项。我建议这样做,不要浪费时间尝试修复活动中可能出现的当前错误。迁移到新方法将很容易,您将获得更好的结果。

要开始使用,您可以在此处阅读一些代码:

Android Developer - Reference - PreferenceFragment

或者在这里阅读完整的指南:

Android Developer - Api Guides - UI - Settings

如果你继续这个,并有任何进一步的问题,请毫不犹豫地回答任何问题,我将很乐意帮助你!