LongClick оқиғасы тым тез орындалады. Оны іске қосу үшін қажетті клик уақытын қалай арттыра аламын?

In an application I'm working on, I have the requirement that a user must click & hold a component for a period time before a certain action occurs.

Мен OnLongClickListener қызметін ұзақ уақыт бойы тыңдау үшін пайдаланып жатырмын, бірақ OnLongClick оқиғасын іске қосу үшін басудың ұзындығы тым қысқа екендігін білемін.

For example, let's say the LongClick event triggers after a 400ms click, but I want the user to have to click & hold for 1200ms before the event triggers.

LongClick оқиғасын неғұрлым ұзақ нұқуды талап ететіндей етіп теңшеуге болады ма? Немесе ұзын шерулерді тыңдауға мүмкіндік беретін басқа конструкция бар ма?

16

6 жауаптар

OnLongClick оқиғасындағы таймерді өзгерту мүмкін емес, оны Android-да басқарады.

Мүмкін, .setOnTouchListener() пайдалану керек.

Then register when the MotionEvent is a ACTION_DOWN.
Note the current time in a variable.
Then when a MotionEvent with ACTION_UP is registered and the current_time - actionDown time > 1200 ms then do something.

соншалықты көп:

Button button = new Button();
long then = 0;
    button.setOnTouchListener(new OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if(event.getAction() == MotionEvent.ACTION_DOWN){
                then = (Long) System.currentTimeMillis();
            }
            else if(event.getAction() == MotionEvent.ACTION_UP){
                if(((Long) System.currentTimeMillis() - then) > 1200){
                    return true;
                }
            }
            return false;
        }
    })
17
қосылды
Неге = getSystemTime() неге түсіндіріледі? Сондай-ақ, getSystemTime() әдісі жұмыс істемейді. Мүмкін, Меңзеп түрі: System.currentTimeMillis ()
қосылды автор Cumulo Nimbus, көзі
Расталған. Содан кейін ұзын емес, int деп анықтаңыз. Содан кейін пайдаланыңыз: then = (Long) System.currentTimeMillis (); және айырмашылықты табу кезінде getSystemTime() орнына System.currentTimeMillis() функциясын қолданған кезде,
қосылды автор Cumulo Nimbus, көзі
Бұл маған қажет нәрсені істейді. Орналастырылған әдіс пайдаланушы саусағыңызды көтерген кезде ғана кодты орындайды. Мен өзімнің логикасын кідіртіп қалмай-ақ іске қосқым келеді, ал пайдаланушы басуды тоқтатқаннан гөрі.
қосылды автор ampersandre, көзі

Бұл мінез-құлыққа жетудің ең қарапайым жолы. Қазіргі уақытта қабылданған жауап бойынша бірнеше артықшылығы бар.

  1. view.isPressed тексергенде, сенсорлық оқиға оқиғалардан шыққан жағдайда onClick және onLongClick қосылмағанына көз жеткіземіз. Бұл жүйенің әдепкі onClick және onLongClick әрекетін имитациялайды.
  2. Оқиға уақыт туралы ақпаратты сақтайды, сондықтан бастау коэффициентін ACTION_DOWN сақтауға қажеті жоқ немесе ағымдағы уақытты ACTION_UP ішінде есептеңіз. Бұл onTouch шегінен тыс бір айнымалы оқиға оқиғасының басталу уақытын бақылай алмағандықтан, біз оны бір мезгілде бірнеше рет көру үшін пайдалануға болатынын білдіреді.

ЕСКЕРТПЕ: ViewConfiguration.getLongPressTimeout() әдепкі болып табылады және сіз кез келген мәнді пайдалану үшін осы тексеруді өзгерте аласыз.

ЕСКЕРТПЕ: Егер көрініс әдеттегідей басылмайтын болса, жұмыс істеу үшін view.isPressed() үшін view.setClickable (true) деп қоңырау шалу қажет.

@Override
public boolean onTouch(View view, MotionEvent event) {
    if (view.isPressed() && event.getAction() == MotionEvent.ACTION_UP) {
        long eventDuration = event.getEventTime() - event.getDownTime();
        if (eventDuration > ViewConfiguration.getLongPressTimeout()) {
            onLongClick(view);
        } else {
            onClick(view);
        }
    }
    return false;
}

Егер сіз @ampersandre сияқты, ұзақ уақытқа созылатын оқиғаны ACTION_UP күту орнына кешіктіру кезеңіне жеткенде дереу іске қосқыңыз келсе, төмендегілер мен үшін жақсы жұмыс істейді.

@Override
public boolean onTouch(View view, MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        view.setTag(true);
    } else if (view.isPressed() && (boolean) view.getTag()) {
        long eventDuration = event.getEventTime() - event.getDownTime();
        if (eventDuration > ViewConfiguration.getLongPressTimeout()) {
            view.setTag(false);
            onLongClick(view);
        } else if (event.getAction() == MotionEvent.ACTION_UP) {
            onClick(view);
        }
    }
    return false;
}
3
қосылды
Сәлеметсіз бе! Сіздің жауабыңызға рахмет, бұл маған өте пайдалы болды. Сіздің шешіміммен бір кішігірім мәселе бар (кешіктіру кезеңіне бірден қол жеткізілетін ұзақ уақыт басу оқиғасы): ұзақтығы> уақытты белгілеу үшін тексеруді жалғастыру қажет. Осылайша, егер U түймесінде кішкентай қозғалыстар болмаса, ол басылады (оқиға ...), OnLongClick іске қосылуы уақыттың ұзақтығынан кейін болуы мүмкін. Ұсыныс бар ма? Көптеген нәрсе!
қосылды автор Tom, көзі

Мен Rohan көмегімен шешім жасадым

Мен оның жауаптарын өз талаптарыма сай бейімдедім.

Пайдаланушы түймені басқан кезде, жіп іске қосылады. Ұяшық менің қалаған кідірісім үшін ұйықтайды, содан кейін ол оянғанда, ол маған қажет кодты орындайды. Пайдаланушы жолға шыққанда, жіп жойылады. Бұл менің қалағанымды жүзеге асырады, себебі пайдаланушы жіп ұйықтамай тұрып кетуге мүмкіндік берсе, жіп үзіледі және әрекет орындалмайды.

Мен бұл тәсілді ұнатамын, өйткені ол маған кешіктіріле бастағаннан кейін менің бизнес-логикамды жүзеге асыруға мүмкіндік береді, бұл жақсы, себебі мен пайдаланушыға олар жеткілікті ұзақ уақытқа итерілгенін білуге ​​мүмкіндік беретін кері байланыс бере аламын (мысалы, телефон дірілдей алады).
Бұл тәсілдің төмендеуі: қолданушы қажетті әрекетті орындау кезінде түймені босатуға мүмкіндік беретін қауіп бар, және бәрі орындалмас бұрын жіпті өлтіреді. Бұл менің ісім үшін үлкен проблема емес, өйткені менің бизнес-логикум өте аз. бұл басқа сыныптың өңдеуі үшін оқиға ғана өртейді. Егер әрекет толығымен аяқталмаса, пайдаланушы қайтадан әрекет етуі керек.

Коды қалағанымнан сәл ұзағырақ, бірақ егер бұл қолданбаңыздағы жалпы мүмкіндік болса, ол оңай қайта пайдалануға болады. Міне код үлгісі:

protected class MyLongClickListener implements View.OnTouchListener {
    private Thread longClickSensor;

    public boolean onTouch(View view, MotionEvent event) {
       //If the user is pressing down and there is no thread, make one and start it
        if (event.getAction() == MotionEvent.ACTION_DOWN && longClickSensor == null) {
            longClickSensor = new Thread(new MyDelayedAction());
            longClickSensor.start();
        }
       //If the user has let go and there was a thread, stop it and forget about the thread
        if (event.getAction() == MotionEvent.ACTION_UP && longClickSensor != null) {
            longClickSensor.interrupt();
            longClickSensor = null;
        }
        return false;
    }

    private class MyDelayedAction implements Runnable {
        private final long delayMs = 1200;

        public void run() {
            try {
                Thread.sleep(delayMs);//Sleep for a while
                doBusinessLogic();    //If the thread is still around after the sleep, do the work
            } catch (InterruptedException e) { return; }
        }
        private void doBusinessLogic() {
           //Make sure this logic is as quick as possible, or delegate it to some other class
           //through Broadcasted Intents, because if the user lets go while the work is happenening,
           //the thread will be interrupted.
        }
    }
}
3
қосылды
Пайдаланушы екінші саусақты пайдаланған кезде бұл нашар болады. тексеріп шығу керек, егер сізде тақырып басталған болса немесе басқа таңдау идентификаторларын қадағалауыңыз керек.
қосылды автор xeed, көзі
final boolean[] isLongPress = {false};
final int duration = 3000;
final Handler someHandler = new Handler();
    final Runnable someCall = new Runnable() {
        @Override
        public void run() {
            if(isLongPress[0]) {
               //your code goes here 
            }
        }
    };

    someButton.setOnTouchListener(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            int eventAction = event.getAction();
            if(eventAction == MotionEvent.ACTION_DOWN){
                isLongPress[0] = true;
                someHandler.postDelayed(someCall, duration);
            }
            else if (eventAction == MotionEvent.ACTION_UP) {
                isLongPress[0] = false;
                someHandler.removeCallbacks(someCall);
            }
            return false;
        }
    });
2
қосылды
MotionEvent.ACTION_MOVE ататын және removeCallbacks
қосылды автор UnLoCo, көзі

Бір әдіс оны жасай алады. Қайта шақыруды бастау үшін уақытты ұзындығын теңшеу оңай, пайдалану оңай.

public static void setOnLongClickListener(final View view, final View.OnLongClickListener longClickListener, final long delayMillis)
{
    view.setOnTouchListener(new View.OnTouchListener()
    {
        final Handler handler = new Handler();
        final Runnable runnable = new Runnable()
        {
            @Override
            public void run()
            {
                longClickListener.onLongClick(view);
                mRunning = false;
            }
        };

        boolean mRunning;
        boolean mOutside;
        RectF mRect = new RectF();

        @Override
        public boolean onTouch(View v, MotionEvent event)
        {
            switch (event.getAction())
            {
                case MotionEvent.ACTION_DOWN:
                {
                    handler.postDelayed(runnable, delayMillis);
                    mRunning = true;
                    mOutside = false;
                    mRect.set(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
                    break;
                }
                case MotionEvent.ACTION_MOVE:
                    if (!mOutside)
                    {
                        mOutside = !mRect.contains(v.getLeft() + event.getX(), v.getTop() + event.getY());
                        if (mOutside)
                        {
                            handler.removeCallbacks(runnable);
                            mRunning = false;
                        }
                    }
                    break;
                case MotionEvent.ACTION_UP:
                {
                    if (mRunning)
                        v.performClick();
                    handler.removeCallbacks(runnable);
                    mRunning = false;
                    break;
                }
                case MotionEvent.ACTION_CANCEL:
                {
                    handler.removeCallbacks(runnable);
                    mRunning = false;
                    break;
                }
            }
            return true;//!!!
        }
    });
}
1
қосылды

Мен ұзақ баспасөз іс-шарасының қалай жұмыс істейтінін қарапайым шешім таптым. Көрініс әр рет басылғанда, Runnable түрін CheckForLongPress кезекке кешігумен қосылады. Егер кідіріс аяқталса, OnLongClickListener шақырылады. Кешіктіріп аяқталғанға дейін басқа оқиға болған жағдайда, CheckForLongPress Runnable кезекте жойылады.

Операциялық кідіртуді өзгерту үшін қарапайым әдісті postDelayed (Runnable action, long delayMillis) әдісін болдырмау

@Override public boolean postDelayed(Runnable action, long delayMillis) {
    boolean isLongPress = action.getClass().getSimpleName().equals("CheckForLongPress");
    return super.postDelayed(action, isLongPress ? LONG_PRESS_MILLIS : delayMillis);
}

Мен LONG_PRESS_MILLIS параметрін 100-ге орнаттым және ол жұмыс істейді!

Бұл көмектеседі деп сенемін !!! ;)

0
қосылды