ListView addHeaderView khiến vị trí tăng lên một?


97

Dưới đây là đoạn mã với ListView. Tôi đã thêm một Chế độ xem trống và Chế độ xem tiêu đề. Việc thêm headerView làm cho vị trí trong onItemClick được tăng lên một.

Vì vậy, nếu không có headerView, phần tử danh sách đầu tiên sẽ có vị trí 0, với headerView, vị trí của phần tử danh sách đầu tiên sẽ là 1!

Điều này gây ra lỗi trong bộ điều hợp của tôi, ví dụ: khi gọi getItem () và sử dụng một số phương pháp khác, hãy xem bên dưới. Điều kỳ lạ: Trong phương thức getView () của bộ điều hợp, phần tử danh sách đầu tiên được yêu cầu ở vị trí 0 ngay cả khi headerView được thêm vào !!

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    ListView list = (ListView) viewSwitcher.findViewById(R.id.list);
    View emptyView = viewSwitcher.findViewById(R.id.empty);
    list.setEmptyView(emptyView);

    View sectionHeading = inflater.inflate(R.layout.heading, list, false);
    TextView sectionHeadingTextView = (TextView) sectionHeading.findViewById(R.id.headingText);
    sectionHeadingTextView.setText(headerText);
    list.addHeaderView(sectionHeading);

    list.setAdapter(listAdapter);

    list.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            listAdapter.getItem(position);
            //Do something with it
        }
    });
}

Một số phương pháp bộ điều hợp:

@Override
public int getViewTypeCount() {
    return TYPE_COUNT;
}

@Override
public int getItemViewType(int position) {
    return (position < items.size()) ? ITEM_NORMAL : ITEM_ADVANCED;
}

    @Override
public Product getItem(int position) {
    return items.get(position);
}
@Override
public boolean areAllItemsEnabled() {
    return false;
}

@Override
public boolean isEnabled(int position) {
    return (position < items.size());
}

Đây có phải là hành vi bình thường khi thêm headerView không ?? Và làm thế nào để khắc phục các sự cố trong bộ điều hợp của tôi?


1
Câu hỏi của bạn đã có câu trả lời cho câu hỏi của tôi. +1
Shashank Degloorkar

Câu trả lời:


113

Tôi chỉ tình cờ gặp vấn đề này và cách tốt nhất dường như sử dụng ListView.getItemAtPosition(position)thay vì ListAdapter.getItem(position)ListViewphiên bản chiếm các tiêu đề, ví dụ: -

Làm điều này thay thế:

myListView.getItemAtPosition(position)

1
Quá đúng! onItemClickcho bạn parentmột lý do. Bạn có thể sử dụngparent.getItemAtPosition(position)
Brais Gabin.

3
Điều này thực sự không hoạt động với tôi trong khi sử dụng giải pháp bộ điều hợp được trang trí / wrapper @whuandroid thì không.
Dori

3
bạn cũng phải cast mục trong trường hợp này.
njzk2 23/12/13

Không hoạt động cho tôi ngay cả khi tôi truyền cha mẹ đến ListView. Tôi chỉ cần loại trừ vị trí == 0 ...
PawelP

Không làm việc cho tôi. AdapterViewcũng chỉ chuyển xuống listAdapter được thêm vào. return (adapter == null || position < 0) ? null : adapter.getItem(position);
philippe

31

Nếu bạn không quan tâm đến lần nhấp vào tiêu đề, hãy trừ số lần xem tiêu đề khỏi vị trí để lấy vị trí cho bộ điều hợp của bạn:

        listView.addHeaderView(inflater.inflate(
                R.layout.my_hdr_layout, null), null, false);
        listView.setAdapter(m_adapter);
        listView.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {
            position -= listView.getHeaderViewsCount();
            final MyObject object = m_adapter.getItem(position);

        }
    });

Đây nên là câu trả lời tốt nhất, tôi không quan tâm đến tiêu đề, tôi quan tâm đến listitem.
Ninja

Tôi nghĩ rằng giải pháp này không làm việc cho OS 7.0 mới nhất
sha

27

Nếu bạn thêm tiêu đề vào một mục ListViewđó sẽ trở thành mục đầu tiên trong danh sách. Bạn có thể bù đắp điều này bằng cách ghi đè getCount()để trả lại một mục ít hơn, nhưng đảm bảo bạn xử lý getItem(), getItemId()v.v. vì tiêu đề sẽ là mục ở vị trí 0.


6
Ghi đè getCount () để trả lại một mục ít hơn không hoạt động, vì sau đó tôi bỏ lỡ mục danh sách cuối cùng của danh sách. Nếu chỉ có 1 mục trong danh sách thì getView () không bao giờ được gọi. Hơn nữa, bộ điều hợp được tách ra khỏi listview và không biết liệu có một tiêu đề được thêm vào listview hay không.
d1rk

2
Trong ListItemClick set position = vị trí - 1 nếu có một tiêu đề kèm theo, tôi nghĩ rằng thats những gì tôi đã làm khi tôi phải đối mặt với vấn đề cụ thể này, nó không phải là rất gọn gàng, nhưng cách duy nhất tôi có thể nghĩ đến
akshaydashrath

3
Tôi đoán cách dễ nhất là đặt position = position- (số lần xem tiêu đề được thêm vào) trong OnItemClickListener như bạn đã đề xuất. Tôi đã thay đổi bộ điều hợp của mình để xử lý chính chế độ xem tiêu đề, do đó tôi không phải gọi addHeaderView trên chế độ xem danh sách. Mặc dù bộ điều hợp phức tạp hơn một chút.
d1rk

22
"Số lần xem tiêu đề được thêm vào" có thể được lấy bằng:ListView.getHeaderViewsCount()
John

2
Tôi không thấy làm thế nào đây là câu trả lời đúng. @Ian Warwick đã đăng đúng, tuy nhiên tôi cho rằng hơi muộn.
sidon

14

Khi thực hiện, AdapterView.OnItemClickListenerchúng tôi chỉ trừ các tiêu đề khỏi vị trí.

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    position -= mListView.getHeaderViewsCount();
    // what ever else follows...
}

13

Không cần phải thay đổi bất kỳ mã nào. Đơn giản chỉ cần sử dụng mã dưới đây.

 list.setOnItemClickListener(new OnItemClickListener() {
     @Override
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
      parent.getAdapter().getItem(position);
         //Do something with it
     }
});

1
Điều này thường sẽ cần ép, vì mục được trả về chỉ là "Đối tượng".
nhà phát triển android

9

Không sử dụng bộ điều hợp của bạn, hãy sử dụng bộ điều hợp 'được trang trí' từ getAdapter.


+1 IMO này là cách để bắt đầu - bộ điều hợp bạn cung cấp được bọc bằng bộ điều hợp khác có tính đến phần bù chỉ số khi bạn cung cấp tiêu đề. Mã này cho việc này đang sử dụng được cung cấp bởi @Ramesh ở nơi khác trên trang này (+1 cho bạn!)
Dori

5

Một giải pháp cho điều này là ánh xạ id để lập chỉ mục. Về cơ bản, làm cho id trả về chỉ mục trong danh sách và trình nghe nhấp chuột sẽ làm:

public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            listAdapter.getItem((int) id);
}

3

Xin chào, chúng tôi có thể giải quyết vấn đề này theo cách này trước tiên bạn tạo dạng xem tiêu đề của mình, sau khi đưa vào danh sách của bạn và bước cuối cùng không thể setOnClickListener. nó hoạt động cho tôi. chào mừng mọi phản hồi

ViewGroup headerView = (ViewGroup) getLayoutInflater().inflate(R.layout.your_header, list,false);
list.addHeaderView(headerView);
headerView.setEnabled(false);
headerView.setOnClickListener(null);

Đó là danh sách các câu trả lời, nhưng điều này thực sự hữu ích. Nếu bạn không thực hiện những thay đổi này, thì chế độ xem tiêu đề của bạn sẽ vẫn có thể nhấp được, với các hiệu ứng gợn sóng, v.v.
Scott Ferguson

0

Không phải thêm nhiều điều mới mà @Ramesh đã không thêm nhưng một số ngữ cảnh bổ sung:

personList.setOnItemClickListener(new OnItemClickListener() {
    @SuppressWarnings("unchecked")
    public void onItemClick( AdapterView<?> parent, View view, int position, long duration) {
        Map<String, Object> person = (Map<String, Object>) parent.getAdapter().getItem(position);
        if (person != null){

            // If the header was clicked on a null  is returned

            OnPersonUiChangeListener listener = (OnPersonUiChangeListener) getActivity();
            listener.onSelectedPersonChanged(person);
        }
    }
});

0

Sử dụng getSelectedItemPosition () Trả lại vị trí của mục hiện được chọn trong tập dữ liệu của bộ điều hợp. Phương pháp này không cần phải lo lắng về kích thước của đầu trang hoặc chân trang.


0

Điều này có thể giúp ích cho ai đó, cải thiện câu trả lời của Farid_z và Philipp, chúng ta có thể áp dụng chính xác setItemChecked và setTitle với một cái gì đó như thế này

        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
        position += 1;
        mDrawerList.setItemChecked(position, true);
        mDrawerList.setSelection(position);
        position -= 1;
        setTitle(mNavigationDrawerItemTitles[position]);
        mDrawerLayout.closeDrawer(mDrawerList);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.