滚动和恢复时按钮更改状态

时间:2015-09-24 15:22:09

标签: android scroll android-button

我有一个ListView,此列表中的一些View有一个Button(并非每个视图都有)。此按钮有2种状态:START和STOP。因此,每当我滚动列表或打开另一个应用程序,然后返回此应用程序(不永久关闭),按钮的状态将更改回其先前的状态。无论如何要解决它吗?

工作正常。问题是状态未保存,因此当我滚动时,它再次调用getView,状态变回前一状态。当更改应用程序然后再回来

这是getView函数,其中所有问题都开始了:

 @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ContentViewHolder.CaptionTitleHolder captionHolder = null;
        ContentViewHolder.PreCookingViewHolder preCookingHolder = null;
        ContentViewHolder.CookingViewHolder cookingHolder = null;
        int type = getItemViewType(position);
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        if (type == CAPTION_TITLE){
            if (convertView == null){
                convertView = inflater.inflate(R.layout.caption_title_view, parent, false);
                captionHolder = new ContentViewHolder.CaptionTitleHolder();
                captionHolder.text = (TextView) convertView.findViewById(R.id.caption_title_textview);
                convertView.setTag(captionHolder);
            } else {
                captionHolder = (ContentViewHolder.CaptionTitleHolder) convertView.getTag();
            }
            captionHolder.text.setText(((RecipeContentActivity2.CaptionTitle) allItems.get(position)).getContent());

        } else if (type == COOKING){
            if (convertView == null){
                convertView = inflater.inflate(R.layout.cooking_steps_and_timer, parent, false);
                cookingHolder = new ContentViewHolder.CookingViewHolder();
                cookingHolder.text = (TextView) convertView.findViewById(R.id.cooking_step_content);
                cookingHolder.time = (TextView) convertView.findViewById(R.id.cooking_timer);
                cookingHolder.skipButton = (Button) convertView.findViewById(R.id.button_skip);
                cookingHolder.startButton = (Button) convertView.findViewById(R.id.button_timer);

                convertView.setTag(cookingHolder);
            } else {
                cookingHolder = (ContentViewHolder.CookingViewHolder) convertView.getTag();
            }
            CookingStep myStep = (CookingStep) allItems.get(position);
            setUpCookingView(convertView, cookingHolder, myStep);
        } else {
            if (convertView == null){
                convertView = inflater.inflate(R.layout.pre_cooking_view, parent, false);
                preCookingHolder = new ContentViewHolder.PreCookingViewHolder();
                preCookingHolder.text = (TextView) convertView.findViewById(R.id.pre_cooking_textview);
                convertView.setTag(preCookingHolder);
            } else {
                preCookingHolder = (ContentViewHolder.PreCookingViewHolder) convertView.getTag();
            }
            preCookingHolder.text.setText((String) allItems.get(position));
        }

        return convertView;
    }

    private void setUpCookingView(final View c, final ContentViewHolder.CookingViewHolder view, final CookingStep step){
        String stepOrder = context.getResources().getString(R.string.step_order) + " " + step.getOrder();
        String content = "<b>" + stepOrder + ":</b> " + step.getContent() + "\n";
        view.text.setText(Html.fromHtml(content));

        if (step.getMinute() != null && step.getMinute() > 0){
            if (step.getMyTimer() == null) {
                CookingTimer2 timer = new CookingTimer2(step.getMinute()) {

                    @Override
                    public void upgradeUI() {
                        view.time.setText(toString());
                    }
                };
                step.setTimer(timer);
            }
            view.time.setVisibility(View.VISIBLE);
            view.startButton.setVisibility(View.VISIBLE);
            view.skipButton.setVisibility(View.VISIBLE);



            view.startButton.setText(R.string.button_available);
            view.skipButton.setText(R.string.skip_button_content);
            view.startButton.setEnabled(step.isTurnEnable());
            view.skipButton.setEnabled(step.isTurnEnable());
            view.time.setText(step.getMyTimer().toString());


            view.startButton.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getAction() == MotionEvent.ACTION_UP) {
                        if (!view.startButton.isPressed()) {
                            view.startButton.setPressed(true);
                            view.startButton.setText(R.string.button_pressed);
                            step.getMyTimer().doStart();
                            //c.setTag(R.id.button_timer, true);
                        } else {
                            view.startButton.setPressed(false);
                            view.startButton.setText(R.string.button_available);
                            step.getMyTimer().doStop();
                            //c.setTag(R.id.button_timer, false);
                        }
                    }
                    return true;
                }
            });

            view.skipButton.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getAction() == MotionEvent.ACTION_UP) {
                        step.getMyTimer().doStop();
                        ((RecipeContentActivity2) context).enableNextStep();
                    }
                    return true;
                }
            });
        } else {
            view.time.setVisibility(View.GONE);
            view.startButton.setVisibility(View.GONE);
            view.skipButton.setVisibility(View.GONE);
        }

    }

不知何故,我设法解决了这个问题,以防使用这个计时器的状态进行滚动。感谢milosmns提醒我,我仍然有我的计时器滴答作响

if (step.getMyTimer().isTicking()){
                view.startButton.setPressed(true);
                view.startButton.setText(R.string.button_pressed);
            }

但是当我切换到另一个应用程序时,我仍然遇到这个问题,然后再回来。似乎在这种情况下,getView没有被调用。那我接下来该怎么办?

所以是的,我发现了一种做事的黑客方式。我不是很喜欢它

在我的活动中:

@Override
    protected void onResume() {
        super.onResume();
        if (wasStoped)
            ((MyAdapter)listContent.getAdapter()).notifyDataSetChanged();
    }

    @Override
    protected void onStop() {
        wasStoped = true;
        super.onStop();
    }

我仍然想知道任何其他方法

3 个答案:

答案 0 :(得分:0)

使用持有人类如:

public View getView(final int i, View view, final ViewGroup viewGroup) {
        View vi = view;
        final ViewHolder holder;
        if (view == null) {
            holder = new ViewHolder();
            vi = inflater.inflate(R.layout.listview_row_cart, null);
            holder.yourbutton = (Button) vi.findViewById(R.id.btn);
            vi.setTag(holder);
        } else {
            holder = (ViewHolder) view.getTag();
        }
            holder.yourbutton.setText("Start");
     }
     class ViewHolder {
           Button yourbutton
    }

答案 1 :(得分:0)

您的onCreate方法很可能再次被调用以重建视图并刷新按钮的状态,您需要保存按钮的状态。

您可以使用sharedPreferences执行此操作。

您可以查看有关如何实现此目的的文档 Here

答案 2 :(得分:0)

所以我能够解决这个问题,通过实现自己的Button,自定义状态。是的,我只是意识到依赖于按钮的状态pressed不是那样的,因为有太多干扰可以改变这种状态。

public class TimerButtonControl extends Button{
    private static final int[] STATE_RUN = {R.attr.timer_run};

    private boolean running = false;

    public TimerButtonControl(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setRun(boolean r){
        running = r;
        refreshDrawableState();
    }
    public boolean isRunning() {return running; }

    @Override
    protected int[] onCreateDrawableState(int extraSpace) {
        final int[] drawableState =  super.onCreateDrawableState(extraSpace + 1);
        if (running) {
            mergeDrawableStates(drawableState, STATE_RUN);
        }
        return drawableState;
    }
}

然后为此按钮定义xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item android:drawable="@drawable/clock_button_not_pressed"
        app:timer_run="false" android:state_enabled="true" />
    <item android:drawable="@drawable/clock_button_pressed"
        app:timer_run="true" android:state_enabled="true" />
    <item android:drawable="@drawable/button_unavailable"
        android:state_enabled="false" />
</selector>

然后在我的布局中使用它:

<com.username.mypackage.uiassistance.TimerButtonControl
        android:id="@+id/button_timer"
        android:padding="4dip"
        android:layout_width="90dip"
        android:layout_height="wrap_content"
        android:layout_below="@id/cooking_step_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:background="@drawable/timer_button"
        android:enabled="false"/>

最后在适配器内部:

if (step.getMyTimer().isTicking()){
                view.startButton.setRun(true);
                view.startButton.setText(R.string.button_pressed);
            }

            view.startButton.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getAction() == MotionEvent.ACTION_UP) {
                        if (!view.startButton.isRunning()) {
                            view.startButton.setRun(true);
                            view.startButton.setText(R.string.button_pressed);
                            step.getMyTimer().doStart();
                        } else {
                            view.startButton.setRun(false);
                            view.startButton.setText(R.string.button_available);
                            step.getMyTimer().doStop();
                        }
                    }
                    return true;
                }
            });

希望它可以帮助其他与我有同样问题的人。