Spinner 등의 기능, SharedPreference으로 값 변경 저장하기,

조회수 1237회
public class RD_OSBG : Fragment
{
    Spinner _BG_Position;

    public override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        ISharedPreferences prefs = Application.Context.GetSharedPreferences("Test", FileCreationMode.Private);
        prefs.GetString("Test_Data", "");

        // Create your fragment here
    }

    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View _RD_OSBG = inflater.Inflate(Resource.Layout.RD_OSBG_Layout, container, false);


        Switch _OS_Mark = (Switch)_RD_OSBG.FindViewById(Resource.Id._OS_Mark);
        _OS_Mark.CheckedChange += (s, e) =>
        {
            if (e.IsChecked == true)
            {
                Toast.MakeText(this.Activity, "OS Mark를 사용합니다", ToastLength.Short).Show();
            }
            else if (e.IsChecked == false)
            {
                Toast.MakeText(this.Activity, "OS Mark를 사용하지 않습니다", ToastLength.Short).Show();
            }
        };


        TextView _OS_Length_Text = (TextView)_RD_OSBG.FindViewById(Resource.Id._OS_Length_Text);
        SeekBar _OS_Length = (SeekBar)_RD_OSBG.FindViewById(Resource.Id._OS_Length);
        int _Setup_OS_Length_Text = 0;
        _OS_Length_Text.Text = "OS Length : " + _Setup_OS_Length_Text + "ft";
        _OS_Length.ProgressChanged += (s, e) =>
        {
            //int _Setup_Progress = e.Progress;
            _OS_Length_Text.Text = string.Format("OS Length : " + e.Progress + "ft");
        };


        TextView _OS_Beam_Text = (TextView)_RD_OSBG.FindViewById(Resource.Id._OS_Beam_Text);
        SeekBar _OS_Beam = (SeekBar)_RD_OSBG.FindViewById(Resource.Id._OS_Beam);
        int _Setup_OS_Beam_Text = 0;
        _OS_Beam_Text.Text = "OS Beam : " + _Setup_OS_Beam_Text + "ft";
        _OS_Beam.ProgressChanged += (s, e) =>
        {
            //int _Setup_Progress = e.Progress;
            _OS_Beam_Text.Text = string.Format("OS Beam : " + e.Progress + "ft");
        };


        Switch _BG_Mark = (Switch)_RD_OSBG.FindViewById(Resource.Id._BG_Mark);
        _BG_Mark.CheckedChange += (s, e) =>
        {
            if(e.IsChecked == true)
            {
                Toast.MakeText(this.Activity, "Barge Mark을 활성화 합니다", ToastLength.Short).Show();
            }
            else if(e.IsChecked == false)
            {
                Toast.MakeText(this.Activity, "Barge Mark을 비활성화 합니다", ToastLength.Short).Show();
            }
        };


        _BG_Position = (Spinner)_RD_OSBG.FindViewById(Resource.Id._BG_Position);
        ArrayList _BG_Position_Contents = new ArrayList { "Bow", "Stern" };
        _BG_Position.Adapter = new ArrayAdapter(this.Activity, Resource.Layout.Custom_Spinner, Resource.Id._Custom_Spinner_Text, _BG_Position_Contents);

        ISharedPreferences prefs = Application.Context.GetSharedPreferences("Test", FileCreationMode.Private);
        ISharedPreferencesEditor editor = prefs.Edit();

        _BG_Position.ItemSelected += (s, e) =>
        {
            switch(e.Position)
            {
                case 1:
                    Toast.MakeText(this.Activity, "Stern", ToastLength.Short).Show();
                    editor.PutString("Test_Data", "Stern");
                    editor.Commit();
                    break;
            }

        };


        TextView _BG_Length_Text = (TextView)_RD_OSBG.FindViewById(Resource.Id._BG_Length_Text);
        SeekBar _BG_Length = (SeekBar)_RD_OSBG.FindViewById(Resource.Id._BG_Length);
        int _Setup_BG_Length_Text = 0;
        _BG_Length_Text.Text = "BG Length : " + _Setup_BG_Length_Text + "ft";
        _BG_Length.ProgressChanged += (s, e) =>
        {
            //int _Setup_Progress = e.Progress;
            _BG_Length_Text.Text = string.Format("BG Length : " + e.Progrhess + "ft");
        };


        TextView _BG_Beam_Text = (TextView)_RD_OSBG.FindViewById(Resource.Id._BG_Beam_Text);
        SeekBar _BG_Beam = (SeekBar)_RD_OSBG.FindViewById(Resource.Id._BG_Beam);
        int _Setup_BG_Beam_Text = 0;
        _BG_Beam_Text.Text = "BG Beam : " + _Setup_BG_Beam_Text + "ft";
        _BG_Beam.ProgressChanged += (s, e) =>
        {
            //int _Setup_Progress = e.Progress;
            _BG_Beam_Text.Text = string.Format("BG Beam : " + e.Progress + "ft");
        };


        return _RD_OSBG;
    }
}

현재 이런 상태입니다 Spinner, Switch, SeekBar의 값이 변경 된 내용을 저장하여 Fragment를 종료한 후에 다시 들어갔을 때, 값이 변경된 값으로 유지되도록 하려면 어떻게 해야하나요?

SharedPreference를 지금 Spinner 쪽에 넣어두고 OnCreate 부분에서 불러왓는데 에러가 발생하더라구요 ㅠㅠ

  • (•́ ✖ •̀)
    알 수 없는 사용자
  • 어떤 에러가 발생하시는건가요? 알 수 없는 사용자 2018.6.19 15:10
  • 에러라기보다는 동작을 안하는거겠죠? 처음에는 에러가 났는데 위에처럼 한 이후로는 에러는 없는데, 어플리케이션 실행을 하면 동작은 다되는데 저장되는 현상이 일어나질 않아요. 다시 접속해도 원래 기본값으로 복구 되고. 알 수 없는 사용자 2018.6.19 15:12
  • 음 첨부하신 코드만 보면 itemSelected() 에서 preference 에 값을 저장하는부분은 보이는데 읽어와서 Spinner 에 세팅하는 부분은 안보이는것 같네요. 알 수 없는 사용자 2018.6.19 15:15
  • Spinner세팅하는 부분이 가장 위에 OnCreate 부분에서 해야하는거 아닌가요? 화면을 다시 킬 때도 유지해야하니까 그 때 미리 불러와야하는.. 그런 생각으로 저기에 넣은건데... 틀린건가요? 알 수 없는 사용자 2018.6.19 15:16
  • ISharedPreferences prefs = Application.Context.GetSharedPreferences("Test", FileCreationMode.Private); prefs.GetString("Test_Data", ""); 이 부분을 말씀하시는 거라면 Test_Data 라는 Key 의 값을 가져오기만 하고 Spinner 에 해당 값으로 세팅하는 부분은 없네요 ㅎㅎ 알 수 없는 사용자 2018.6.19 15:19
  • 어.. 그럼 어떻게 해야하는거죠... ㅠ 그 부분의 추가로 " SpinnerName.SetSelection" 인가 ... 그거 하면 될까요? 알 수 없는 사용자 2018.6.19 15:19
  • _BG_Position.SetSelection(prefs.GetString("Test_Data", "")); 이 문장을 추가하면, string을 int로 바꿀 수 없다는 에러가 발생하는데 저는 분명 put에서도 string으로 받았는데 왜 이러는걸까요? 알 수 없는 사용자 2018.6.19 15:23
  • setSelection() 함수 매개변수가 아마 int 일 것으로 보이는데, Spinner 에 선택 된 index 자체를 putInt 로 넣어서 getInt 로 가져오는 방법이 있겠네요. 알 수 없는 사용자 2018.6.19 15:26
  • 흠.. 그 방법을 해봤긴한데, 그게 제가 잘 몰라서 방법을 맞게했는지 틀리게했는지 조차도 모르겠네요 ㅋㅋ 알 수 없는 사용자 2018.6.19 15:29
  • 예제 코드 첨부해볼게요 알 수 없는 사용자 2018.6.19 15:35
  • 아, 네. 제가 했던 방법은 Spinner 부분에서 int selection = _BG_Position.getSelectedItemPosition() 해서 int로 받아온건데 여기서 getSelectedItemPosition부분이 에러가 발생하더라구요.. 그래서 SelectedItemPosition으로 하면 실행하고 난 후에 불러오는데서 에러가 발생합니다 ㅠ 알 수 없는 사용자 2018.6.19 15:38

2 답변

  • 
    //preference 값 가져와서 spinner 에 설정
    val pref = getSharedPreferences("pref", Context.MODE_PRIVATE)
    spinner.setSelection(pref.getInt("spinnerSelectedPosition", 0))
    
    //preference 에 값 저장하기
    spinner.setOnItemClickListener { parent, view, position, id ->
         val editor = getSharedPreferences("pref", Context.MODE_PRIVATE).edit()
         editor.putInt("spinnerSelectedPosition", position)
         editor.apply()
    }
    

    대충 위와같은 형태가 될 것이구요.

    pref.getInt("spinnerSelectedPosition", 0)
    

    여기서 getInt() 두번째 인자값은 기본 값이며 preference 에 해당 값이 없을때 자동으로 설정되는 값입니다.

    • (•́ ✖ •̀)
      알 수 없는 사용자
    • 이걸 Xamarin 나름대로 editor.PutInt("Test_Data", e.Position); 로 수정해서 해보니까 이런 오류가 발생합니다. ㅠㅠ 저번 줌 화면도 그렇게 이번것도 그렇게 왜이러는지.. 참 ㅠJava.Lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer 알 수 없는 사용자 2018.6.19 15:45
    • putInt() 호출 할때 발생하는건 아닌것 같은데, 에러가 발생하는 라인이 어디인가요? 알 수 없는 사용자 2018.6.19 15:54
    • pistolcaffe님께서 올려주신 예제에서는 spinner.setSelection(pref.getInt("spinnerSelectedPosition", 0)) 이 부분이겠네요 제 코드 상으로는 public override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); ISharedPreferences prefs = Application.Context.GetSharedPreferences("Test", FileCreationMode.Private); _BG_Position.SetSelection(prefs.GetInt("Test_Data", 0)); // Create your fragment here } 이부분 알 수 없는 사용자 2018.6.19 16:16
    • 제가 생각하기에는 지금 불러오는 곳을 Spinner에 대한 선언보다 위에서 해주고 있어서 그런게 아닐까 하는데, 그렇다고 아래로 내려버리자니 그럼 더 의미가 없고.. ListVIew에서 다른 곳을 열었을 때는 별 문제가 없는데 저 Spinner가 들어있는 프레그먼트만 열면 에러가 나네요 알 수 없는 사용자 2018.6.19 16:20
    • 다시해보니 그건 아닌것 같네요.. 그냥 뭐가 뭔지. 어후 ㅠㅠ 알 수 없는 사용자 2018.6.19 16:22
    • setSelection(int position) 에 prefs.getInt() 로 불러 와서 넣는데 왜 ClassCastException 가 발생하는지 모르겠네요;; 제가 xamarin 은 다뤄보질 않아서 그러는데 exception 발생한 정확한 라인수를 알수 없나요? 알 수 없는 사용자 2018.6.19 16:28
    • 아쉽게도.. 정확한 라인수를 알 수가 없네요. 근데 이게 지금 몇번을 발목잡는지 모르겠어요 저도 아까 이거와 유사한 방법으로 했을 때, 방금 에러때문에 이게 아닌가부다 싶어서 질문을 올린건데... 하... 정말...ㅋㅋㅋ 알 수 없는 사용자 2018.6.19 16:31
    • 처음에 질문 올리신 코드 부분에 현재 코드 상황으로 바꿔서 올려주실수 있나요? 알 수 없는 사용자 2018.6.19 16:39
    • 잠시만요 이번에는 구글드라이브로 올려서 링크 걸어드릴게요 알 수 없는 사용자 2018.6.19 16:41
    • https://drive.google.com/file/d/16989Ps9AEGqE6MVrOw3jVShcyh8nmy0-/view?usp=sharing 입니다 알 수 없는 사용자 2018.6.19 16:42
    • 우선 ISharedPreferences prefs = Application.Context.GetSharedPreferences("Test", FileCreationMode.Private); _BG_Position.SetSelection(prefs.GetInt("Test_Data", 0)); 이부분 같은 경우에는 onCreate() 시점에선 _BG_Position 이 아직 할당 되기 전이라 에러가 발생할것 같긴해요. 근데 ClassCastException 이 발생한건 좀 의아하네요.. NullPointerException 이 발생할것 같은데.. 암튼 Fragment 생명주기 상 onCreate() 시점에선 아직 Fragment 의 contentview 가 만들어지기 전이기 때문에 onCreateView() 내에서 처리해주셔야 할것 같습니다. 알 수 없는 사용자 2018.6.19 17:11
    • 저도 그 생각에 onCreateView에 넣어보기도 했는데, 별반 다를게 없어요. 그래서 생각해봤던게 외부에 private로 차라리 다른 함수를 만들어서 호출을 하는 방식으로도 해볼까 했는데 역시 마찬가지더라구요.. 알 수 없는 사용자 2018.6.19 17:13
    • onCreateView 에 넣으실 땐 _BG_Position = (Spinner)_RD_OSBG.FindViewById(Resource.Id._BG_Position); 하고 나서 넣으신거구요? 알 수 없는 사용자 2018.6.19 17:18
    • 넵 ISharedPreferences prefs = Application.Context.GetSharedPreferences("Test", FileCreationMode.Private); 문장 뒤에 넣었어요 앞에 넣으면 prefs에 대한 인식을 못하더라구요... 알 수 없는 사용자 2018.6.19 17:23
    • 그런데 진짜 궁금한게 다른 외국 사이트보면 대부분이 int selectedPosition = yourSpinner.getSelectedItemPosition() 이런식으로 뒤에 저장할 데이터를 int로 만들던데 저는 왜 getSelectedItemPosition 이부분이 계속 에러가 뜨는걸까요; 자바에서만 통하는걸까요... 알 수 없는 사용자 2018.6.19 17:40
    • 음 글쎄요 그부분은 잘 모르겠지만.. xamarin 이라고 해서 해당 메소드를 지원안하거나 하진 않을거에요. 일단 저도 kotlin 환경에서 테스트코드를 좀 짜보고 말씀드릴게요 ㅋㅋ 알 수 없는 사용자 2018.6.19 17:46
    • 네 ㅠ 정말 감사합니다 이렇게까지 도와주셔서 ㅠ 꼭 해결을 보고 싶네요, 저도 안드로이드 스튜디오에서 한번 해봐야겠네요 정상적으로 된다면 Xamarin 측에 뭔가 문제가 있는걸수도 있으니 알 수 없는 사용자 2018.6.19 17:47
    • 답변 새로 올렸습니다. 참고하세요. 알 수 없는 사용자 2018.6.19 18:42
  • spinner 에 adapter 객체를 할당 한 후 setSelection 을 호출 해주세요. spinner 내부코드를 보니 adapter 가 할당 된 후 position 을 초기화 하는 로직이 있어서 이부분을 유의하셔야 할 것 같습니다. getSelectedItemPosition() 이 안된다는건 어느 부분에서 어떻게 안되신다는건지 잘 모르겠네요.. kotlin 에서 짜본 테스트 코드를 첨부합니다.

    const val KEY_LAST_SELECTED_POSITION = "last_selected_position"
    
    class TestFragment : Fragment() {
    
        private var currentSelectedPosition = Spinner.INVALID_POSITION
    
        override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
            return inflater.inflate(R.layout.fragment_content, container, false)
        }
    
        override fun onActivityCreated(savedInstanceState: Bundle?) {
            super.onActivityCreated(savedInstanceState)
    
            val adapter = ArrayAdapter.createFromResource(context, R.array.planets_array, android.R.layout.simple_spinner_item)
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
            testSpinner.adapter = adapter
    
            currentSelectedPosition = loadLastSelectedPosition()
            testSpinner.setSelection(lastSelectedPosition)
    
            testSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
                override fun onNothingSelected(parent: AdapterView<*>?) {
    
                }
    
                override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
                    if (currentSelectedPosition != position) {
                        saveLastSelectedPosition(position)
                        currentSelectedPosition = position
                    }
                }
            }
        }
    
        private fun loadLastSelectedPosition(): Int {
            return PreferenceManager.getDefaultSharedPreferences(context).getInt(KEY_LAST_SELECTED_POSITION, 0)
        }
    
        private fun saveLastSelectedPosition(position: Int) {
            PreferenceManager.getDefaultSharedPreferences(context).edit().putInt(KEY_LAST_SELECTED_POSITION, position).apply()
        }
    }
    
    • (•́ ✖ •̀)
      알 수 없는 사용자
    • 이렇게까지 해주셔서 정말 감사합니다 ㅠ 코틀린 코드다 보니 좀 오래봐야겠네요 ㅠ 일단 제대로 해보고 다시 연락드리겠습니다! 알 수 없는 사용자 2018.6.19 19:35
    • pistolcaffe 님 해결했습니다. 문제는 저 위에 님이 말씀하신 왜 이 오류가 발생하는지 모르겠다고 하셨던 부분을 좀 수정했는데, 그 부분에 이미 전에 String형식의 문장이 들어가있어서 int 형식이 들어올 수 없는거였어요. 그래서 Key값을 새로운걸로 바꿔서 Switch문에 각 부분마다 서로 다른 value 값을 보내도록 한다음에 switch문 바로 위에서 실행하니까 되네요! 알 수 없는 사용자 2018.6.20 10:08
    • https://drive.google.com/file/d/1XDACvCkypHgNhQpTmd_BIQDgl-e2yoF9/view?usp=sharing 이렇게 수정해서 해결했습니다! 알 수 없는 사용자 2018.6.20 10:10
    • 이제 Seekbar나 switch는 어떻게 해야할지 고민해야겠네요 ㅠ 알 수 없는 사용자 2018.6.20 10:10
    • Sekkbark switch 도 비슷한 맥락으로 처리하시면 크게 어려울점은 없어보이네요 ㅎ 알 수 없는 사용자 2018.6.20 11:02
    • 그런데 SeekBar는 아직 안해봣지만 Switch 같은 경우, 비슷하게 해서 SetChecked로 불러오라는데 SetChecked 메소드가 없어서 지금 미치겠네욬ㅋㅋ 뭐 이리 꼬이는게 많은지 ㅠ 알 수 없는 사용자 2018.6.20 11:07
    • switch.Checked 란게 있지 않나요? 알 수 없는 사용자 2018.6.20 11:21
    • 어우 죄송합니다 너무 늦게 확인했네요 Checked 라는게 있긴한데. _BG_Mark.Checked(prefs.GetBoolean("Switch_Test", false)); 이런식으로 작성하게 되면 메서드처럼 사용할 수 없다는 에러문구가 나옵니다! 알 수 없는 사용자 2018.6.20 15:43
    • _BG_Mrk.Checked = prefs.GetBoolean("Switch_Test",false)); 는 안되나요? 알 수 없는 사용자 2018.6.20 15:56
    • 마침 p님이 말씀하시기 전에 그거해서 에러 없는거 확인하고 실행해봣는데 , 되네요... 젠장?ㅋㅋㅋ 이제 Seekbar랑 리스트뷰 남았는데 비슷하게 하면 되겠죠? 알 수 없는 사용자 2018.6.20 15:59
    • 넵 맥락은 동일합니다 알 수 없는 사용자 2018.6.20 16:03
    • 도와주셔서 정말 감사합니다! SeekBar가 또 말썽이긴하지만 정말 너무너무 감사했습니다 ㅠㅠ 알 수 없는 사용자 2018.6.20 16:41
    • 네 도움이 되셨다면 답변 채택 부탁드리겠습니다 알 수 없는 사용자 2018.6.20 16:56
    • 넵 채택드렸습니다! 감사합니다! 알 수 없는 사용자 2018.6.20 17:07

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)