0

我正在使用ParseQueryAdapter將數據加載到我的列表視圖中。我使用listview進行某種聊天。但是當我滾動ListView時,它完全混淆了佈局。 下面是截圖如何從一開始聊天的樣子,加載所有數據剛過: Chat from the begininngListView更改並刪除滾動視圖

,這是它的外觀後,我把它的滾動向上和向下幾次: Chat after scroll

我有已經看到類似的問題和答案,如:「用戶ViewHolder模式」但我從一開始就使用它,這沒有幫助。此外,我做了一個ListView match_parent的寬度和高度,因爲我看到包裝內容混亂了開始觀看項目。

我假設我的問題可以在AsyncTask中,因爲它是我設置ListView項目的地方。這裏是適配器的代碼:

public class ChatParseQueryAdapter extends ParseQueryAdapter<Message> { 
    Activity activity; 

    String lighterID; 
    String lighterColor; 

    public ChatParseQueryAdapter(Context context, final String lighterID, String lighterColor){ 
     super(context, new QueryFactory<Message>() { 
      @Override 
      public ParseQuery<Message> create() { 
       ParseQuery<Message> query = new ParseQuery<>("Message"); 
       query.orderByAscending("createdAt"); 
       query.whereEqualTo("lighter", ParseObject.createWithoutData("Lighter", lighterID)); 
       query.include("user"); 
       return query; 
      } 
     }); 
     activity = (Activity) context; 

     this.lighterID = lighterID; 
     this.lighterColor = lighterColor; 
    } 

    @Override 
    public View getItemView(Message message, View v, ViewGroup parent) { 
     final ViewHolder viewHolder; 
     if (v == null){ 
      v = View.inflate(getContext(), R.layout.message_list_item, null); 

      viewHolder = new ViewHolder(); 

      viewHolder.messageDate = (TextView) v.findViewById(R.id.message_date); 
      viewHolder.otherUserImage = (ImageView) v.findViewById(R.id.message_other_user_image); 
      viewHolder.otherUserName = (TextView) v.findViewById(R.id.message_other_user_name); 
      viewHolder.messageTextLayout = (RelativeLayout) v.findViewById(R.id.message_text_layout); 
      viewHolder.messageText = (TextView) v.findViewById(R.id.message_text); 
      viewHolder.messageImage = (ImageView) v.findViewById(R.id.message_picture); 
      viewHolder.userImage = (ImageView) v.findViewById(R.id.message_user_image); 
      viewHolder.userName = (TextView) v.findViewById(R.id.message_user_name); 

      v.setTag(viewHolder); 
     } else { 
      viewHolder = (ViewHolder) v.getTag(); 
     } 

     new GetMessage(viewHolder).execute(message); 



     return super.getItemView(message, v, parent); 
    } 

    static class ViewHolder { 
     TextView messageDate; 
     ImageView otherUserImage; 
     TextView otherUserName; 
     RelativeLayout messageTextLayout; 
     TextView messageText; 
     ImageView messageImage; 
     ImageView userImage; 
     TextView userName; 
    } 

    class GetMessage extends AsyncTask<Message, Void, ChatMessage> { 
     ViewHolder viewHolder; 
     Resources resources; 

     public GetMessage(ViewHolder viewHolder){ 
      this.viewHolder = new ViewHolder(); 
      this.viewHolder = viewHolder; 

      resources = activity.getResources(); 
     } 

     @Override 
     protected ChatMessage doInBackground(Message... params) { 
      if (isCancelled()){ 
       cancel(true); 
       return null; 
      } 
      Message message = params[0]; 
      ChatMessage result = new ChatMessage(); 

      ParseUser messageAuthor = message.getUser(); 
      String userProfileID = null; 
      String userName = null; 
      if (messageAuthor != null) { 

       userProfileID = messageAuthor.getString("profileID"); 
       userName = messageAuthor.getString("name").toUpperCase(); 

      } 
      result.setIsOtherMessage(messageAuthor != AppDelegate.getUser()); 

      Bitmap bitmap = GraphicsHelper.getBitmap(userProfileID, messageAuthor, activity); 
      result.setUserImage(GraphicsHelper.getRoundedBitmap(bitmap)); 
      result.setUserName(userName); 
      String messageText = message.getContent(); 
      if (messageText != null){ 
       result.setMessage(messageText); 
      } else { 
       result.setMessageImage(getParseImage(message)); 
      } 


      SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yy"); 
      String date = simpleDateFormat.format(Date.parse(message.getCreatedAt().toString())); 
      result.setDate(date); 

      return result; 
     } 

     @Override 
     protected void onPostExecute(ChatMessage result) { 
      super.onPostExecute(result); 

      if (result != null && !isCancelled()){ 
       if (result.isOtherMessage()){ 
        viewHolder.userImage.setVisibility(View.GONE); 
        viewHolder.userName.setVisibility(View.GONE); 

//     Drawable drawable = resources.getDrawable(R.drawable.black_other_chat); 
        viewHolder.messageTextLayout.setBackgroundResource(R.drawable.black_other_chat); 
//     viewHolder.messageTextLayout.setBackground(drawable); 


        viewHolder.otherUserImage.setImageBitmap(result.getUserImage()); 
        viewHolder.otherUserName.setText(result.getUserName()); 
       } else { 
        viewHolder.otherUserImage.setVisibility(View.GONE); 
        viewHolder.otherUserName.setVisibility(View.GONE); 

//     Drawable drawable = activity.getResources().getDrawable(R.drawable.black_my_chat); 
        viewHolder.messageTextLayout.setBackgroundResource(R.drawable.black_my_chat); 
//     viewHolder.messageTextLayout.setBackground(drawable); 

        viewHolder.userImage.setImageBitmap(result.getUserImage()); 
        viewHolder.userName.setText(result.getUserName()); 
        viewHolder.messageText.setTextColor(GraphicsHelper.getAnotherColor(lighterColor, activity.getResources())); 
       } 
       String messageText = result.getMessage(); 
       if (messageText != null){ 
        viewHolder.messageDate.setText(result.getDate()); 
        viewHolder.messageImage.setVisibility(View.GONE); 
        viewHolder.messageText.setText(result.getMessage()); 
       } else { 
        viewHolder.messageDate.setVisibility(View.GONE); 
        viewHolder.messageText.setVisibility(View.GONE); 
        viewHolder.messageImage.setImageBitmap(result.getMessageImage()); 
       } 
      } 
     } 

     private Bitmap getParseImage (Message message){ 
      Bitmap bitmap = null; 
      byte[] imageByteArray; 
      if (message != null){ 
       ParseFile imageFile = (ParseFile) message.get("info"); 
       try { 
        imageByteArray = imageFile.getData(); 
        bitmap = BitmapFactory.decodeByteArray(imageByteArray, 0, imageByteArray.length); 
//     int dimension = GraphicsHelper.getSquareCropDimensionForBitmap(bitmap); 
//     bitmap = ThumbnailUtils.extractThumbnail(bitmap, dimension, dimension); 
       } catch (ParseException | NullPointerException e1) { 
//    e1.printStackTrace(); 
       } 
      } 
      return bitmap; 
     } 
    } 
} 

這是我的聊天片段代碼:

public class FragmentChat extends Fragment { 
    String lighterID; 
    String lighterColor; 

    ListView chatListView; 
    View globalView; 

    ChatParseQueryAdapter mainAdapter; 
    ApplicationInterface fragmentHolder; 

    public FragmentChat(String lighterID, String lighterColor){ 
     this.lighterID = lighterID; 
     this.lighterColor = lighterColor; 
    } 

    @Override 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 
     try { 
      fragmentHolder = (ApplicationInterface) activity; 
     } catch (ClassCastException e) { 
      throw new ClassCastException(activity.toString()); 
     } 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     View view = inflater.inflate(R.layout.fragment_chat, container, false); 

     globalView = view; 
     new SetUpChatTitle(view).execute(0); 

     chatListView = (ListView) view.findViewById(R.id.chat_list_view); 

//  chatListView.setOnScrollListener(new AbsListView.OnScrollListener() { 
//   @Override 
//   public void onScrollStateChanged(AbsListView view, int scrollState) { 
// 
//   } 
// 
//   @Override 
//   public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 
// 
//   } 
//  }); 

     mainAdapter = new ChatParseQueryAdapter(getActivity(), lighterID, lighterColor); 
     chatListView.setAdapter(mainAdapter); 


     RelativeLayout chatLayout = (RelativeLayout) view.findViewById(R.id.chat_layout); 
     chatLayout.setBackgroundColor(GraphicsHelper.getColor(lighterColor, getResources())); 

//  EditText chatInputMessage = (EditText) view.findViewById(R.id.chat_input_message); 
//  chatInputMessage.setBackgroundResource(R.drawable.round_corners_layout); 
//  GradientDrawable inputMessageDrawable = (GradientDrawable) chatInputMessage.getBackground(); 
//  inputMessageDrawable.setColor(getResources().getColor(R.color.white)); 
//  inputMessageDrawable.setStroke(4, GraphicsHelper.getAnotherColor(lighterColor, resources)); 
//  inputMessageDrawable.setCornerRadius(40); 
// 
//  Button sendMessageButton = (Button) view.findViewById(R.id.chat_send_message); 
//  sendMessageButton.setBackgroundResource(R.drawable.round_corners_layout); 
//  GradientDrawable sendMessageDrawable = (GradientDrawable) sendMessageButton.getBackground(); 
//  sendMessageDrawable.setColor(GraphicsHelper.getAnotherColor(lighterColor, resources)); 
//  sendMessageDrawable.setCornerRadius(30); 

     return view; 
    } 

    class SetUpChatTitle extends AsyncTask<Integer, Void, RankingItem> { 
     View view; 

     HorizontalScrollView chatTitleScrollView; 
     RelativeLayout lighterNameAndMilesLayout; 
     TextView rank; 
     TextView lighterName; 
     TextView milesTravelled; 
     ImageView userImage; 

     LinearLayout enterMessageLayout; 
     EditText chatInputMessage; 
     Button sendMessageButton; 
     ImageView attachPictureButton; 

     public SetUpChatTitle(View view){ 
      this.view = view; 

      chatTitleScrollView = (HorizontalScrollView) view.findViewById(R.id.chat_title_scroll_view); 
      lighterNameAndMilesLayout = (RelativeLayout) view.findViewById(R.id.chat_lighter_name_and_miles_layout); 
      rank = (TextView) view.findViewById(R.id.chat_rank_number); 
      lighterName = (TextView) view.findViewById(R.id.chat_lighter_name); 
      milesTravelled = (TextView) view.findViewById(R.id.chat_lighter_miles_travelled); 
      userImage = (ImageView) view.findViewById(R.id.chat_user_image); 

      enterMessageLayout = (LinearLayout) view.findViewById(R.id.chat_message_layout); 
      chatInputMessage = (EditText) view.findViewById(R.id.chat_input_message); 
      sendMessageButton = (Button) view.findViewById(R.id.chat_send_message); 
      attachPictureButton = (ImageView) view.findViewById(R.id.chat_attach_picture_button); 
     } 

     @Override 
     protected RankingItem doInBackground(Integer... params) { 
      if (isCancelled()){ 
       cancel(true); 
       return null; 
      } 

      RankingItem result = new RankingItem(); 

      ParseQuery<ParseObject> lighterQuery = ParseQuery.getQuery("Lighter"); 
      try { 
       Lighter lighter = (Lighter) lighterQuery.get(lighterID); 
       result.setLighterName(lighter.getLighterName().toUpperCase()); 
       result.setMilesTravelled(String.valueOf(lighter.getIntMiles()) + " MILES TRAVELLED"); 
       ParseUser lastUser = lighter.getMaster(); 
       String profileID = null; 
       if (lastUser != null) { 
        lastUser.fetchIfNeeded(); 
        profileID = lastUser.getString("profileID"); 
       } 
       Bitmap bitmap = GraphicsHelper.getBitmap(profileID, lastUser, getActivity()); 
       result.setUserImage(GraphicsHelper.getBitmapWithTineCircle(bitmap, getActivity())); 

       lighterQuery.whereGreaterThanOrEqualTo("miles", lighter.getDouble("miles")); 
       result.setRank("#" + lighterQuery.count()); 

       JSONArray userList = lighter.getJSONArray("users"); 

       String parseUserObjectId = AppDelegate.getUser().getObjectId(); 
       boolean userChat = false; 
       for (int i = 0; i < userList.length(); i++){ 
        if (userList.getJSONObject(i).getString("objectId").equals(parseUserObjectId)) { 
         userChat = true; 
        } 
       } 
       result.setUserChat(userChat); 
      } catch (ParseException | JSONException e) { 
       e.printStackTrace(); 
      } 

      return result; 
     } 

     @Override 
     protected void onPostExecute(RankingItem result) { 
      super.onPostExecute(result); 

      if (result != null && !isCancelled()){ 
       GraphicsHelper.setUpChatTitle(view, lighterColor, getActivity()); 

       lighterNameAndMilesLayout.getLayoutParams().width = GraphicsHelper.getScreenSize(getActivity()).x - FragmentMap.MARGIN; 
       chatTitleScrollView.setSmoothScrollingEnabled(true); 
       globalView.post(new Runnable() { 
        @Override 
        public void run() { 
         chatTitleScrollView.fullScroll(View.FOCUS_RIGHT); 
        } 
       }); 

       rank.setText(result.getRank()); 
       lighterName.setText(result.getLighterName()); 
       milesTravelled.setText(result.getMilesTravelled()); 
       userImage.setImageBitmap(result.getUserImage()); 

       final GestureDetector gestureDetector = new GestureDetector(
         new GestureDetectorTwoPositions(1, chatTitleScrollView)); 

       chatTitleScrollView.setOnTouchListener(new View.OnTouchListener() { 
        @Override 
        public boolean onTouch(View v, MotionEvent event) { 
         return gestureDetector.onTouchEvent(event); 
        } 
       }); 

       chatTitleScrollView.setVisibility(View.VISIBLE); 

       if (result.isUserChat()){ 
        Resources resources = getResources(); 

        chatInputMessage.setBackgroundResource(R.drawable.round_corners_layout); 
        GradientDrawable inputMessageDrawable = (GradientDrawable) chatInputMessage.getBackground(); 
        inputMessageDrawable.setColor(getResources().getColor(R.color.white)); 
        inputMessageDrawable.setStroke(4, GraphicsHelper.getAnotherColor(lighterColor, resources)); 
        inputMessageDrawable.setCornerRadius(40); 

        sendMessageButton.setBackgroundResource(R.drawable.round_corners_layout); 
        GradientDrawable sendMessageDrawable = (GradientDrawable) sendMessageButton.getBackground(); 
        sendMessageDrawable.setColor(GraphicsHelper.getAnotherColor(lighterColor, resources)); 
        sendMessageDrawable.setCornerRadius(30); 

        sendMessageButton.setOnClickListener(new View.OnClickListener() { 
         @Override 
         public void onClick(View v) { 
          String inputMessage = chatInputMessage.getText().toString().trim(); 
          if (TextUtils.isEmpty(inputMessage)) { 
           LoginActivity.showAlertDialog(getString(R.string.enter_the_message), getActivity()); 
          } else { 
           Message message = new Message(); 

           message.setUser(AppDelegate.getUser()); 
           message.setPublicReadWriteAcl(); 
           message.setLighter(ParseObject.createWithoutData("Lighter", lighterID)); 

           Location currentLocation = LocationInfo.getBestLocation(getActivity()); 
           ParseGeoPoint location = new ParseGeoPoint(currentLocation.getLatitude(), currentLocation.getLongitude()); 
           message.setLocation(location); 

           message.setContent(inputMessage); 
           message.setType(1d); 
           message.saveInBackground(new SaveCallback() { 
            @Override 
            public void done(ParseException e) { 
             mainAdapter.notifyDataSetChanged(); 
             chatListView.setAdapter(mainAdapter); 
            } 
           }); 
          } 
         } 
        }); 

        enterMessageLayout.setVisibility(View.VISIBLE); 
        attachPictureButton.setVisibility(View.VISIBLE); 
       } 
      } 
     } 

     public void receiveMessage(){ 

     } 
    } 
} 

,這是我的ListView XML代碼的樣子:

<ListView 
    android:id="@+id/chat_list_view" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:dividerHeight="0dp" 
    android:divider="@null" 
    android:stackFromBottom="true" 
    android:transcriptMode="alwaysScroll" 
    android:layout_marginBottom="@dimen/double_margin" 
    android:layout_below="@id/chat_title_scroll_view" 
    android:layout_above="@+id/chat_message_layout"/> 

謝謝你提前。

回答

1

試試這個: 在適配器類中重寫這兩個方法:

@Override 
    public int getViewTypeCount() { 

    return 1; 
    } 

    @Override 
    public int getItemViewType(int position) { 

    return position; 
    } 

你也可以看到這一點:List view items changes position when scrolling android?

編輯 Adater類的getItemView()方法一次又一次的被稱爲非常頻繁,並且您正在使用此方法調用您的asyncTask(運行緩慢),即不是好方法。您需要從片段類中調用asyncTask,然後從asynkTask的中調用適配器類。

+0

我已經試過兩種方法。您的代碼導致此錯誤: 嘗試在空對象引用 上調用虛擬方法'void android.widget.TextView.setText(java.lang.CharSequence)'並且鏈接中的代碼導致了此錯誤: java.lang.IllegalArgumentException :不能有一個viewTypeCount <1 但是,無論如何,謝謝 –

+0

我把'GetMessage' AsyncTask類的所有代碼移動到'getItemVIew'但行爲沒有改變。我使用的是'AsyncTask',因爲我無法從'Message'對象獲取所有數據,而且我必須從互聯網下載圖像,並且它在UI線程中被禁止。 但是我並沒有完全理解你希望我如何更改代碼,所以我只是試圖將所有內容從'AsynTask'移動到'getItemView'方法。如果你能更準確地解釋我會很感激。並感謝您的幫助 –