Android: как передать ссылку на кнопку в адаптере для действия

Все,

У меня есть список, заполненный кнопками, которые запускают и останавливают таймер хронометра. Каждый таймер также устанавливается внутри каждой строки списка. Внутри активности у меня есть глобальная кнопка запуска и остановки. Эти кнопки должны останавливать и запускать все таймеры в списке. Кажется, я не могу получить ссылку на все таймеры в списке, чтобы остановить их. Я даже не могу получить ссылку на кнопки внутри каждой строки списка.

Ниже мой код. Пожалуйста помоги!

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="fill_parent"
android:layout_height="fill_parent">

<TextView android:layout_width="wrap_content" android:id="@+id/timerPositionName"
    android:layout_height="wrap_content" android:text="blocker" />

<TextView android:layout_width="wrap_content" android:id="@+id/timerTime"
    android:layout_height="wrap_content" />

<Button android:layout_width="wrap_content" android:id="@+id/timerResetTime"
    android:layout_height="wrap_content" android:text="@string/timerResetTime"></Button>

<Button android:layout_width="wrap_content" android:id="@+id/timerStartStopTime"
    android:layout_height="wrap_content"></Button>


<Chronometer android:id="@+id/chrono"
    android:layout_height="wrap_content" android:layout_width="wrap_content"
    android:textStyle="bold" android:textSize="14sp" android:visibility="gone" />

Here is the Adapter:

открытый класс TimersAdapter расширяет BaseAdapter {

final static String START = "Start";
final static String STOP = "Stop";
private PenaltyBoxTimerActivity activity;
private ArrayList<TimerController> _controllers;
private static LayoutInflater inflater = null;

public TimersAdapter(PenaltyBoxTimerActivity a, ArrayList<TimerController> controllers) {
    activity = a;
    _controllers = controllers;
    inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

public int getCount() {
    return _controllers.size();
}

public Object getItem(int position) {
    return _controllers.get(position);
}

public long getItemId(int position) {
    return position;
}

public static class ViewHolder {
    public Button startStopButton;
    public Button resetButton;
    public TextView timeView;
    public TextView timerName;
    public Chronometer stopWatch;

    public long length = 0;
    public long startTime = 0;
    public long currentTime = 0;
    public long timeElapsed = 0;
    public long timeRemaining = 0;
    public long prevTimeRemaining = 0;
    public boolean isCurrentlyRunning = false;
}

public View getView(final int position, View convertView, ViewGroup parent) {
    View vi = convertView;
    final ViewHolder holder;

    if (convertView == null) {
        vi = inflater.inflate(R.layout.timer_item, null);
        holder = new ViewHolder();

        holder.timeView = (TextView) vi.findViewById(R.id.timerTime);
        holder.startStopButton = (Button) vi.findViewById(R.id.timerStartStopTime);
        holder.resetButton = (Button) vi.findViewById(R.id.timerResetTime);
        holder.timerName = (TextView) vi.findViewById(R.id.timerPositionName);

        holder.stopWatch = (Chronometer) vi.findViewById(R.id.chrono);

        vi.setTag(holder);
    } else
        holder = (ViewHolder) vi.getTag();

    holder.length = _controllers.get(position).getLength();
    holder.startTime = _controllers.get(position).getStartTime();
    holder.currentTime = _controllers.get(position).getCurrentTime();
    holder.timeElapsed = _controllers.get(position).getTimeElapsed();
    holder.timeRemaining = _controllers.get(position).getTimeRemaining();
    holder.prevTimeRemaining = _controllers.get(position).getPrevTimeRemaining();
    holder.isCurrentlyRunning = _controllers.get(position).getIsCurrentlyRunning();
    holder.timerName.setText(_controllers.get(position).getPositionName());
    holder.timeView.setText(DateTimes.formatTime(holder.length));

    holder.stopWatch.setOnChronometerTickListener(new OnChronometerTickListener() {
        @Override
        public void onChronometerTick(Chronometer arg0) {
            AndroidLogger.logMessage("time remaining " + DateTimes.formatTime(holder.timeRemaining), Log.INFO);
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    holder.currentTime = SystemClock.elapsedRealtime();
                    holder.isCurrentlyRunning = true;
                    holder.timeElapsed = holder.currentTime - holder.startTime;
                    if (holder.prevTimeRemaining == 0)
                        holder.timeRemaining = holder.length - holder.timeElapsed;
                    else
                        holder.timeRemaining = holder.prevTimeRemaining - holder.timeElapsed;
                    holder.timeView.setText(DateTimes.formatTime(holder.timeRemaining));
                }
            });
        }
    });

    holder.resetButton.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            AndroidLogger.logMessage("reset single Timer", Log.INFO);
            holder.prevTimeRemaining = 0;
            holder.isCurrentlyRunning = false;
            AndroidLogger.logMessage("RESET clicked ", Log.INFO);
            holder.stopWatch.setBase(SystemClock.elapsedRealtime());
            holder.timeView.setText(DateTimes.formatTime(0000));
        }
    });

    holder.startStopButton.setText(START);
    holder.startStopButton.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            if (holder.startStopButton.getText().toString().equalsIgnoreCase(START)) {
                AndroidLogger.logMessage("start single Timer", Log.INFO);
                holder.startTime = SystemClock.elapsedRealtime();
                holder.isCurrentlyRunning = true;

                holder.stopWatch.setBase(SystemClock.elapsedRealtime());
                holder.stopWatch.start();
                holder.startStopButton.setText(STOP);
                AndroidLogger.logMessage("start clicked ", Log.INFO);
                OnTimerStartClickEvent(true);
            } else {
                AndroidLogger.logMessage("stop single Timer", Log.INFO);
                holder.currentTime = SystemClock.elapsedRealtime();
                holder.timeElapsed = holder.currentTime - holder.startTime;
                if (holder.prevTimeRemaining == 0) {
                    holder.timeRemaining = holder.length - holder.timeElapsed;
                } else {
                    holder.timeRemaining = holder.prevTimeRemaining - holder.timeElapsed;
                }
                holder.prevTimeRemaining = holder.timeRemaining;
                holder.timeView.setText(DateTimes.formatTime(holder.timeRemaining));

                holder.stopWatch.stop();

                holder.startStopButton.setText(START);
                AndroidLogger.logMessage("stop clicked ", Log.INFO);
                OnTimerStopClickEvent(false);
            }
        }
    });

    activity.setOnTimerStartClickListener(new OnTimerStartStopClickListener() {
        @Override
        public void onTimerStartStopButtonClick() {
            AndroidLogger.logMessage("is currently running:" + holder.isCurrentlyRunning, Log.INFO);
            if (holder.isCurrentlyRunning) {
                AndroidLogger.logMessage("start single Timer", Log.INFO);
                holder.startTime = SystemClock.elapsedRealtime();
                holder.isCurrentlyRunning = true;

                holder.stopWatch.setBase(SystemClock.elapsedRealtime());
                holder.stopWatch.start();
                holder.startStopButton.setText(STOP);
                AndroidLogger.logMessage("start clicked ", Log.INFO);
            }
        }
    });
    activity.setOnTimerStopClickListener(new OnTimerStartStopClickListener() {
        @Override
        public void onTimerStartStopButtonClick() {
            AndroidLogger.logMessage("is currently running:" + holder.isCurrentlyRunning, Log.INFO);
            // if (_holder.isCurrentlyRunning) {
            AndroidLogger.logMessage("stop single Timer", Log.INFO);
            holder.currentTime = SystemClock.elapsedRealtime();
            holder.timeElapsed = holder.currentTime - holder.startTime;
            if (holder.prevTimeRemaining == 0) {
                holder.timeRemaining = holder.length - holder.timeElapsed;
            } else {
                holder.timeRemaining = holder.prevTimeRemaining - holder.timeElapsed;
            }
            holder.prevTimeRemaining = holder.timeRemaining;
            holder.timeView.setText(DateTimes.formatTime(holder.timeRemaining));

            holder.stopWatch.stop();
            holder.startStopButton.setText(START);
            AndroidLogger.logMessage("stop clicked ", Log.INFO);
            // }
        }
    });

    return vi;
}

private OnTimerStartStopClickListener _onTimerStopClickListener = null;

public void setOnTimerStopClickListener(OnTimerStartStopClickListener listener) {
    _onTimerStopClickListener = listener;
}

private void OnTimerStopClickEvent(boolean isTimerCurrentlyActive) {
    if (_onTimerStopClickListener != null) {
        _onTimerStopClickListener.onTimerStartStopButtonClick();
    }
}

private OnTimerStartStopClickListener _onTimerStartClickListener = null;

public void setOnTimerStartClickListener(OnTimerStartStopClickListener listener) {
    _onTimerStartClickListener = listener;
}

private void OnTimerStartClickEvent(boolean isTimerCurrentlyActive) {
    if (_onTimerStartClickListener != null) {
        _onTimerStartClickListener.onTimerStartStopButtonClick();
    }
}}

Вот мои действия:

открытый класс PenaltyBoxTimerActivity расширяет Activity {private Button _startTimersButton; приватная кнопка _stopTimersButton; частный ListView _manageTimersList; TimersListAdapter _adapter;

private ArrayList<TimerController> _timerList = new ArrayList<TimerController>();

private boolean _areCountersActive = false;
long countUp;

private OnTimerStartStopClickListener _onTimerStopClickListener = null;

public void setOnTimerStopClickListener(OnTimerStartStopClickListener listener) {
    _onTimerStopClickListener = listener;
}

private void OnTimerStopClickEvent() {
    if (_onTimerStopClickListener != null) {
        _onTimerStopClickListener.onTimerStartStopButtonClick();
    }
}

private OnTimerStartStopClickListener _onTimerStartClickListener = null;

public void setOnTimerStartClickListener(OnTimerStartStopClickListener listener) {
    _onTimerStartClickListener = listener;
}

private void OnTimerStartClickEvent() {
    if (_onTimerStartClickListener != null) {
        _onTimerStartClickListener.onTimerStartStopButtonClick();
    }
}

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    initializeGoToSettingsButton();
    initializeStartTimerButton();
    initializeStopTimerButton();

    // add some test data
    _timerList = new ArrayList<TimerController>();
    TimerController a = new TimerController(UUID.randomUUID(), "hello", 100000);
    TimerController b = new TimerController(UUID.randomUUID(), "hello", 60000);
    TimerController c = new TimerController(UUID.randomUUID(), "hello", 10000);
    TimerController d = new TimerController(UUID.randomUUID(), "hello", 10000);
    TimerController e = new TimerController(UUID.randomUUID(), "hello", 10000);
    TimerController f = new TimerController(UUID.randomUUID(), "hello", 10000);
    _timerList.add(a);
    _timerList.add(b);
    _timerList.add(c);
    _timerList.add(d);
    _timerList.add(e);
    _timerList.add(f);

    initializeListView();
    intializeTimerButtons();
}

private void initializeGoToSettingsButton() {
    Button goToSettingsButton = (Button) findViewById(R.id.goToSettingsButton);
    goToSettingsButton.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {

            Intent myIntent = new Intent(getApplicationContext(), SettingsActivity.class);
            startActivity(myIntent);

        }
    });
}

private void initializeStopTimerButton() {
    _stopTimersButton = (Button) findViewById(R.id.stopTimersButton);
    _stopTimersButton.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            enableStartTimerButton();
            // OnTimerStopClickEvent();
            AndroidLogger.logMessage("stop all timers", Log.INFO);

            for (int i = 0; i < _timerList.size(); i++) {
                if (_timerList.get(i).getIsCurrentlyRunning()) {
                    // _timerList.get(i).getStopWatch().stop();

                    _timerList.get(i).setCurrentTime(SystemClock.elapsedRealtime());
                    _timerList.get(i).setTimeElapsed(
                            _timerList.get(i).getCurrentTime() - _timerList.get(i).getStartTime());

                    if (_timerList.get(i).getPrevTimeRemaining() == 0) {
                        _timerList.get(i).setTimeRemaining(
                                _timerList.get(i).getLength() - _timerList.get(i).getTimeElapsed());
                    } else {
                        _timerList.get(i).setTimeRemaining(
                                _timerList.get(i).getPrevTimeRemaining() - _timerList.get(i).getTimeElapsed());
                    }
                    _timerList.get(i).setPrevTimeRemaining(_timerList.get(i).getTimeRemaining());
                    // holder.timeView.setText(DateTimes.formatTime(holder.timeRemaining));
                }
            }

            _adapter.notifyDataSetChanged();
        }
    });
}

private void initializeStartTimerButton() {
    _startTimersButton = (Button) findViewById(R.id.startTimersButton);
    _startTimersButton.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            AndroidLogger.logMessage("start all Timers", Log.INFO);
            enableStopTimerButton();

        }
    });
}

private void initializeListView() {
    _manageTimersList = (ListView) findViewById(R.id.manageTimersList);
    // TimersAdapter adapter = new TimersAdapter(this, R.layout.timer_item,
    // _timerList, this);
    _adapter = new TimersListAdapter(this, _timerList);
    _adapter.setOnTimerStartClickListener(new OnTimerStartStopClickListener() {
        @Override
        public void onTimerStartStopButtonClick() {
            if (!_areCountersActive) {
                enableStopTimerButton();
            }
        }
    });
    _adapter.setOnTimerStopClickListener(new OnTimerStartStopClickListener() {
        @Override
        public void onTimerStartStopButtonClick() {
            // stopTimer();
        }
    });

    _manageTimersList.setAdapter(_adapter);
    _manageTimersList.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            if (!_areCountersActive) {
                enableStopTimerButton();
            }
        }
    });
}

private void enableStartTimerButton() {
    AndroidLogger.logMessage("start All Timers", Log.INFO);
    _startTimersButton.setEnabled(true);
    _stopTimersButton.setEnabled(false);

}

private void enableStopTimerButton() {
    AndroidLogger.logMessage("stop all Timers", Log.INFO);
    _startTimersButton.setEnabled(false);
    _stopTimersButton.setEnabled(true);

}

private void intializeTimerButtons() {
    AndroidLogger.logMessage("create timer buttons", Log.INFO);
    _startTimersButton.setEnabled(false);
    _stopTimersButton.setEnabled(false);

}}

person SpoiledTechie.com    schedule 20.08.2011    source источник


Ответы (2)


Вы можете попробовать эти три варианта, чтобы попытаться получить ссылку на вашу деятельность:

  1. Используйте метод getChildAt() в вашем ListView (_manageTimersList). Это должно привести ребенка к определенному положению. Вы можете получить доступ к своему хронометру отсюда, используя findViewById, а затем остановить его.
  2. Вы можете открыть stopAll() и startAll() для своей активности через адаптер. В реализации этого метода вы должны добавить любые хронометры, добавленные с помощью getView(), а затем просто остановить их, когда кнопка вызовет stopAll(), или запустить их все с помощью startAll(). Примечание: это не мой предпочтительный метод
  3. Каждый TimerController, который вы передаете адаптеру, может иметь ссылку на Chronometer, который вы установили во время getView(). По сути, TimerController становится его оболочкой (что, я думаю, может быть вашим намерением, но я не уверен). Вы в основном будете делать что-то вроде

    TimerController timerController = _controllers.get(position);
    timerController.setChronometer(holder.stopWatch);

Как только вы установите эту ссылку, вы сможете делать то, что реализовали в коде. Просто не забудьте проверить значение null для каждого TimerController в списке.

person momo    schedule 20.08.2011
comment
Я попробовал ваш третий метод, думая, что он будет работать таким образом, но, к сожалению, это не так. Я не понимаю, почему он не может попасть в эту ссылку, но это просто так. Мне нравится эта функция stopAll и start all, хотя она и не является предпочтительной. Почему тебе все равно не нравится этот, если я могу спросить? - person SpoiledTechie.com; 21.08.2011
comment
Механизм повторного использования ConvertView может раздуть коллекцию, поскольку вы можете получить разные ссылки на хронометр. Это также, вероятно, причина, по которой № 3 может работать ненадежно, поскольку ссылка может быть переключена. Если размер ListView невелик, я думаю, что № 2 может работать нормально. Я бы сначала попробовал № 1 и двигался оттуда. Кроме того, когда у меня была аналогичная проблема, я проверял правильность ссылки, печатая предполагаемый объект (в вашем случае хронометр). По умолчанию toString() печатает экземпляр объекта, который включает его адрес в памяти. - person momo; 21.08.2011
comment
Спасибо, Момо, я думаю, что номер 1 определенно сделал это!!! Цените это тонну! Работал над этой проблемой в течение пары дней. - person SpoiledTechie.com; 21.08.2011

Я думаю, что ссылки на кнопки должны быть инкапсулированы в _adapter. Вы должны хранить представления кнопок в массиве (который можно инициализировать или повторно инициализировать в методе getView()) в классе TimersListAdapter и создать специальный общедоступный метод для переключения всех кнопок. Метод, который вы сможете вызывать из своей деятельности.

Надеюсь, это поможет вам.

person Andrei Buneyeu    schedule 20.08.2011