我在这里查看了答案 - 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**
。我只是完成了()活动,所以没有问题按钮过早启用。
答案 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);
}
}