在开头 - 滚动问题上动态添加和动画新的ListView项

时间:2014-08-14 09:15:16

标签: android listview animation listadapter

我有一个ListFragment,有一个简单的ListView。当WebSocket上有新消息时,我会动态地向此ListView添加新项。我将新行添加到ArrayAdapter的开头,添加新项目时会有一个简单的动画。

问题是,当动画正在进行时,我正在尝试滚动,只有当我快速滚动时,旧版项目才会在ListView上设置动画。

以下是ListAdapter

package adapters;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.ArrayList;

import custom_view.CompassView;
import hu.horadiz.ehoghu.blitzinfo.R;
import logger.AndroidLogger;
import model.BlitzLive;

/**
 * Created by ehog on 2014.08.13..
 */
public class LiveArrayAdapter extends ArrayAdapter<BlitzLive> {

    private ArrayList<BlitzLive> mLiveData;
    private Context mContext;
    private String[] mCompass;
    private Integer mRecentAddedIndex;
    private BlitzLive mRecentAdded;
    private boolean mRecentAnimated;

    private final static DateFormat DATE_FORMAT = new SimpleDateFormat("HH:MM:SS");


    public LiveArrayAdapter(Context context, ArrayList<BlitzLive> mLiveData) {
        super(context, 0, mLiveData);
        this.mLiveData = mLiveData;
        this.mContext = context;
        mCompass = mContext.getResources().getStringArray(R.array.compass);
    }

    @Override
    public synchronized void add(BlitzLive object) {
        mLiveData.add(0,object);
        if (mLiveData.size() > 120)
        {
            mLiveData.remove(mLiveData.size()-1);
        }
        mRecentAddedIndex = 0;
        mRecentAnimated = true;
        mRecentAdded = object;
        notifyDataSetChanged();
    }

    private String coords(Double lat, Double lng)
    {
        String latitude_text = lat >= 0 ? mCompass[0] : mCompass[8];
        String longitude_text = lng >= 0 ? mCompass[4] : mCompass[12];

        DecimalFormat nf = new DecimalFormat();
        DecimalFormatSymbols p=new DecimalFormatSymbols();
        p.setDecimalSeparator('.');
        nf.setDecimalFormatSymbols(p);

        nf.setMaximumFractionDigits(3);
        nf.setMinimumFractionDigits(3);

        return  String.format("%s %s, %s %s",nf.format(lat),latitude_text,nf.format(lng),longitude_text);
    }

    @Override
    public int getCount() {
        return mLiveData.size();
    }


    @Override
    public synchronized View getView(int i, View view, ViewGroup viewGroup) {
        if (view == null) {
            LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.holder_blitzes_live, null);
        }

        TextView settlem = (TextView)view.findViewById(R.id.live_settlem);
        TextView data = (TextView)view.findViewById(R.id.live_data);
        TextView distancemarker = (TextView)view.findViewById(R.id.live_distancemarker);

        DecimalFormat nf = new DecimalFormat();
        DecimalFormatSymbols p=new DecimalFormatSymbols();
        p.setDecimalSeparator('.');
        nf.setDecimalFormatSymbols(p);

        nf.setMaximumFractionDigits(2);
        nf.setMinimumFractionDigits(2);

        if (!mLiveData.get(i).Settlement.equals(""))
        {
            settlem.setText(mLiveData.get(i).Settlement);
            data.setText(String.format("%s km, %s (%s)", nf.format(mLiveData.get(i).Distance), mCompass[(int)((((mLiveData.get(i).Bearing + 11.0) / 22.5) % 16))],coords(mLiveData.get(i).Latitude,mLiveData.get(i).Longitude)));
        }
        else
        {
            settlem.setText(coords(mLiveData.get(i).Latitude,mLiveData.get(i).Longitude));
            data.setText(String.format("%s km, %s", nf.format(mLiveData.get(i).Distance), mCompass[(int)((((mLiveData.get(i).Bearing + 11.0) / 22.5) % 16))]));
        }
        CompassView compass = (CompassView)view.findViewById(R.id.live_compass);
        compass.setBaseBearing(new Float(mLiveData.get(i).Bearing));
        ImageView flag = (ImageView)view.findViewById(R.id.live_flag);
        if (mLiveData.get(i).CountryCode.equals("--"))
        {
            flag.setImageResource(mContext.getResources().getIdentifier(String.format("_cf_big_%s","empty"), "drawable", "hu.horadiz.ehoghu.blitzinfo"));
        }
        else
        {
            flag.setImageResource(mContext.getResources().getIdentifier(String.format("_cf_big_%s", mLiveData.get(i).CountryCode), "drawable", "hu.horadiz.ehoghu.blitzinfo"));
        }

        if (mLiveData.get(i).Distance >= 1000.0)
        {
            distancemarker.setBackgroundResource(R.drawable.groupedblitzes_count_background_1000plus);
        }
        else if (mLiveData.get(i).Distance >= 200.0 && mLiveData.get(i).Distance < 1000.0)
        {
            distancemarker.setBackgroundResource(R.drawable.groupedblitzes_count_background_200plus);
        }
        else if (mLiveData.get(i).Distance >= 50.0 && mLiveData.get(i).Distance < 200.0)
        {
            distancemarker.setBackgroundResource(R.drawable.groupedblitzes_count_background_50plus);
        }
        else if (mLiveData.get(i).Distance >= 20.0 && mLiveData.get(i).Distance < 50.0)
        {
            distancemarker.setBackgroundResource(R.drawable.groupedblitzes_count_background_20plus);
        }
        else if (mLiveData.get(i).Distance >= 5.0 && mLiveData.get(i).Distance < 20.0)
        {
            distancemarker.setBackgroundResource(R.drawable.groupedblitzes_count_background_5plus);
        }
        else if (mLiveData.get(i).Distance >= 0.0 && mLiveData.get(i).Distance < 5.0)
        {
            distancemarker.setBackgroundResource(R.drawable.groupedblitzes_count_background_0plus);
        }

        //This if is false when the wrong item is animates, but the animation is still occurs
        if (mRecentAddedIndex == i && mRecentAnimated && mRecentAdded.equals(mLiveData.get(i)))
        {
            mRecentAnimated = false;
            Animation ANIM_APPEAR = AnimationUtils.loadAnimation(getContext(), R.anim.push_right_in);
            ANIM_APPEAR.setDuration(500);
            view.findViewById(R.id.live_holder_parent).startAnimation(ANIM_APPEAR);
            AndroidLogger.PushDebugMessage("Animáció megtörtént: "+mRecentAddedIndex+" "+mLiveData.get(i).Settlement);
        }


        return view;
    }
}

ListFragment

package fragments;

import android.app.Fragment;
import android.app.ListFragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import org.json.JSONObject;

import java.util.ArrayList;

import adapters.LiveArrayAdapter;
import hu.horadiz.ehoghu.blitzinfo.R;
import logger.AndroidLogger;
import model.BlitzLive;
import using_net.BlitzLiveDataAsyncTask;

/**
 * Created by ehog on 2014.08.12..
 */
public class LiveDataFragment extends ListFragment implements BlitzLiveDataAsyncTask.OnMessage
{
    private BlitzLiveDataAsyncTask _mLiveAsyncTask;
    private LiveArrayAdapter mListAdapter;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View v = inflater.inflate(R.layout.fragment_live, container, false);
        return v;
    }

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        setHasOptionsMenu(true);
        super.onCreate(savedInstanceState);
        mListAdapter = new LiveArrayAdapter(getActivity(),new ArrayList<BlitzLive>());
        mListAdapter.setNotifyOnChange(true);
        setListAdapter(mListAdapter);
    }

    @Override
    public void onStart()
    {
        if (getActivity() != null)
        {
            getActivity().setTitle(getActivity().getResources().getString(R.string.title_liveview));
        }
        super.onStart();
        if (_mLiveAsyncTask != null)
        {
            _mLiveAsyncTask.cancel(true);
        }
        _mLiveAsyncTask = new BlitzLiveDataAsyncTask(this);
        _mLiveAsyncTask.execute();
    }

    @Override
    public void onPause() {
        super.onPause();
        if (_mLiveAsyncTask != null)
        {
            _mLiveAsyncTask.stop();
            _mLiveAsyncTask.cancel(true);
            AndroidLogger.PushDebugMessage("onPause cancel");
        }
    }

    @Override
    public void onCreateOptionsMenu (Menu menu, MenuInflater inflater)
    {
        menu.clear();
        inflater.inflate(R.menu.blitz_live, menu);
        super.onCreateOptionsMenu(menu, inflater);
    }


    @Override
    public void onMessage(final JSONObject message)
    {
        getActivity().runOnUiThread(new Runnable() {
            public void run() {
                ((LiveArrayAdapter)getListAdapter()).add(BlitzLive.fromJSON(message));
            }
        });

        AndroidLogger.PushDebugMessage(String.format("Websocket message: %s", message.toString()));
    }


}

2 个答案:

答案 0 :(得分:0)

是回收是问题所在。在适配器中添加动画时,必须放置一个&#34;删除动画代码&#34;:

 if (mRecentAddedIndex == i && mRecentAnimated && mRecentAdded.equals(mLiveData.get(i)))
        {
            mRecentAnimated = false;
            Animation ANIM_APPEAR = AnimationUtils.loadAnimation(getContext(), R.anim.push_right_in);
            ANIM_APPEAR.setDuration(500);
            view.findViewById(R.id.live_holder_parent).startAnimation(ANIM_APPEAR);
            AndroidLogger.PushDebugMessage("Animáció megtörtént: "+mRecentAddedIndex+" "+mLiveData.get(i).Settlement);
        } else {
// remove animation

答案 1 :(得分:0)

最终代码:(清理,动画最后等等)

if (mRecentAddedIndex == i && mRecentAnimated && mRecentAdded.equals(mLiveData.get(i)))
    {
        mRecentAnimated = false;
        layout.startAnimation(ANIM_APPEAR);
        AndroidLogger.PushDebugMessage("Animáció megtörtént (Animation occurred): "+mRecentAddedIndex+" "+mLiveData.get(i).Settlement);
    }
    else
    {
        layout.clearAnimation();
    }