2011-08-25 25 views
5

Tôi đang cố gắng xây dựng ngăn phân tách dựa trên example code được cung cấp ở cuối tài liệu Android về Fragments, về cơ bản LinearLayout chứa hai đoạn (tất cả các chi tiết có thể tìm thấy ở trên) link):Các vấn đề khi chuyển đổi ListView ChoiceMode trên xoay màn hình

  • TitlesFragment để hiển thị một danh sách các tiêu đề
  • DetailsFragment để hiển thị các chi tiết của tiêu đề hiện đang được chọn

vấn đề của tôi là unexp sau hành vi ected xảy ra:

  1. tôi khởi động ứng dụng trong Cảnh định hướng: danh sách các chức danh sẽ được hiển thị ở bên trái và các chi tiết của tiêu đề hiện đang được chọn (người đầu tiên ngay từ đầu) được hiển thị ở bên phải.
  2. Tôi chọn mục X từ danh sách tiêu đề: tiêu đề sẽ được đánh dấu vì ListView được đặt thành CHOICE_MODE_SINGLE và các mục của nó triển khai giao diện Checkable.
  3. Tôi chuyển sang Chân dung hướng (bằng cách xoay thiết bị hoặc trình mô phỏng): như mong đợi, chỉ danh sách tiêu đề được hiển thị và không có mục nào được chọn trong cấu hình này, vì ListView được tạo lại và theo mặc định, nó được đặt đến CHOICE_MODE_NONE.
  4. Tôi chọn mục Y từ danh sách tiêu đề: như dự kiến, hoạt động chỉ hiển thị DetailsFragment tương ứng với lựa chọn được thực hiện được hiển thị.
  5. tôi chuyển về Cảnh định hướng (đây là nơi mà các hành vi bất ngờ xảy ra): các DetailsFragment bên phải một cách chính xác cho thấy các chi tiết của mục Y (được chọn theo hướng dọc) nhưng TitlesFragment vẫn cho thấy mục X như được chọn (tức là đã chọn trước khi xoay màn hình đầu tiên).

Tất nhiên, tôi muốn lựa chọn cuối cùng được thực hiện theo hướng dọc cũng được hiển thị chính xác trong TitlesFragment, nếu không tôi sẽ kết thúc với mục nổi bật không hiển thị mục X như được chọn trong khi hiển thị chi tiết của mục Y.

tôi gửi mã có liên quan nơi chế độ ListView được thay đổi (trong vòng 'onActivityCreated') và mục đã chọn được thiết lập (trong phương pháp 'showDetails'):

public static class TitlesFragment extends ListFragment { 
boolean mDualPane; 
int mCurCheckPosition = 0; 

@Override 
public void onActivityCreated(Bundle savedInstanceState) { 
    super.onActivityCreated(savedInstanceState); 

    // Populate list with our static array of titles. 
    setListAdapter(new ArrayAdapter<String>(getActivity(), 
      android.R.layout.simple_list_item_activated_1, Shakespeare.TITLES)); 

    // Check to see if we have a frame in which to embed the details 
    // fragment directly in the containing UI. 
    View detailsFrame = getActivity().findViewById(R.id.details); 
    mDualPane = detailsFrame != null && detailsFrame.getVisibility() == View.VISIBLE; 

    if (savedInstanceState != null) { 
     // Restore last state for checked position. 
     mCurCheckPosition = savedInstanceState.getInt("curChoice", 0); 
    } 

    if (mDualPane) { 
     // In dual-pane mode, the list view highlights the selected item. 
     getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); 
     // Make sure our UI is in the correct state. 
     showDetails(mCurCheckPosition); 
    } 
} 

@Override 
public void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 
    outState.putInt("curChoice", mCurCheckPosition); 
} 

@Override 
public void onListItemClick(ListView l, View v, int position, long id) { 
    showDetails(position); 
} 

/** 
* Helper function to show the details of a selected item, either by 
* displaying a fragment in-place in the current UI, or starting a 
* whole new activity in which it is displayed. 
*/ 
void showDetails(int index) { 
    mCurCheckPosition = index; 

    if (mDualPane) { 
     // We can display everything in-place with fragments, so update 
     // the list to highlight the selected item and show the data. 
     getListView().setItemChecked(index, true); 

     // Check what fragment is currently shown, replace if needed. 
     DetailsFragment details = (DetailsFragment) 
       getFragmentManager().findFragmentById(R.id.details); 
     if (details == null || details.getShownIndex() != index) { 
      // Make new fragment to show this selection. 
      details = DetailsFragment.newInstance(index); 

      // Execute a transaction, replacing any existing fragment 
      // with this one inside the frame. 
      FragmentTransaction ft = getFragmentManager().beginTransaction(); 
      ft.replace(R.id.details, details); 
      ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); 
      ft.commit(); 
     } 

    } else { 
     // Otherwise we need to launch a new activity to display 
     // the dialog fragment with selected text. 
     Intent intent = new Intent(); 
     intent.setClass(getActivity(), DetailsActivity.class); 
     intent.putExtra("index", index); 
     startActivity(intent); 
    } 
} 

có ai có một ý tưởng về cách để giải quyết vấn đề như vậy? Cảm ơn trước.

+0

Tôi biết nó là hơi muộn , nhưng tôi có chính xác hành vi tương tự. Tôi đang thử nghiệm mã trong một thiết bị thực, một máy tính bảng có API 16 được cài đặt. Tôi đặt dấu vết và có thể thấy rằng trong 'showDetails (index)', chỉ mục là chính xác, nhưng 'setItemChecked (index, true)' không làm nổi bật tiêu đề chính xác. – eternay

Trả lời

-2

Nếu bạn đặt android:configChanges="orientation" trong thẻ hoạt động của mình trong tệp kê khai, ứng dụng của bạn sẽ bỏ qua phép xoay nhưng vẫn hiển thị bố cục có liên quan.

+0

Cảm ơn bạn đã trả lời nhanh. Tôi đã nhận thức được tính năng như vậy, nhưng đó không phải là hành vi dự định. Thật vậy, tôi muốn hoạt động nhận thức được sự thay đổi định hướng, vì chỉ tiêu đề phải được hiển thị theo hướng dọc, trong khi tiêu đề và chi tiết phải được hiển thị theo hướng ngang. Bạn có đề xuất nào về cách đạt được điều này không? – Luke

0

Có thể bạn nên đặt giá trị outState TRƯỚC KHI bạn gọi super.onSaveInstanceState?

@Override 
public void onSaveInstanceState(Bundle outState) { 
    outState.putInt("curChoice", mCurCheckPosition); 
    super.onSaveInstanceState(outState); 
} 
+0

Cảm ơn bạn một lần nữa, nhưng tiếc là điều đó KHÔNG giải quyết được vấn đề của tôi. Có vẻ như trường 'mCheckStates' của ListView đang giữ các giá trị được đặt thời gian cuối cùng mà 'CHOICE_MODE_SINGLE' được đặt, trong khi bất kỳ lựa chọn nào được thực hiện trong khi 'CHOICE_MODE_NONE' được đặt sẽ bị hủy. Hơn nữa, tôi nhận thấy rằng nếu tôi giữ ListView trong 'CHOICE_MODE_SINGLE' (bằng cách bình luận ra 'if (mDualPane)' ở cuối 'onActivityCreated'), lựa chọn cuối cùng được lưu và phục hồi chính xác khi thay đổi hướng màn hình. Nhưng tôi không muốn làm nổi bật ở hướng Chân dung ... Bất kỳ ý tưởng nào khác? – Luke

+1

Có vẻ như giả thuyết của tôi là chính xác, tức là các lựa chọn được thực hiện trong 'CHOICE_MODE_NONE' không ảnh hưởng đến trường 'mCheckStates' của ListView, điều này có vẻ hợp lý ở một mức độ nào đó. Giả thuyết của tôi được hỗ trợ bởi thực tế là tôi đã tìm thấy cách giải quyết sau (khủng khiếp): nếu tôi thêm các dòng mã sau: getListView(). SetChoiceMode (ListView.CHOICE_MODE_SINGLE); getListView(). SetItemChecked (chỉ mục, đúng); getListView(). SetChoiceMode (ListView.CHOICE_MODE_NONE); ở đầu phương thức 'khác' của phương thức 'showDetails', mọi thứ đều hoạt động tốt. Tôi chắc chắn phải có một giải pháp sạch hơn ... – Luke

+0

Tôi đã thử nghiệm mã mẫu từ SDK phiên bản 13 trên máy tính bảng chạy 3.1 và hoạt động tốt. Tôi đã không nhận được hành vi không chính xác. Có lẽ giả lập của bạn cần được cập nhật? – Mullins

2

Hai năm sau, ở đây tôi đang làm việc với mẫu Bố cục phân đoạn từ thư viện hỗ trợ v4 của Android và tôi gặp vấn đề tương tự chính xác này!

Dưới đây là sửa chữa duy nhất mà tôi đã đưa ra mà không yêu cầu sử dụng CHOICE_MODE_SINGLE tất cả các thời gian:

chỉ cần thêm một cuộc gọi đến getListView().setItemChecked(mCurCheckPosition, true); trong phương pháp onResume() của TitlesFragment. Và ... đó là nó!

0

Tôi đã gặp phải vấn đề tương tự trên mã đó và như workaround tôi gọi setItemChecked trên onStart phương pháp:

@Override 
public void onStart() { 
    super.onStart(); 
    if (mDualPane) { 
     getListView().setItemChecked(mCurCheckPosition, true); 
    } 
} 

Hoặc như LearningNerd nói làm điều đó trong onResume()

Các vấn đề liên quan