如何防止快速双击按钮

时间:2015-09-28 09:18:52

标签: android

我在这里查看了答案 - Android Preventing Double Click On A Button 并实现了qezt的解决方案,我已经尝试了doneButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // mis-clicking prevention, using threshold of 1 second if (SystemClock.elapsedRealtime() - doneButtonClickTime < 1000){ return; } //store time of button click doneButtonClickTime = SystemClock.elapsedRealtime(); doneButton.setEnabled(false); //do actual work } }); -

doneButton.setEnabled(true)

这些都不能对抗超快速双击。

注意 - 处理完成后我没有设置**SQLite** 。我只是完成了()活动,所以没有问题按钮过早启用。

11 个答案:

答案 0 :(得分:12)

我这样做很有效。

public abstract class OnOneOffClickListener implements View.OnClickListener {

   private static final long MIN_CLICK_INTERVAL=600;

   private long mLastClickTime;

   public static boolean isViewClicked = false;


   public abstract void onSingleClick(View v);

   @Override
   public final void onClick(View v) {
       long currentClickTime=SystemClock.uptimeMillis();
       long elapsedTime=currentClickTime-mLastClickTime;

       mLastClickTime=currentClickTime;

       if(elapsedTime<=MIN_CLICK_INTERVAL)
           return;
       if(!isViewClicked){
           isViewClicked = true;
           startTimer();
       } else {
           return;
       }
       onSingleClick(v);        
   }
    /**
     * This method delays simultaneous touch events of multiple views.
     */
    private void startTimer() {
        Handler handler = new Handler();

        handler.postDelayed(new Runnable() {

            @Override
            public void run() {
                    isViewClicked = false;
            }
        }, 600);

    }

}

答案 1 :(得分:5)

我在按钮的监听器中使用这样的函数:

public static long lastClickTime = 0;
public static final long DOUBLE_CLICK_TIME_DELTA = 500;

public static boolean isDoubleClick(){
    long clickTime = System.currentTimeMillis();
    if(clickTime - lastClickTime < DOUBLE_CLICK_TIME_DELTA){
        lastClickTime = clickTime;
        return true;
    }
    lastClickTime = clickTime;
    return false;
}

答案 2 :(得分:3)

Probably not most efficient, but minimal inversive:

...
onClick(View v) {
    MultiClickPreventer.preventMultiClick(v);
    //your op here
}
...
public class MultiClickPreventer {
    private static final long DELAY_IN_MS = 500;

    public static void preventMultiClick(final View view) {
        if (!view.isClickable()) {
            return;
        }
        view.setClickable(false);
        view.postDelayed(new Runnable() {
            @Override
            public void run() {
                view.setClickable(true);
            }
        }, DELAY_IN_MS);
    }
}

答案 3 :(得分:1)

苏鲁的回答对我有用,谢谢!

我想为使用https://github.com/balysv/material-ripple/blob/master/library/src/main/java/com/balysv/materialripple/MaterialRippleLayout.java且面临此问题的任何人添加以下答案 -

app:mrl_rippleDelayClick默认为true。 这意味着,onClick只有在完成显示纹波后才会执行。因此onClick中的setEnabled(false)将在延迟后执行,因为纹波未执行,在此期间您可以双击视图。

设置app:mrl_rippleDelayClick="false"以解决此问题。这意味着只要单击视图就会调用onClick,而不是等待纹波完成显示。

答案 4 :(得分:1)

您可以使用此方法。通过使用后延迟,您可以照顾双击事件。

void debounceEffectForClick(查看视图){

// NOTE
// Update the next available ID when you add a new LayerParameter field.
//
// LayerParameter next available layer-specific ID: 147 (last added: recurrent_param)
message LayerParameter {
  optional string name = 1; // the layer name
  optional string type = 2; // the layer type
  repeated string bottom = 3; // the name of each bottom blob
  repeated string top = 4; // the name of each top blob

  // The train / test phase for computation.
  optional Phase phase = 10;

  // The amount of weight to assign each top blob in the objective.
  // Each layer assigns a default value, usually of either 0 or 1,
  // to each top blob.
  repeated float loss_weight = 5;

  // Specifies training parameters (multipliers on global learning constants,
  // and the name and other settings used for weight sharing).
  repeated ParamSpec param = 6;

  // The blobs containing the numeric parameters of the layer.
  repeated BlobProto blobs = 7;

  // Specifies whether to backpropagate to each bottom. If unspecified,
  // Caffe will automatically infer whether each input needs backpropagation
  // to compute parameter gradients. If set to true for some inputs,
  // backpropagation to those inputs is forced; if set false for some inputs,
  // backpropagation to those inputs is skipped.
  //
  // The size must be either 0 or equal to the number of bottoms.
  repeated bool propagate_down = 11;

  // Rules controlling whether and when a layer is included in the network,
  // based on the current NetState.  You may specify a non-zero number of rules
  // to include OR exclude, but not both.  If no include or exclude rules are
  // specified, the layer is always included.  If the current NetState meets
  // ANY (i.e., one or more) of the specified rules, the layer is
  // included/excluded.
  repeated NetStateRule include = 8;
  repeated NetStateRule exclude = 9;

  // Parameters for data pre-processing.
  optional TransformationParameter transform_param = 100;

  // Parameters shared by loss layers.
  optional LossParameter loss_param = 101;

  // Layer type-specific parameters.
  //
  // Note: certain layers may have more than one computational engine
  // for their implementation. These layers include an Engine type and
  // engine parameter for selecting the implementation.
  // The default for the engine is set by the ENGINE switch at compile-time.
  optional AccuracyParameter accuracy_param = 102;
  optional ArgMaxParameter argmax_param = 103;
  optional BatchNormParameter batch_norm_param = 139;
  optional BiasParameter bias_param = 141;
  optional ConcatParameter concat_param = 104;
  optional ContrastiveLossParameter contrastive_loss_param = 105;
  optional ConvolutionParameter convolution_param = 106;
  optional CropParameter crop_param = 144;
  optional DataParameter data_param = 107;
  optional DropoutParameter dropout_param = 108;
  optional DummyDataParameter dummy_data_param = 109;
  optional EltwiseParameter eltwise_param = 110;
  optional ELUParameter elu_param = 140;
  optional EmbedParameter embed_param = 137;
  optional ExpParameter exp_param = 111;
  optional FlattenParameter flatten_param = 135;
  optional HDF5DataParameter hdf5_data_param = 112;
  optional HDF5OutputParameter hdf5_output_param = 113;
  optional HingeLossParameter hinge_loss_param = 114;
  optional ImageDataParameter image_data_param = 115;
  optional InfogainLossParameter infogain_loss_param = 116;
  optional InnerProductParameter inner_product_param = 117;
  optional InputParameter input_param = 143;
  optional LogParameter log_param = 134;
  optional LRNParameter lrn_param = 118;
  optional MemoryDataParameter memory_data_param = 119;
  optional MVNParameter mvn_param = 120;
  optional ParameterParameter parameter_param = 145;
  optional PoolingParameter pooling_param = 121;
  optional PowerParameter power_param = 122;
  optional PReLUParameter prelu_param = 131;
  optional PythonParameter python_param = 130;
  optional RecurrentParameter recurrent_param = 146;
  optional ReductionParameter reduction_param = 136;
  optional ReLUParameter relu_param = 123;
  optional ReshapeParameter reshape_param = 133;
  optional ROIPoolingParameter roi_pooling_param = 8266711;
  optional ScaleParameter scale_param = 142;
  optional SigmoidParameter sigmoid_param = 124;
  optional SmoothL1LossParameter smooth_l1_loss_param = 8266712;
  optional SoftmaxParameter softmax_param = 125;
  optional SPPParameter spp_param = 132;
  optional SliceParameter slice_param = 126;
  optional TanHParameter tanh_param = 127;
  optional ThresholdParameter threshold_param = 128;
  optional TileParameter tile_param = 138;
  optional WindowDataParameter window_data_param = 129;
  optional ShuffleChannelParameter shuffle_channel_param = 164;
}

}

答案 5 :(得分:1)

将清单中活动的launchMode设置为singleTop

<template lang="html">
    <section class="charts-highcharts">
        <grid-block title="Map">
            <div class="-map" id="map" >
                <l-map :zoom="8" :center="[47.41322, -1.219482]" :options="{ gestureHandling: true }" ref="map">
                    <l-tile-layer url="http://{s}.tile.osm.org/{z}/{x}/{y}.png"></l-tile-layer>
                    <l-marker-cluster :options="clusterOptions">
                        <l-geo-json v-for="l in locations" :key="l.id" :geojson="l.location" :options="options"></l-geo-json>
                    </l-marker-cluster>
                </l-map>
            </div>
        </grid-block>
    </section>
</template>

<script lang="js">
import L from "leaflet";
import { LMap, LTileLayer, LMarker, LGeoJson, LPopup } from "vue2-leaflet";
import { GestureHandling } from "leaflet-gesture-handling";
import Vue2LeafletMarkercluster from 'vue2-leaflet-markercluster';
import 'vue2-leaflet-markercluster/dist/leaflet.markercluster.js';
import 'vue2-leaflet-markercluster/dist/leaflet.markercluster-src.js';


export default  {
    name: 'Maps',
    components: {
        LMap,
        LTileLayer,
        LMarker,
        LGeoJson,
        LPopup,
        "l-marker-cluster": Vue2LeafletMarkercluster,
    },
    data () {
        return {
            geojson: null,
            clusterOptions: { disableClusteringAtZoom: 11},
            locations: [],
            options: {
                onEachFeature: function onEachFeature(feature, layer) {
                    layer.bindPopup(feature.properties.name);
                },
            },
        };
    },

    created () {

         L.Map.addInitHook("addHandler","gestureHandling", GestureHandling);
    },
    mounted() {

            let geojson = response.data.features,
                id = 0,
                tmpLocations = [];

            for (let l of geojson) {
                tmpLocations.push({
                    id: id,
                    location: l,
                 });
                id++;
            }

            this.locations = tmpLocations;
        });
    },
 };
</script>

<style scoped lang="scss">
@import "~leaflet.markercluster/dist/MarkerCluster.css";
@import "~leaflet.markercluster/dist/MarkerCluster.Default.css";
.charts-highcharts {
}
.-map {
    width: 100%;
    height: 800px;
}
</style>

答案 6 :(得分:0)

尝试设置你的按钮.setClickable(false) 像这样:

onclick(){
yourbutton.setClickable(false) ;
ButtonLogic();
}

ButtonLogic(){
//your button logic
yourbutton.setClickable(true);
}

答案 7 :(得分:0)

Qezt解决方案已经很好了。 但是如果你想要防止超级快速双击,那么你只需减少门槛

    // half a second
    if (SystemClock.elapsedRealtime() - doneButtonClickTime < 500) {
        return;
    }

    // or 100ms (1/10 of second)
    if (SystemClock.elapsedRealtime() - doneButtonClickTime < 100) {
        return;
    }

答案 8 :(得分:0)

public static void disablefor1sec(final View v) {
        try {
            v.setEnabled(false);
            v.setAlpha((float) 0.5);
            v.postDelayed(new Runnable() {
                @Override
                public void run() {
                    try {
                        v.setEnabled(true);
                        v.setAlpha((float) 1.0);
                    } catch (Exception e) {
                        Log.d("disablefor1sec", " Exception while un hiding the view : " + e.getMessage());
                    }
                }
            }, 1000);
        } catch (Exception e) {
            Log.d("disablefor1sec", " Exception while hiding the view : " + e.getMessage());
        }
    }

我将上面的方法保存在一个静态文件中,我会像所有按钮一样调用此方法

    button_or_textview.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            StaticFile.disablefor1sec(button_or_textview);
            // Do Somthing.
        }
    });

答案 9 :(得分:0)

科特林短版:

private var lastClickTime: Long = 0

//in click listener
if (SystemClock.elapsedRealtime() - lastClickTime < 1000) {
    return
}
lastClickTime = SystemClock.elapsedRealtime()

答案 10 :(得分:0)

private static final long MIN_CLICK_INTERVAL = 1000;

private boolean isViewClicked = false;

private View.OnClickListener onClickListener = new View.OnClickListener() {
@Override
final public void onClick(View view) {
    if (isViewClicked) {
      return:
    }
    // place your onClick logic here
    isViewClicked = true;
    view.postDelayed(new Runnable() {
        @Override
        public void run() {
            isViewClicked = false;
        }
    }, MIN_CLICK_INTERVAL);
}

}

相关问题