Installation and Project Setup
Downloading Android Studio
Download location: https://developer.android.google.cn/studio
Installation Process
During installation, accept all default settings;
If you encounter the error "Unable to access Android SDK and-on list", select "Cancel" and the Android SDK will install during subsequent steps.
Creating New Projects
Select template "Empty Activity";
"Save location" specifies the project directory;
Avoid checking the "Use legacy android.support libraries" option.
Project Structure Overview
Virtual Device Setup
Click "AVD Manager" in the upper right corner to install;
For "HAXM is not installed" errors, follow prompts to install Haxm.
Running Applications
Essential UI Components
TextView Component
<TextView
android:id="@+id/text_display" : assigns an identifier to the TextView component
android:layout_width="200dp" : width of the component
android:layout_height="200dp" : height of the component
android:background="@color/purple_200" : background color of the control, can be an image
android:gravity="center_horizontal" : alignment direction within the control, text for TextView, images for ImageView
android:text="@string/hello" : sets displayed text content
android:textColor="#ffff0000" : font color
android:textSize="20sp" : font size, typically in sp units
android:textStyle="normal" : font style with options: normal (no effect), bold, italic
android:shadowColor="@color/red" : shadow color, requires shadowRadius
android:shadowDx="10.0" : horizontal shadow offset
android:shadowDy="10.0" : vertical shadow offset
android:shadowRadius="3.0" : shadow blur level, 0.1 becomes font color, recommend 3.0
android:singleLine="true" : display content in single line
android:ellipsize="marquee" : where to truncate text
android:marqueeRepeatLimit="marquee_forever" : animation repeat count
android:focusable="true" : whether can receive focus
android:focusableInTouchMode="true" : controls touch focus behavior>
<requestFocus /> : acquire focus
</TextView>
Button Component
<Button : Button extends TextView
android:id="@+id/action_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/button_selector" : referenced bitmap, add .Bridge after DarkActionBar in themes.xml
android:backgroundTint="@color/button_color_selector" : bitmap color reference
android:onClick="handleButtonClick" : corresponds to handleButtonClick(View) method in MainActivity
android:text="@string/button_text"
/>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_baseline_ac_unit_24" : referenced Drawable bitmap
android:color="@color/green" : referenced color
android:state_focused="true" : has focus
android:state_pressed="true" : button pressed
android:state_enabled="true" : control enabled
android:state_selected="true" : control selected, for scroll wheels
android:state_checked="true" : control checked
android:state_checkable="true" : control checkable, e.g., checkbox
></item>
</selector>
// Execution order: touch event (returns true, stops subsequent events) -> long press event (returns true, stops subsequent events) -> click event
View actionBtn = findViewById(R.id.action_button);
// Click event
actionBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("clicked");
}
});
// Long press event
actionBtn.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
System.out.println("long pressed");
return false;
}
});
// Touch event
actionBtn.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
System.out.println("touched" + event.getAction());
return false;
}
});
Four methods to implement click events:
1. Internal class implementing View.OnClickListener interface
2. Anonymous internal class implementing interface
3. Current class implementing interface
4. Adding onClick attribute to Button tag
EditText Component
<EditText
android:id="@+id/input_field"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#99000000" : background color
android:drawableLeft="@drawable/ic_baseline_person_outline_24" : adds image at specified position
android:drawablePadding="20dp" : spacing between image and input
android:hint="Enter text here" : input prompt
android:inputType="number" : input type
android:paddingLeft="20dp" : spacing between content and border
android:textColorHint="@color/green" : hint text color
></EditText>
// Retrieve input content
EditText inputField = findViewById(R.id.input_field);
System.out.println(inputField.getText().toString());
ImageView Component
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true" : adjust View boundaries
android:maxWidth="200dp" : maximum width
android:maxHeight="200dp" : maximum height
android:scaleType="fitCenter" : image scaling type
android:src="@drawable/image_resource" : image resource
></ImageView>
ProgressBar Componant
<ProgressBar
style="?android:attr/progressBarStyleHorizontal" : horizontal progress bar
android:layout_width="200dp"
android:layout_height="wrap_content"
android:indeterminate="false" : when true, progress bar doesn't show exact progress
android:max="100" : maximum value
android:progress="30" : completed progress value
android:visibility="gone" : whether to display progress bar
></ProgressBar>
Notification Implementation
public class MainActivity extends AppCompatActivity {
private NotificationManager notificationManager;
private Notification notificationObject;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel("channel_id", "Notifications", NotificationManager.IMPORTANCE_HIGH);
notificationManager.createNotificationChannel(channel);
}
Intent intent = new Intent(this, NotificationActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
notificationObject = new NotificationCompat.Builder(this, "channel_id")
.setContentTitle("Official Notification")
.setContentText("Exploring the world")
.setSmallIcon(R.drawable.ic_baseline_person_outline_24)
.setColor(Color.parseColor("#00ff00"))
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.img))
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.build();
}
public void sendNotification(View view) {
notificationManager.notify(1, notificationObject);
}
public void removeNotification(View view) {
notificationManager.cancel(1);
}
}
Toolbar Configuration
xmlns:app="http://schemas.android.com/apk/res-auto"
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#ffff0000"
app:logo="@drawable/ic_baseline_ac_unit_24"
app:navigationIcon="@drawable/ic_baseline_arrow_back_24"
app:subtitle="Subtitle"
app:subtitleTextColor="@color/black"
app:title="Main Title"
app:titleMarginStart="100dp"
app:titleTextColor="@color/green">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="Custom Title" />
</androidx.appcompat.widget.Toolbar>
AlertDialog Variations
Basic Dialog
public void showDialogButton(View view) {
View customDialogView = getLayoutInflater().inflate(R.layout.activity_notification, null);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setIcon(R.drawable.ic_baseline_person_outline_24)
.setTitle("Modal Window")
.setMessage("This is Chinese text")
.setView(customDialogView)
.setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.e("", "Confirmed clicked");
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.e("", "Cancel clicked");
}
})
.setNeutralButton("Middle", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.e("", "Middle clicked");
}
})
.create()
.show();
}
Single Choice Dialog
public void handleSelectionClick(View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
String[] choices = {"Jujingyi", "Huangtingting", "Mengmeiqi"};
builder.setSingleChoiceItems(choices, -1, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String selected = choices[which];
Toast.makeText(getApplicationContext(), selected, Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
});
builder.show();
}
Multiple Choice Dialog
public void handleMultipleClick(View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
String[] choices = {"Jujingyi", "Huangtingting", "Mengmeiqi", "Jiangzhenyu", "Angela"};
boolean[] selections = {false, true, false, false, true};
builder.setMultiChoiceItems(choices, selections, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
}
});
builder.setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < selections.length; i++) {
if (selections[i]) {
result.append(choices[i] + ",");
}
}
Toast.makeText(getApplicationContext(), result.toString(), Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
});
builder.show();
}
Progress Dialog
public void handleProgressClick(View view) {
ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setTitle("Loading...");
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.show();
new Thread() {
@Override
public void run() {
progressDialog.setMax(100);
for (int progress = 0; progress < 100; progress++) {
progressDialog.setProgress(progress);
SystemClock.sleep(50);
}
progressDialog.dismiss();
}
}.start();
}
PopupWindow Implementation
public void showPopupButton(View view) {
View popupLayout = getLayoutInflater().inflate(R.layout.activity_popupwindow, null);
Button confirmBtn = popupLayout.findViewById(R.id.btn1);
Button dismissBtn = popupLayout.findViewById(R.id.btn2);
PopupWindow popup = new PopupWindow(popupLayout,
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
true);
popup.setBackgroundDrawable(getResources().getDrawable(R.drawable.img));
popup.showAsDropDown(view);
confirmBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e("", "Confirm clicked");
}
});
dismissBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e("", "Cancel clicked");
popup.dismiss();
}
});
}
Top Right Menu
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, 1, 0, "Forward");
menu.add(0, 2, 0, "Backward");
menu.add(0, 3, 0, "Home");
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
int menuItemId = item.getItemId();
if (menuItemId == 1) {
System.out.println("Forward");
} else if (menuItemId == 2) {
System.out.println("Backward");
} else if (menuItemId == 3) {
System.out.println("Home");
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onMenuOpened(int featureId, Menu menu) {
return super.onMenuOpened(featureId, menu);
}
}
Searchable Dropdown
<?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">
<AutoCompleteTextView
android:id="@+id/auto_complete_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:completionThreshold="2" />
</LinearLayout>
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AutoCompleteTextView autoCompleteInput = findViewById(R.id.auto_complete_input);
String[] suggestions = new String[]{"option_a", "option_b", "option_c", "option_d"};
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, suggestions);
autoCompleteInput.setAdapter(adapter);
}
}