你好我的ListView有一个非常奇怪的故障:当我滚动时,列表的残像保持静止,就像视图出现两次一样,通常具有透明背景滚动而另一个保持静止静态,你看到另一个后面。这是它的外观:
我尝试做的是按照本教程实现字母列表视图:http://www.brightec.co.uk/ideas/android-listview-alphabet-scroller 它工作正常,然后我想提取代码并将其放在一个片段中,但它以相反的顺序显示,所以我按照这篇文章:Horizontal LinearLayout displaying components in reverse order并用RelativeLayout替换原始的LinearLayout,并且它在启动时表现得很奇怪。这是片段的xml代码:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/contacts_root"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:id="@+id/sideIndex"
android:layout_width="40dip"
android:layout_alignParentRight="true"
android:layout_height="fill_parent"
android:gravity="center_horizontal"
android:orientation="vertical" >
</LinearLayout>
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_marginRight="40dip"
android:layout_alignParentLeft="true"
android:layout_height="match_parent"
android:fastScrollEnabled="true"
android:cacheColorHint="@android:color/transparent"/>
</RelativeLayout>
这是我的活动代码:
public class MainActivity extends GlActivity {
IconTextMenu menu;
private GestureDetector mGestureDetector;
public void setmGestureDetector(GestureDetector mGestureDetector) {
this.mGestureDetector = mGestureDetector;
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("DEBUG", "MainActivity.onCreate()");
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.main_fragment, new ContactsFragment());
fragmentTransaction.commit();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mGestureDetector.onTouchEvent(event)) {
return true;
} else {
return false;
}
}
@Override
protected @Nullable @LayoutRes Integer getLayoutResource() {
return R.layout.activity_main;
}
@Override
protected void initializeData() {
super.initializeData();
menu = new IconTextMenu();
menu.add(new IconTextMenuEntry(R.drawable.icon_import_export, R.string.import_export));
menu.add(new IconTextMenuEntry(R.drawable.icon_tag, R.string.manage_tags));
menu.add(new IconTextMenuEntry(R.drawable.icon_settings, R.string.settings));
}
@Override
protected void initializeComponents() {
super.initializeComponents();
UiBuilder builder = new UiBuilder(this);
builder.buildDrawerMenu(R.id.main_menu, menu);
builder.buildToolbar(R.id.main_toolbar, R.id.main_drawer);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
((DrawerLayout) findViewById(R.id.main_drawer)).openDrawer(GravityCompat.START);
return true;
}
return super.onOptionsItemSelected(item);
}
}
我的片段代码:
public class ContactsFragment extends Fragment {
MainActivity context;
ListView listView;
private AlphabetListAdapter adapter = new AlphabetListAdapter();
private List<Object[]> alphabet = new ArrayList<Object[]>();
private HashMap<String, Integer> sections = new HashMap<String, Integer>();
private int sideIndexHeight;
private static float sideIndexX;
private static float sideIndexY;
private int indexListSize;
private class SideIndexGestureListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
// we know already coordinates of first touch
// we know as well a scroll distance
sideIndexX = sideIndexX - distanceX;
sideIndexY = sideIndexY - distanceY;
// when the user scrolls within our side index
// we can show for every position in it a proper
// item in the country list
if (sideIndexX >= 0 && sideIndexY >= 0) {
displayListItem();
}
return super.onScroll(e1, e2, distanceX, distanceY);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
this.context = (MainActivity) context;
}
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
Log.d("DEBUG", "ContactsFragment.onCreateView()");
View rootView = inflater.inflate(R.layout.activity_main_fragment_contacts, container, false);
return rootView;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
context.setmGestureDetector(new GestureDetector(context, new SideIndexGestureListener()));
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
listView = (ListView) view.findViewById(android.R.id.list);
List<String> countries = populateCountries();
Collections.sort(countries);
List rows = new ArrayList();
int start = 0;
int end = 0;
String previousLetter = null;
Object[] tmpIndexItem = null;
Pattern numberPattern = Pattern.compile("[0-9]");
for (String country : countries) {
String firstLetter = country.substring(0, 1);
// Group numbers together in the scroller
if (numberPattern.matcher(firstLetter).matches()) {
firstLetter = "#";
}
// If we've changed to a new letter, add the previous letter to the alphabet scroller
if (previousLetter != null && !firstLetter.equals(previousLetter)) {
end = rows.size() - 1;
tmpIndexItem = new Object[3];
tmpIndexItem[0] = previousLetter.toUpperCase(Locale.UK);
tmpIndexItem[1] = start;
tmpIndexItem[2] = end;
alphabet.add(tmpIndexItem);
start = end + 1;
}
// Check if we need to add a header row
if (!firstLetter.equals(previousLetter)) {
rows.add(new AlphabetListAdapter.Section(firstLetter));
sections.put(firstLetter, start);
}
// Add the country to the list
rows.add(new AlphabetListAdapter.Item(country));
previousLetter = firstLetter;
}
if (previousLetter != null) {
// Save the last letter
tmpIndexItem = new Object[3];
tmpIndexItem[0] = previousLetter.toUpperCase(Locale.UK);
tmpIndexItem[1] = start;
tmpIndexItem[2] = rows.size() - 1;
alphabet.add(tmpIndexItem);
}
adapter.setRows(rows);
listView.setAdapter(adapter);
updateList();
}
private List<String> populateCountries() {
List<String> countries = new ArrayList<>();
countries.add("Afghanistan");
countries.add("Albania");
countries.add("Bahrain");
countries.add("Bangladesh");
countries.add("Cambodia");
countries.add("Cameroon");
countries.add("Denmark");
countries.add("Djibouti");
countries.add("East Timor");
countries.add("Ecuador");
countries.add("Fiji");
countries.add("Finland");
countries.add("Gabon");
countries.add("Georgia");
countries.add("Haiti");
countries.add("Holy See");
countries.add("Iceland");
countries.add("India");
countries.add("Jamaica");
countries.add("Japan");
countries.add("Pakistan");
countries.add("Palau");
countries.add("Qatar");
countries.add("Romania");
countries.add("Russia");
countries.add("Saint Kitts and Nevis");
countries.add("Saint Lucia");
countries.add("Taiwan");
countries.add("Tajikistan");
countries.add("Uganda");
countries.add("Ukraine");
countries.add("Vanuatu");
countries.add("Venezuela");
countries.add("Yemen");
countries.add("Zambia");
countries.add("Zimbabwe");
countries.add("0");
countries.add("2");
countries.add("9");
return countries;
}
public void displayListItem() {
LinearLayout sideIndex = (LinearLayout) getView().findViewById(R.id.sideIndex);
sideIndexHeight = sideIndex.getHeight();
// compute number of pixels for every side index item
double pixelPerIndexItem = (double) sideIndexHeight / indexListSize;
// compute the item index for given event position belongs to
int itemPosition = (int) (sideIndexY / pixelPerIndexItem);
// get the item (we can do it since we know item index)
if (itemPosition < alphabet.size()) {
Object[] indexItem = alphabet.get(itemPosition);
int subitemPosition = sections.get(indexItem[0]);
listView.setSelection(subitemPosition);
}
}
public void updateList() {
LinearLayout sideIndex = (LinearLayout) getView().findViewById(R.id.sideIndex);
sideIndex.removeAllViews();
indexListSize = alphabet.size();
if (indexListSize < 1) {
return;
}
int indexMaxSize = (int) Math.floor(sideIndex.getHeight() / 20);
int tmpIndexListSize = indexListSize;
while (tmpIndexListSize > indexMaxSize) {
tmpIndexListSize = tmpIndexListSize / 2;
}
double delta;
if (tmpIndexListSize > 0) {
delta = indexListSize / tmpIndexListSize;
} else {
delta = 1;
}
TextView tmpTV;
for (double i = 1; i <= indexListSize; i = i + delta) {
Object[] tmpIndexItem = alphabet.get((int) i - 1);
String tmpLetter = tmpIndexItem[0].toString();
tmpTV = new TextView(context);
tmpTV.setText(tmpLetter);
tmpTV.setGravity(Gravity.CENTER);
tmpTV.setTextSize(15);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1);
tmpTV.setLayoutParams(params);
sideIndex.addView(tmpTV);
}
sideIndexHeight = sideIndex.getHeight();
sideIndex.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// now you know coordinates of touch
sideIndexX = event.getX();
sideIndexY = event.getY();
// and can display a proper item it country list
displayListItem();
return false;
}
});
}
}