एंड्रॉइड में रैंडम पोजीशन पर बटन एनिमेट करना
यह उदाहरण एक बटन को हर सेकंड स्क्रीन पर रैंडम निर्देशांक पर ले जाता है, जिसमें Timer + Handler (या runOnUiThread) और व्यू प्रॉपर्टी एनिमेशन का उपयोग किया जाता है।
आवश्यकताएं
- न्यूनतम SDK 21+
- पैकेज:
com.example.randombutton
चरण 1 - लेआउट (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/movingButton"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:text="मुझे पकड़ो!"
android:layout_gravity="center" />
</FrameLayout>
FrameLayout (या ConstraintLayout) ओवरलैपिंग/मूविंग व्यू के लिए अच्छा काम करता है। मूल LinearLayout व्यू ट्रांसलेशन को प्रतिबंधित करता है।
चरण 2 - गतिविधि (MainActivity.java)
package com.example.randombutton;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.DisplayMetrics;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class MainActivity extends AppCompatActivity {
private Button movingButton;
private ScheduledExecutorService scheduler;
private final Random random = new Random();
private final Handler mainHandler = new Handler(Looper.getMainLooper());
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
movingButton = findViewById(R.id.movingButton);
// बटन के मापने जाने तक प्रतीक्षा करें
movingButton.post(this::startMoving);
}
private void startMoving() {
int screenW = getResources().getDisplayMetrics().widthPixels;
int screenH = getResources().getDisplayMetrics().heightPixels;
int btnW = movingButton.getWidth();
int btnH = movingButton.getHeight();
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(() -> {
// बटन पैडिंग के साथ सुरक्षित रैंडम X/Y की गणना करें
final float newX = random.nextInt(Math.max(1, screenW - btnW));
final float newY = random.nextInt(Math.max(1, screenH - btnH));
mainHandler.post(() -> movingButton.animate()
.x(newX)
.y(newY)
.setDuration(300) // सुचारू संक्रमण
.start());
}, 0, 1, TimeUnit.SECONDS);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (scheduler != null) scheduler.shutdownNow(); // लीक रोकें
}
}
सुधार
- FrameLayout निरपेक्ष X/Y ट्रांसलेशन की अनुमति देता है।
- ScheduledExecutorService +
HandlerTimer(जो एक नया थ्रेड बनाता है) और लीक होने वाले आंतरिकTimerऑब्जेक्ट को प्रतिस्थापित करता है। - बटन आयाम बटन के लेआउट होने के बाद पढ़े जाते हैं (
post) ताकि यह स्क्रीन से बाहर न जाए। - एनिमेशन अवधि 300ms अचानक कूद के बजाय दृश्य गति देती है।
- onDestroy() में सफाई बैकग्राउंड थ्रेड को रोकती है।
चलाएं
- डिवाइस/एमुलेटर पर डेप्लॉय करें।
- बटन हर सेकंड सुचारू रूप से घूमता है।
- बैक दबाकर गतिविधि को नष्ट करें — कोई लीक थ्रेड नहीं।
- बटन को टैप करने योग्य बनाएं (क्लिक लिसनर जोड़ें) एक "व्हैक-ए-मोल" गेम के लिए।
- एक्सेलेरोमीटर डेटा के आधार पर स्थिति बदलें।
- बटन के बजाय
ImageViewका उपयोग करें कस्टम ग्राफिक्स के लिए।