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

标签 android android-emulator

我有一个 preferences.xml 文件,其中包含一些复选框首选项、自定义时间选择器首选项和自定义 SeekBar 首选项。在我的 2.2 模拟器中一切正常。我试过在 1.6 模拟器中运行它,每次我调整其中一个 slider (SeekBar 首选项)或更改另一个首选项时,SeekBar 首选项都会改变位置。就像他们只是四处乱窜。任何人都知道我怎么能阻止这个? 这使我无法进行分组,因为它们总是在改变位置。

我有这个作为我的偏好 Activity :

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

这是我的 slider :

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"/>

最佳答案

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

无论如何,这里最重要的是,我看到这是 2011 年的问题,但现在似乎重新打开了,在这一点上,我不会继续基于这段代码的 Activity ,它已经过时了,所以除此之外,它还不能完美地工作,现在是进行一些重构的最佳时机。

如你所见here addPreferencesFromResource 自 API 级别 11 起已被弃用,这意味着 75% 的设备将其视为一些旧东西,而一些最新的设备有一天甚至会以一种“我告诉过你”的方式引发错误“基础。

没有替代方法,因为几年前 android 团队在这里想要的,不是功能的改变,而是完全不同的方法,使用 Fragments。

具体来说,您应该创建一些 PreferenceFragment对象从资源文件加载您的首选项。我会建议这样做,不要浪费时间尝试修复 Activity 中可能存在的当前错误。迁移到新方法会很容易,而且您会得到更好的结果。

首先,您可以在此处阅读一些代码:

Android Developer - Reference - PreferenceFragment

或在此处阅读完整指南:

Android Developer - Api Guides - UI - Settings

如果您继续这样做,并且有任何其他问题,请随时回来提出任何问题,我很乐意为您提供帮助!

关于Android 为什么偏好会自动更改位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4637693/

相关文章:

Android应用程序在按钮单击时调用号码

带有 Flutter 的 Android Studio 看不到模拟器

android - 如何在后台服务中放置带有无限循环的线程

Android 模拟器 - Intent.createChooser 在打开 pdf 类型文档时显示 "No application can perform this action"

android - Intel HAXM 运行成功,但是android 模拟器说HAX 不工作,为什么? Windows 8.1 64 位,CPU-Intel Core i5

android - flutter 插件 : detect orientation change in native (android) side

java - 在 Android 客户端中处理来自 Jersey 服务器的多部分响应

java - 如何更改ListView项的文本背景

android - 终结器抛出的未捕获异常(将被丢弃),Android

android - 我试图在 android studio 中单击时更改按钮属性,但不幸的是它停止了应用程序