top of page

Mastering Event Handling, Styles, and Themes in Android App Development



Event Handling


In Android, event handling is the process of responding to user actions such as button clicks, swipes, and taps. Event handling can be implemented in two ways: using anonymous inner classes or implementing the corresponding listener interfaces.

  • Using anonymous inner classes:


Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // Handle button click here
    }
});
  • Implementing the corresponding listener interfaces:


public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    @Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button = findViewById(R.id.button);
        button.setOnClickListener(this);
    }

    @Override
public void onClick(View v) {
        // Handle button click here
    }
}

Styles


Styles in Android are used to define a set of attributes that can be applied to a View or an Activity. Styles are defined in an XML file under the "res/values" directory.

Here's an example of a style definition:


<style name="MyButtonStyle" 
parent="@android:style/Widget.Button"><item name="android:textColor">#FFFFFF</item><item name="android:background">#000000</item><item name="android:textSize">16sp</item></style>

This style can then be applied to a button like this:


<Button
    android:id="@+id/button"
    style="@style/MyButtonStyle"
    android:text="Click me" />

Themes


A theme in Android is a collection of styles that are applied to an entire application or an Activity. Themes are defined in an XML file under the "res/values" directory.

Here's an example of a theme definition:


<style name="MyTheme" parent="Theme.AppCompat.Light.DarkActionBar"><item name="colorPrimary">#3F51B5</item><item name="colorPrimaryDark">#303F9F</item><item name="colorAccent">#FF4081</item></style>

This theme can then be applied to an application or an Activity in the AndroidManifest.xml file:


<applicationandroid:theme="@style/MyTheme"... >
    ...
</application>
    

That's it for the basics of event handling, styles, and themes in Android. Now let us deep dive into advance version...


Advanced Event Handling


In addition to handling basic user actions such as button clicks, Android provides various advanced event handling techniques, such as touch events, gesture detection, and drag-and-drop.


Touch Events:


In Android, touch events are a series of actions that occur when a user interacts with the touch screen of a device. These events can be handled by implementing the corresponding listener interfaces.

Here's an example of handling touch events on a View:


public class MainActivity extends AppCompatActivity implements View.OnTouchListener {
    private float x1, y1, x2, y2;

    @Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ImageView imageView = findViewById(R.id.image_view);
        imageView.setOnTouchListener(this);
    }

    @Override
public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                x1 = event.getX();
                y1 = event.getY();
                break;
            case MotionEvent.ACTION_UP:
                x2 = event.getX();
                y2 = event.getY();
                if (y1 < y2) {
                    // Handle swipe down
                } else if (y1 > y2) {
                    // Handle swipe up
                }
                break;
        }
        return true;
    }
}

Gesture Detection:


Android provides a Gesture Detection API that allows you to detect various gestures such as swipes, pinches, and rotations. Gesture detection can be implemented by extending the GestureDetector.SimpleOnGestureListener class and overriding the corresponding methods.

Here's an example of detecting a swipe gesture using the Gesture Detection API:


public class MainActivity extends AppCompatActivity {
    private GestureDetector gestureDetector;

    @Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
            @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                if (e1.getY() < e2.getY()) {
                    // Handle swipe down
                } else if (e1.getY() > e2.getY()) {
                    // Handle swipe up
                }
                return super.onFling(e1, e2, velocityX, velocityY);
            }
        });

        View view = findViewById(R.id.view);
        view.setOnTouchListener(new View.OnTouchListener() {
            @Override
        public boolean onTouch(View v, MotionEvent event) {
                gestureDetector.onTouchEvent(event);
                return true;
            }
        });
    }
}

Drag-and-Drop:


Android provides a Drag-and-Drop API that allows you to implement drag-and-drop functionality in your app. Drag-and-drop can be implemented by creating a draggable View and a drop target View, and handling the corresponding events.

Here's an example of implementing drag-and-drop functionality:


public class MainActivity extends AppCompatActivity {
    private TextView textView;

    @Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = findViewById(R.id.text_view);
        textView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
        public boolean onLongClick(View v) {
       ClipData data = ClipData.newPlainText("text", "Hello world!");
    View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(textView);
                textView.startDragAndDrop(data, shadowBuilder, textView, 0);
                textView.setVisibility(View.INVISIBLE);
                return true;
            }
        });

        View view = findViewById(R.id.view);
        view.setOnDragListener(new View.OnDragListener() {
            @Override
        public boolean onDrag(View v, DragEvent event) {
                switch (event.getAction()) {
                    case DragEvent.ACTION_DRAG_STARTED:
      // Check if the event contains the text data
                    if (event.getClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {
                            return true;
                        }
                        return false;
                    case DragEvent.ACTION_DRAG_ENTERED:
                        // Highlight the drop target
                        view.setBackgroundColor(Color.GREEN);
                        return true;
                    case DragEvent.ACTION_DRAG_EXITED:
                        // Unhighlight the drop target
                        view.setBackgroundColor(Color.WHITE);
                        return true;
                    case DragEvent.ACTION_DROP:
                        // Handle the dropped data
                        ClipData.Item item = event.getClipData().getItemAt(0);
                        String text = item.getText().toString();
                        Toast.makeText(MainActivity.this, text, Toast.LENGTH_SHORT).show();
                        textView.setVisibility(View.VISIBLE);
                        view.setBackgroundColor(Color.WHITE);
                        return true;
                    case DragEvent.ACTION_DRAG_ENDED:
                        // Unhighlight the drop target
                        view.setBackgroundColor(Color.WHITE);
                        return true;
                    default:
                        return false;
                }
            }
        });
    }
}

Advanced Styles and Themes


In addition to using predefined styles and themes, Android provides various advanced techniques for creating custom styles and themes.


Custom Styles:

Android allows you to create custom styles by defining a style resource file and specifying the attributes you want to customize.

Here's an example of creating a custom style:

Create a new file named "MyStyle" in the "res/values" directory:


<?xml version="1.0" encoding="utf-8"?><resources><style name="MyStyle" parent="android:Widget.Button"><item name="android:background">#FF0000</item><item name="android:textColor">#FFFFFF</item></style></resources>

Then apply the style to a View:


<Button
    android:id="@+id/my_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Click me"
    style="@style/MyStyle"/>

Custom Themes:


Android allows you to create custom themes by defining a theme resource file and specifying the attributes you want to customize.

Here's an example of creating a custom theme:

Create a new file named "MyTheme" in the "res/values" directory:


<?xml version="1.0" encoding="utf-8"?><resources><style name="MyTheme" parent="android:Theme.Material.Light"><item name="android:colorPrimary">#FF0000</item><item name="android:colorPrimaryDark">#990000</item><item name="android:colorAccent">#FFFFFF</item></style></resources>

Then apply the theme to your app in the "AndroidManifest.xml" file:


<application
    android:theme="@style/MyTheme"
    ...

You can also apply the theme to individual activities by specifying the "android:theme" attribute in the corresponding "activity" tag.


<activity
    android:name=".MainActivity"
    android:theme="@style/MyTheme"
    ...

Inheritance in Styles and themes


Styles and themes can be inherited from each other to avoid redundancy and promote reusability. The parent attribute can be used to inherit from another style or theme.

Here's an example of inheriting a style:

Create a new style named "MyButtonStyle" that inherits from the predefined Widget.Button style:


<style name="MyButtonStyle" parent="android:Widget.Button"><item name="android:background">#FF0000</item><item name="android:textColor">#FFFFFF</item></style>

Then create a new style named "MyBigButtonStyle" that inherits from "MyButtonStyle" and sets a larger font size:


<style name="MyBigButtonStyle" parent="MyButtonStyle"><item name="android:textSize">24sp</item></style>

Finally, apply the "MyBigButtonStyle" to a Button:


<Button
    android:id="@+id/my_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Click me"
    style="@style/MyBigButtonStyle"/>

Here's an example of inheriting a theme:

Create a new theme named "MyTheme" that inherits from the predefined Theme.Material.Light theme:


<style name="MyTheme" parent="android:Theme.Material.Light"><item name="android:colorPrimary">#FF0000</item><item name="android:colorPrimaryDark">#990000</item><item name="android:colorAccent">#FFFFFF</item></style>

Then create a new theme named "MyDarkTheme" that inherits from "MyTheme" and sets a dark background color:


<style name="MyDarkTheme" parent="MyTheme"><item name="android:windowBackground">#000000</item></style>

Finally, apply the "MyDarkTheme" to an activity in the "AndroidManifest.xml" file:


<activity
    android:name=".MainActivity"
    android:theme="@style/MyDarkTheme"
    ...

Overriding styles and themes programmatically:


Styles and themes can also be overridden programmatically using the ContextThemeWrapper class.

Here's an example of overriding a theme programmatically:

Create a new style named "MyButtonStyle" that sets a red background color:


<style name="MyButtonStyle"><item name="android:background">#FF0000</item></style>

Then create a new theme named "MyTheme" that sets a blue background color:


<style name="MyTheme" parent="android:Theme.Material.Light"><item name="android:colorPrimary">#0000FF</item><item name="android:colorPrimaryDark">#000099</item><item name="android:colorAccent">#FFFFFF</item></style>

Finally, apply the "MyTheme" to an activity in the "AndroidManifest.xml" file and override the button style programmatically:


public class MainActivity extends AppCompatActivity {
    @Override
protected void onCreate(Bundle savedInstanceState) {
        // Override the theme with a new ContextThemeWrapper
ContextThemeWrapper contextThemeWrapper = new ContextThemeWrapper(this, R.style.MyTheme);
LayoutInflater inflater = LayoutInflater.from(contextThemeWrapper);
        View view = inflater.inflate(R.layout.activity_main, null);
        Button button = view.findViewById(R.id.my_button);
        button.setBackgroundResource(R.style.MyButtonStyle);
        setContentView(view);
    }
}

This will set the background color of the button to red, overriding the blue background color set in the "MyTheme".


Handling Events:


Event handling is a crucial aspect of Android development as it allows developers to respond to user actions and interact with the app's UI. Here are some of the most common event handling techniques in Android:


OnClick() method:

This method is used to handle click events for UI components such as buttons, image views, etc. To use this method, you need to implement the View.OnClickListener interface and override the onClick() method. Here's an example:


public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button myButton;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myButton = findViewById(R.id.my_button);
        myButton.setOnClickListener(this);
    }

    @Override
public void onClick(View view) {
        if (view.getId() == R.id.my_button) {
            // Handle button click event
        }
    }
}

onTouch() method:


This method is used to handle touch events for UI components. To use this method, you need to implement the View.OnTouchListener interface and override the onTouch() method. Here's an example:


public class MainActivity extends AppCompatActivity implements View.OnTouchListener {
    private ImageView myImageView;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myImageView = findViewById(R.id.my_image_view);
        myImageView.setOnTouchListener(this);
    }

    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        if (view.getId() == R.id.my_image_view) {
            switch (motionEvent.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    // Handle touch down eventbreak;
                case MotionEvent.ACTION_UP:
                    // Handle touch up eventbreak;
            }
        }
        return true;
    }
}

onItemSelected() method:

This method is used to handle item selection events for UI components such as spinners, list views, etc. To use this method, you need to implement the AdapterView.OnItemSelectedListener interface and override the onItemSelected() and onNothingSelected() methods. Here's an example:


public class MainActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
    private Spinner mySpinner;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mySpinner = findViewById(R.id.my_spinner);
        mySpinner.setOnItemSelectedListener(this);
    }

    @Override
    public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
        // Handle item selection event
    }

    @Override
    public void onNothingSelected(AdapterView<?> adapterView) {
        // Handle no item selected event
    }
}

These are just a few examples of event handling in Android. There are many other events and interfaces that you can use to handle user interactions with your app's UI.


Here is a complete example showing all of the above tasks -

  • Create a new Android Studio project and name it "EventHandlingExample".

  • In the activity_main.xml layout file, add the following UI components:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/my_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click me" />
<ImageView
android:id="@+id/my_image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher_foreground" />
<Spinner
android:id="@+id/my_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@array/my_array" />
</LinearLayout>
  • In the MainActivity.java file, add the following code:


public class MainActivity extends AppCompatActivity implements View.OnClickListener, View.OnTouchListener, AdapterView.OnItemSelectedListener {
    private Button myButton;
    private ImageView myImageView;
    private Spinner mySpinner;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setTheme(R.style.MyTheme);
        setContentView(R.layout.activity_main);
        
        myButton = findViewById(R.id.my_button);
        myButton.setOnClickListener(this);
        
        myImageView = findViewById(R.id.my_image_view);
        myImageView.setOnTouchListener(this);
        
        mySpinner = findViewById(R.id.my_spinner);
        mySpinner.setOnItemSelectedListener(this);
    }

    @Override
public void onClick(View view) {
        if (view.getId() == R.id.my_button) {
            Toast.makeText(this, "Button clicked", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
public boolean onTouch(View view, MotionEvent motionEvent) {
        if (view.getId() == R.id.my_image_view) {
            switch (motionEvent.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    Toast.makeText(this, "Image view touched down", Toast.LENGTH_SHORT).show();
                    break;
                case MotionEvent.ACTION_UP:
                    Toast.makeText(this, "Image view touched up", Toast.LENGTH_SHORT).show();
                    break;
            }
        }
        return true;
    }

    @Override
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
        String selectedItem = adapterView.getItemAtPosition(position).toString();
        Toast.makeText(this, "Selected item: " + selectedItem, Toast.LENGTH_SHORT).show();
    }

    @Override
public void onNothingSelected(AdapterView<?> adapterView) {
        Toast.makeText(this, "No item selected", Toast.LENGTH_SHORT).show();
    }
}
  • In the styles.xml file, add the following style:


<resources><style name="MyTheme" parent="Theme.AppCompat.Light.NoActionBar"><item name="android:windowBackground">@color/my_background_color</item></style></resources>
  • In the strings.xml file, add the following string:


<resources><string name="app_name">
EventHandlingExample
</string>
<string name="my_array">
Item 1, Item 2, Item 3</string>
</resources>
  • In the colors.xml file, add the following color:


<resources><color name="my_background_color">#
  • In the AndroidManifest.xml file, add the following permission:


<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  • Add an image to the project's drawable folder and name it ic_launcher_foreground.png.

  • Run the app on an emulator or a physical device, and test the following:

  • Clicking the "Click me" button should display a toast message.

  • Touching the image view should display a toast message.

  • Selecting an item from the spinner should display a toast message.

  • The app's background color should be set to the color specified in the colors.xml file.

  • The app should have permission to read external storage.

Try this yourself !


That's the end of this tutorial on event handling, styles, and themes in Android app development. We covered a lot of ground, including how to handle button clicks, touch events, and spinner selections, as well as how to define custom styles and themes.

By mastering these concepts, you'll be well on your way to creating more polished and professional Android apps. As always, practice makes perfect, so don't be afraid to experiment and try out different approaches.


Thanks for reading, and happy coding!




bottom of page