Skip to content

Instantly share code, notes, and snippets.

@lakinduboteju
Last active May 11, 2020 17:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lakinduboteju/1a0661a562edcf8cec28377ae1860d74 to your computer and use it in GitHub Desktop.
Save lakinduboteju/1a0661a562edcf8cec28377ae1860d74 to your computer and use it in GitHub Desktop.
Basic example of a custom draggable drawer in Android.
<!-- File : app/src/main/res/layout/activity_main_drawer_closed.xml -->
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:id="@+id/rootConstraintLayout"
tools:context=".MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/drawerConstraintLayout"
android:layout_width="152dp"
android:layout_height="108dp"
android:background="@color/colorPrimaryDark"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="parent" >
<Button
android:id="@+id/button1"
android:layout_width="52dp"
android:layout_height="52dp"
android:text="1"
android:backgroundTint="@color/colorAccent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/button2" />
<Button
android:id="@+id/button2"
android:layout_width="52dp"
android:layout_height="52dp"
android:text="2"
android:backgroundTint="@color/colorAccent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/button1"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<ImageView
android:id="@+id/notch"
android:layout_width="8dp"
android:layout_height="72dp"
android:src="@drawable/drawer_notch"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/drawerConstraintLayout" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- File : app/src/main/res/layout/activity_main_drawer_opened.xml -->
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/rootConstraintLayout"
tools:context=".MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/drawerConstraintLayout"
android:layout_width="152dp"
android:layout_height="108dp"
android:background="@color/colorPrimaryDark"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" >
<Button
android:id="@+id/button1"
android:layout_width="52dp"
android:layout_height="52dp"
android:text="1"
android:backgroundTint="@color/colorAccent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/button2" />
<Button
android:id="@+id/button2"
android:layout_width="52dp"
android:layout_height="52dp"
android:text="2"
android:backgroundTint="@color/colorAccent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/button1"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<ImageView
android:id="@+id/notch"
android:layout_width="8dp"
android:layout_height="72dp"
android:src="@drawable/drawer_notch"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/drawerConstraintLayout" />
</androidx.constraintlayout.widget.ConstraintLayout>
// File : app/build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
minSdkVersion 19
targetSdkVersion 29
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
}
<!-- File : app/src/main/res/drawable/drawer_notch.xml -->
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="4dp" />
<solid android:color="@color/colorAccent" />
</shape>
// File : app/src/main/java/<package_path>/MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.ConstraintSet;
import androidx.core.view.GestureDetectorCompat;
import android.os.Bundle;
import android.transition.TransitionManager;
import android.view.GestureDetector;
import android.view.MotionEvent;
public class MainActivity extends AppCompatActivity {
private boolean mIsDrawerOpened;
private ConstraintLayout mRootConstraintLayout;
private final ConstraintSet mDrawerClosedConstraintSet = new ConstraintSet();
private final ConstraintSet mDrawerOpenedConstraintSet = new ConstraintSet();
private GestureDetectorCompat mGestureDetector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_drawer_closed);
// Drawer is initially closed
mIsDrawerOpened = false;
mRootConstraintLayout = findViewById(R.id.rootConstraintLayout);
mDrawerClosedConstraintSet.clone(this, R.layout.activity_main_drawer_closed);
mDrawerOpenedConstraintSet.clone(this, R.layout.activity_main_drawer_opened);
mGestureDetector = new GestureDetectorCompat(
getApplicationContext(),
new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
// Drag / Fling gesture detected
// TODO: Recongnize unwanted drag / fling gestures and ignore them.
TransitionManager.beginDelayedTransition(mRootConstraintLayout);
// Drawer is closed?
if(!mIsDrawerOpened) {
// Open the drawer
mDrawerOpenedConstraintSet.applyTo(mRootConstraintLayout);
mIsDrawerOpened = true;
}
return true;
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
// Single tap detected
// TODO: If user has tapped on the drawer, do not close it.
TransitionManager.beginDelayedTransition(mRootConstraintLayout);
// Drawer is opened?
if(mIsDrawerOpened) {
// Close the drawer
mDrawerClosedConstraintSet.applyTo(mRootConstraintLayout);
mIsDrawerOpened = false;
}
return true;
}
@Override
public boolean onDown(MotionEvent e) {
return true;
}
}
);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mGestureDetector.onTouchEvent(event);
return super.onTouchEvent(event);
}
}
@lakinduboteju
Copy link
Author

I created this Github gist for a StackOverflow question as the code reference.

@lakinduboteju
Copy link
Author

Answer to the StackOverflow question that fixes the issue has been included in this gist (Revision 2).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment