在ListView Android中快速滚动时崩溃

时间:2018-07-15 07:51:32

标签: android android-studio listview fastscroll

我有一个列表视图,滚动时,列表视图中间的项目被放大并且其颜色改变。 但是我有一个问题,当我快速滚动时会崩溃。 我的代码位于下面。 谁能告诉我是什么引起了这个问题? 谢谢

myActivity.java

public class myActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_entekhb_zaman);


       txtday=(TextView)findViewById(R.id.txtday);
       txtdayok=(TextView)findViewById(R.id.txtdayok);
       listviewday = (ListView) findViewById(R.id.listday);

       listday.add("");
       listday.add("1");
       listday.add("2");
       listday.add("3");
       listday.add("4");
       listday.add("");

       adapterday=new Custom_List_Day(this,android.R.layout.simple_list_item_1,listday);
       listviewday.setAdapter(adapterday);


        listviewday.setOnScrollListener(new AbsListView.OnScrollListener() {

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            // TODO Auto-generated method stub
            if (scrollState == SCROLL_STATE_IDLE) {
                View itemView = view.getChildAt(0);
                int top = Math.abs(itemView.getTop());
                int bottom = Math.abs(itemView.getBottom());
                int scrollBy = top >= bottom ? bottom : -top;
                if (scrollBy == 0) {
                    return;
                }
                smoothScrollDeferred(scrollBy, (ListView)view);
            }
        }

        private void smoothScrollDeferred(final int scrollByF,
                                          final ListView viewF) {
            final Handler h = new Handler();
            h.post(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    viewF.smoothScrollBy(scrollByF, 200);
                }
            });
        }

        @Override
        public void onScroll(AbsListView arg0, int firstVisibleItem, int visibleItemCount, int totalItemCount){
            Log.i("Scroll","first "+firstVisibleItem+", visibleItemCount "+visibleItemCount+",totalCount "+totalItemCount);
            int center = firstVisibleItem+(visibleItemCount)/2 ;
            if(currentLargedPosition != center){
                enlargeMiddleView(currentLargedPosition-firstVisibleItem, center-firstVisibleItem);
                currentLargedPosition = center;
                txtdayok.setText(listday.get(currentLargedPosition));
            }

        }
    });


     }

void enlargeMiddleView(int oldPosition, int newPosition){

    // get enlarged view and make it return default size
    TextView newTextView = (TextView)listviewday.getChildAt(oldPosition).findViewById(R.id.txtday3);
    newTextView.setTextSize(22);
    newTextView.setTextColor(getResources().getColor(R.color.white));


    // get the current center view and make it bigger
    TextView oldTextView = (TextView)listviewday.getChildAt(newPosition).findViewById(R.id.txtday3);
    oldTextView.setTextSize(28);
    oldTextView.setTextColor(getResources().getColor(R.color.sormeii));
}
}

Custom_List_Day

public class Custom_List_Day extends ArrayAdapter<String> {

private final Activity context;
private final ArrayList<String> name;
private final int resource;


public Custom_List_Day(Activity context,int resource, ArrayList<String> name) {
    super(context, resource, name);

    this.context = context;
    this.name = name ;
    this.resource=resource;


}
@Override
public int getCount() {
    // TODO Auto-generated method stub
    return name.size();
}

@Override
public long getItemId(int position) {
    // TODO Auto-generated method stub
    return position;
}

@Override
public int getViewTypeCount() {
    return super.getViewTypeCount();
}



public View getView(int position, View convertView, ViewGroup parent) {


    LayoutInflater infalter = context.getLayoutInflater();


    View rowLayout = null;




    if (convertView == null) {
        // inflating the row

        rowLayout =  infalter.inflate(this.resource, parent,false);


    } else {
        rowLayout = convertView;
    }


    TextView txtName = (TextView) rowLayout.findViewById(R.id.txtday3);

    txtName.setText(name.get(position));

    return rowLayout ;
}
}

list_day.xml

  <LinearLayout android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:background="@color/colorPrimary"
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:padding="4dp">


    <TextView
        android:id="@+id/txtday3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="شنبه - ۹خرداد"
        android:textColor="@color/white"
        android:textSize="22sp"/>

     </LinearLayout>

当我缓慢滚动时,我没有问题,程序正常运行。 但是当我快速滚动时,程序崩溃了。 logcat错误

07-15 12:32:45.607 14920-14920/anjam.carno E/AndroidRuntime: FATAL EXCEPTION: main
                                                         Process: anjam.carno, PID: 14920
                                                         java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference
                                                             at anjam.carno.ActivityEntekhabZaman.enlargeMiddleView2(ActivityEntekhabZaman.java:232)
                                                             at anjam.carno.ActivityEntekhabZaman$2.onScroll(ActivityEntekhabZaman.java:189)
                                                             at android.widget.AbsListView.invokeOnItemScrollListener(AbsListView.java:1519)
                                                             at android.widget.AbsListView.trackMotionScroll(AbsListView.java:5245)
                                                             at android.widget.AbsListView$FlingRunnable.run(AbsListView.java:4668)
                                                             at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
                                                             at android.view.Choreographer.doCallbacks(Choreographer.java:580)
                                                             at android.view.Choreographer.doFrame(Choreographer.java:549)
                                                             at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
                                                             at android.os.Handler.handleCallback(Handler.java:739)
                                                             at android.os.Handler.dispatchMessage(Handler.java:95)
                                                             at android.os.Looper.loop(Looper.java:135)
                                                             at android.app.ActivityThread.main(ActivityThread.java:5910)
                                                             at java.lang.reflect.Method.invoke(Native Method)
                                                             at java.lang.reflect.Method.invoke(Method.java:372)
                                                             at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1405)
                                                             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1200)

2 个答案:

答案 0 :(得分:1)

首先,我建议您阅读Standing coding guidelines for android。它将提高您的编码标准。

第二,您需要删除处理程序。从您的代码来看,您想将ListView对齐到中间。请查看RecyclerView。如果您想在中间添加快照,则此链接Linear Snap Helper将为您提供帮助。

但是,如果您想修改代码,建议您进行以下更改

    listviewday.setOnScrollListener(new AbsListView.OnScrollListener()
    {

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState)
        {
            // TODO Auto-generated method stub
            if (scrollState == SCROLL_STATE_IDLE)
            {
                View itemView = view.getChildAt(0);
                int top = Math.abs(itemView.getTop());
                int bottom = Math.abs(itemView.getBottom());
                int scrollBy = top >= bottom ? bottom : -top;
                if (scrollBy == 0)
                {
                    return;
                }

                view.smoothScrollBy(scrollBy, 200);
            }
        }

        @Override
        public void onScroll(AbsListView arg0, int firstVisibleItem, int visibleItemCount, int totalItemCount)
        {
            if (visibleItemCount != 0)
            {
                if (oldTextView != null)
                {
                    oldTextView.setTextSize(22);
                    oldTextView.setTextColor(Color.WHITE);
                    oldTextView = null;
                }

                final int midPosition = visibleItemCount - (visibleItemCount / 2);
                final TextView listItem = (TextView) listviewday.getChildAt(midPosition - 1).findViewById(R.id.txtday3);
                listItem.setTextSize(26);
                listItem.setTextColor(Color.BLACK);

                oldTextView = listItem;
            }

        }
    });

答案 1 :(得分:0)

IMO,200毫秒的延迟是导致崩溃的原因。

更改

if(currentLargedPosition != center){
    enlargeMiddleView(currentLargedPosition-firstVisibleItem, center-firstVisibleItem);
    currentLargedPosition = center;
    txtdayok.setText(listday.get(currentLargedPosition));
}

onScroll

new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(210);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if(currentLargedPosition != center){
                            enlargeMiddleView(currentLargedPosition-firstVisibleItem, center-firstVisibleItem);
                            currentLargedPosition = center;
                            txtdayok.setText(listday.get(currentLargedPosition));
                        }
                    }
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }).start();

当然,在滚动时好像应用程序滞后了。但这是我能想到的唯一方法,而无需更改您的核心逻辑。另外,这只是一个理论,我不确定100%会奏效。