I have been trying to use Floating Action Button. I tried to use some of the resources suggested on here and the links were great; however, I couldn't use alot of them because of problems with dependicies. I tried to fix it but it got more messed up. Long story short, I use the following code as a way to bypass dependicies in my bundle. I got the button to work; however, I couldn't figure out how to have options to appear when the button is clicked. I tried on clicklistener and other ways but I always got an error.
public class FloatingActionButton extends View {
Context context;
Paint mButtonPaint;
Paint mDrawablePaint;
Bitmap mBitmap;
boolean mHidden = false;
public FloatingActionButton(Context context) {
super(context);
this.context = context;
init(Color.WHITE);
}
public void init(int color) {
setWillNotDraw(false);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
mButtonPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mButtonPaint.setColor(color);
mButtonPaint.setStyle(Paint.Style.FILL);
mButtonPaint.setShadowLayer(10.0f, 0.0f, 3.5f, Color.argb(100, 0, 0, 0));
mDrawablePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
setClickable(true);
canvas.drawCircle(getWidth() / 2, getHeight() / 2, (float) (getWidth() / 2.6), mButtonPaint);
canvas.drawBitmap(mBitmap, (getWidth() - mBitmap.getWidth()) / 2,
(getHeight() - mBitmap.getHeight()) / 2, mDrawablePaint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
setAlpha(1.0f);
} else if (event.getAction() == MotionEvent.ACTION_DOWN) {
setAlpha(0.6f);
}
return super.onTouchEvent(event);
}
public void setColor(int color) {
init(color);
}
public void setDrawable(Drawable drawable) {
mBitmap = ((BitmapDrawable) drawable).getBitmap();
invalidate();
}
public void hide() {
if (!mHidden) {
ObjectAnimator scaleX = ObjectAnimator.ofFloat(this, "scaleX", 1, 0);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(this, "scaleY", 1, 0);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(scaleX, scaleY);
animSetXY.setInterpolator(new AccelerateInterpolator());
animSetXY.setDuration(100);
animSetXY.start();
mHidden = true;
}
}
public void show() {
if (mHidden) {
ObjectAnimator scaleX = ObjectAnimator.ofFloat(this, "scaleX", 0, 1);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(this, "scaleY", 0, 1);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(scaleX, scaleY);
animSetXY.setInterpolator(new OvershootInterpolator());
animSetXY.setDuration(200);
animSetXY.start();
mHidden = false;
}
}
public boolean isHidden() {
return mHidden;
}
public static class Builder {
private FrameLayout.LayoutParams params;
private final Activity activity;
int gravity = Gravity.BOTTOM | Gravity.RIGHT; // default bottom right
Drawable drawable;
int color = Color.WHITE;
int size = 0;
float scale = 0;
/**
* Constructor using a context for this builder and the
* {#link com.williammora.openfeed.widgets.FloatingActionButton} it creates
* #param context
*/
public Builder(Activity context) {
scale = context.getResources().getDisplayMetrics().density;
// The calculation (value * scale + 0.5f) is a widely used to convert to dps to pixel
// units based on density scale
// see <a href="http://developer.android.com/guide/practices/screens_support.html">
// developer.android.com (Supporting Multiple Screen Sizes)</a>
size = (int) (72 * scale + 0.5f); // default size is 72dp by 72dp
params = new FrameLayout.LayoutParams(size, size);
params.gravity = gravity;
this.activity = context;
}
public Builder withGravity(int gravity) {
this.gravity = gravity;
return this;
}
public Builder withMargins(int left, int top, int right, int bottom) {
params.setMargins((int) (left * scale + 0.5f), (int) (top * scale + 0.5f),
(int) (right * scale + 0.5f), (int) (bottom * scale + 0.5f));
return this;
}
public Builder withDrawable(final Drawable drawable) {
this.drawable = drawable;
return this;
}
public Builder withColor(final int color) {
this.color = color;
return this;
}
public Builder withSize(int size) {
size = (int) (size * scale + 0.5f);
params = new FrameLayout.LayoutParams(size, size);
return this;
}
public FloatingActionButton create() {
final FloatingActionButton button = new FloatingActionButton(activity);
button.setColor(this.color);
button.setDrawable(this.drawable);
params.gravity = this.gravity;
ViewGroup root = (ViewGroup) activity.findViewById(android.R.id.content);
root.addView(button, params);
return button;
}
}
}
FloatingActionButton mFab = new FloatingActionButton.Builder(this)
.withColor(getResources().getColor(R.color.primaryColorDark))
.withDrawable(getResources().getDrawable(R.drawable.ic_launcher))
.withSize(72)
.withMargins(0, 0, 16, 16)
.create();
MainActivity
FloatingActionButton mFab = new FloatingActionButton.Builder(this)
.withColor(getResources().getColor(R.color.primaryColorDark))
.withDrawable(getResources().getDrawable(R.drawable.ic_launcher))
.withSize(72)
.withMargins(0, 0, 16, 16)
.create();
Just put compile 'com.android.support:design:22.2.1' in your module app dependencies.
In your xml:
<android.support.design.widget.FloatingActionButton
style="#style/<your_style>"
android:src="#drawable/<your_icon_src>"
app:layout_anchor="#id/<if using along with list put your listID here>"
app:layout_anchorGravity="bottom|right|end"
android:id="#+id/fab"
/>
In you java:
FloatingActionButton fab = (FloatingActionButton)findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
There is no need to create FloatingActionButton by yourself now. The new com.android.support:design:23.0.1 can do that for you. Just follow the below procedure.
1.Add this line compile 'com.android.support:design:23.0.1' in dependencies in your build.gradle in Android Studio
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:design:23.0.1'
}
2.To create a FloatingActionButton using the following xml file.
<android.support.design.widget.CoordinatorLayout
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:id="#+id/YourEventsLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--Add other elements here-->
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|bottom"
android:layout_margin="16dp"
android:src="#drawable/ic_add_white_24dp"
app:elevation="6dp"
app:fabSize="normal"
app:pressedTranslationZ="12dp" />
</android.support.design.widget.CoordinatorLayout>
In MainActivity in onCreate method set setOnClickListener as follows
FloatingActionButton fab;
fab = (FloatingActionButton) getView().findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Do what you want here
}
});
This is how you create a floating action button.
build.gradle
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.0.0'
compile 'com.android.support:design:23.0.1'
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="#+id/viewOne"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.6"
android:background="#android:color/holo_blue_light"
android:orientation="horizontal"/>
<LinearLayout
android:id="#+id/viewTwo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.4"
android:background="#android:color/holo_orange_light"
android:orientation="horizontal"/>
</LinearLayout>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:clickable="true"
android:src="#drawable/ic_done"
app:layout_anchor="#id/viewOne"
app:layout_anchorGravity="bottom|right|end"
app:backgroundTint="#FF0000"
app:rippleColor="#FFF" />
</android.support.design.widget.CoordinatorLayout>
</RelativeLayout>
MainActivity.java
package com.ahotbrew.floatingactionbutton;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FloatingActionButton FAB = (FloatingActionButton) findViewById(R.id.fab);
FAB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "Would you like a coffee?", Toast.LENGTH_SHORT).show();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Hope that complete example helps someone.
The example is from http://www.ahotbrew.com/android-floating-action-button/
It also shows how to place the button in other locations if interested.
You don't have to create FAB now, its already available, just follow this Link
you need to add
<RelativeLayout
...
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.design.widget.FloatingActionButton
android:id="#+id/myFAB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_plus_sign"
app:elevation="4dp"
... />
</RelativeLayout>
and
FloatingActionButton myFab = (FloatingActionButton) myView.findViewById(R.id.myFAB);
myFab.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
doMyThing();
}
});
in code behind
For more detail follow :
FloatingActionButton example with Support Library
Related
I am adding a menu to an action bar item. The menu will contain vertical text for each item. What the menu contains is not important. I basically just want to create my own view that will pop up when I press an action bar item. So for the purposes of this question, you could imagine my view as a big black box.
The image on the right was made with Gimp. It is what I am trying to do, not what I have accomplished yet.
What I have tried
In order to update an old app with the Material Design theme, I've been going through all the lessons in the Android documentation for adding the app bar. Since my vertical text menu doesn't fit the common cases, I have to make a custom Action Provider. The documentation does not provide a full example for a custom action provider, though. The best I could find was this Stack Overflow answer.
The best I have been able to do (with a black View representing my future menu) is shown in the following image:
The star in the image above currently has the action provider. However, the custom view gets clipped off within the action bar. How do I make it float over everything? Also, I don't want it appearing until I click on the action bar item. Currently, though, it just shows right away.
Code
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// setup toolbar
Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
setSupportActionBar(myToolbar);
...
}
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
// User chose the "Settings" item, show the app settings UI...
return true;
case R.id.action_favorite:
// User chose the "Favorite" action, mark the current item
// as a favorite...
return true;
default:
// If we got here, the user's action was not recognized.
// Invoke the superclass to handle it.
return super.onOptionsItemSelected(item);
}
}
...
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.v7.widget.Toolbar
android:id="#+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"/>
...
menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_favorite"
android:icon="#drawable/ic_star_black_24dp"
android:title="#string/menu_favorites"
app:actionProviderClass="com.example.chimee.MyActionProvider"
app:showAsAction="ifRoom"/>
<item android:id="#+id/action_settings"
android:title="#string/menu_item_settings"
app:showAsAction="never"/>
</menu>
MyActionProvider.java
import android.content.Context;
import android.support.v4.view.ActionProvider;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
public class MyActionProvider extends ActionProvider {
private Context mContext;
public MyActionProvider(Context context) {
super(context);
mContext = context;
}
// for versions older than api 16
#Override
public View onCreateActionView() {
// Inflate the action provider to be shown on the action bar.
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
View providerView =
layoutInflater.inflate(R.layout.my_action_provider, null);
View myView =
(View) providerView.findViewById(R.id.blackView);
myView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("myTag", "black view was clicked");
}
});
return providerView;
}
#Override
public View onCreateActionView(MenuItem forItem) {
// TODO: don't just repeat all this code here from above.
// Inflate the action provider to be shown on the action bar.
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
View providerView =
layoutInflater.inflate(R.layout.my_action_provider, null);
View myView =
(View) providerView.findViewById(R.id.blackView);
myView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("myTag", "black view was clicked");
}
});
return providerView;
}
}
my_action_provider.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="?attr/actionButtonStyle"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="?attr/actionBarItemBackground"
android:focusable="true" >
<View
android:id="#+id/blackView"
android:layout_width="200dp"
android:layout_height="150dp"
android:background="#000000" />
</LinearLayout>
I would be glad to see an example of any fully functioning custom action provider that shows a view outside of the action bar frame.
If You didn't find Custom Action Provider based solution, may be You want use Custom Toolbar & PopupWindow-based workaround which means:
1) create custom Toolbar with ImageButton as menu button and replace ActionBar with it (like in that post of Machado);
2) create PopupWindow with custom layout for menu items with vertical text;
3) add onClickListener to ImageButton from p.1 which show PopupWindow from p.2.
Layout of custom Toolbar (action_bar.xml) may be something like:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="fill_horizontal"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:background="#color/colorPrimary"
android:elevation="4dp"
android:layout_height="?attr/actionBarSize">
</android.support.v7.widget.Toolbar>
</RelativeLayout>
Layout of MainActivity (activity_main.xml) which use it:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="#+id/activity_main"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="0dp"
tools:context="<your_package_name>.MainActivity">
<include
android:id="#+id/tool_bar"
layout="#layout/action_bar"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:layout_marginStart="31dp"
android:layout_below="#+id/tool_bar"
android:layout_alignParentStart="true"
android:layout_marginTop="31dp"/>
</RelativeLayout>
ImageButton as "main popup menu" button described in main_menu.xml file this way (more in this post of ASH):
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/menu_button"
android:icon="#drawable/ic_more_vert"
android:title=""
app:showAsAction="always"
app:actionViewClass="android.widget.ImageButton"/>
</menu>
For vertical text of menu items You can use, for example, custom View like VerticalLabelView from this of kostmo:
public class VerticalLabelView extends View {
private TextPaint mTextPaint;
private String mText;
private int mAscent;
private Rect text_bounds = new Rect();
final static int DEFAULT_TEXT_SIZE = 15;
public VerticalLabelView(Context context) {
super(context);
initLabelView();
}
public VerticalLabelView(Context context, AttributeSet attrs) {
super(context, attrs);
initLabelView();
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.VerticalLabelView);
CharSequence s = a.getString(R.styleable.VerticalLabelView_text);
if (s != null) setText(s.toString());
setTextColor(a.getColor(R.styleable.VerticalLabelView_textColor, 0xFF000000));
int textSize = a.getDimensionPixelOffset(R.styleable.VerticalLabelView_textSize, 0);
if (textSize > 0) setTextSize(textSize);
a.recycle();
}
private final void initLabelView() {
mTextPaint = new TextPaint();
mTextPaint.setAntiAlias(true);
mTextPaint.setTextSize(DEFAULT_TEXT_SIZE);
mTextPaint.setColor(0xFF000000);
mTextPaint.setTextAlign(Align.CENTER);
setPadding(3, 3, 3, 3);
}
public void setText(String text) {
mText = text;
requestLayout();
invalidate();
}
public void setTextSize(int size) {
mTextPaint.setTextSize(size);
requestLayout();
invalidate();
}
public void setTextColor(int color) {
mTextPaint.setColor(color);
invalidate();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
mTextPaint.getTextBounds(mText, 0, mText.length(), text_bounds);
setMeasuredDimension(
measureWidth(widthMeasureSpec),
measureHeight(heightMeasureSpec));
}
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text
result = text_bounds.height() + getPaddingLeft() + getPaddingRight();
if (specMode == MeasureSpec.AT_MOST) {
// Respect AT_MOST value if that was what is called for by measureSpec
result = Math.min(result, specSize);
}
}
return result;
}
private int measureHeight(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
mAscent = (int) mTextPaint.ascent();
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text
result = text_bounds.width() + getPaddingTop() + getPaddingBottom();
if (specMode == MeasureSpec.AT_MOST) {
// Respect AT_MOST value if that was what is called for by measureSpec
result = Math.min(result, specSize);
}
}
return result;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float text_horizontally_centered_origin_x = getPaddingLeft() + text_bounds.width()/2f;
float text_horizontally_centered_origin_y = getPaddingTop() - mAscent;
canvas.translate(text_horizontally_centered_origin_y, text_horizontally_centered_origin_x);
canvas.rotate(-90);
canvas.drawText(mText, 0, 0, mTextPaint);
}
}
(NB: may be You need to customize paddings of VerticalLabelView: on line
result = text_bounds.height() + getPaddingLeft() + getPaddingRight() + 16;
add "+16" for better padding)
and attrs.xml for VerticalLabelView class:
<resources>
<declare-styleable name="VerticalLabelView">
<attr name="text" format="string" />
<attr name="textColor" format="color" />
<attr name="textSize" format="dimension" />
</declare-styleable>
</resources>
Layout for PopupWindow (menu_layout.xml) in this case might be like:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/menu_root"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="#dimen/activity_horizontal_margin">
<<your_package_name>.VerticalLabelView
android:id="#+id/menu_item1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#android:color/white"
android:textSize="18sp"
android:layout_margin="16dp"
android:padding="4dp"
android:text="Vertical menu item 1"/>
<<your_package_name>.VerticalLabelView
android:id="#+id/menu_item2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#android:color/white"
android:textSize="18sp"
android:layout_margin="16dp"
android:padding="4dp"
android:text="Vertical menu item 2"/>
<<your_package_name>.VerticalLabelView
android:id="#+id/menu_item3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#android:color/white"
android:textSize="18sp"
android:layout_margin="16dp"
android:padding="4dp"
android:text="Vertical menu item 3"/>
<<your_package_name>.VerticalLabelView
android:id="#+id/menu_item4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#android:color/white"
android:textSize="18sp"
android:layout_margin="16dp"
android:padding="4dp"
android:text="Vertical menu item 4"/>
</LinearLayout>
And MainActivity class can be like:
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private Toolbar mToolbar;
private int mToolbarTitleColor;
private ImageButton mMainMenuButton;
private int mActionBarSize;
private PopupWindow mPopupMenu;
private int mTextSize = 48;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TypedValue tv = new TypedValue();
if (getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
mActionBarSize = TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics());
}
mToolbarTitleColor = Color.WHITE;
mToolbar = (Toolbar) findViewById(R.id.toolbar);
mToolbar.setTitleTextColor(mToolbarTitleColor);
setSupportActionBar(mToolbar);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
Drawable menuIcon = ContextCompat.getDrawable(this, R.drawable.ic_more_vert);
menuIcon.setColorFilter(mToolbarTitleColor, PorterDuff.Mode.SRC_ATOP);
getMenuInflater().inflate(R.menu.main_menu, menu);
mMainMenuButton = (ImageButton) menu.findItem(R.id.menu_button).getActionView();
mMainMenuButton.setBackground(null);
mMainMenuButton.setImageDrawable(menuIcon);
mMainMenuButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mPopupMenu != null && mPopupMenu.isShowing()) {
mPopupMenu.dismiss();
}
mPopupMenu = createPopupMenu();
mPopupMenu.showAtLocation(v, Gravity.TOP | Gravity.RIGHT, 0, mActionBarSize);
}
});
return true;
}
public PopupWindow createPopupMenu() {
final PopupWindow popupWindow = new PopupWindow(this);
LayoutInflater inflater = getLayoutInflater();
View popupView = inflater.inflate(R.layout.menu_layout, null);
VerticalLabelView menuItem1 = (VerticalLabelView)popupView.findViewById(R.id.menu_item1);
menuItem1.setOnClickListener(mOnMenuItemClickListener);
menuItem1.setText("Vertical menu item 1");
menuItem1.setTextColor(Color.WHITE);
menuItem1.setTextSize(mTextSize);
VerticalLabelView menuItem2 = (VerticalLabelView)popupView.findViewById(R.id.menu_item2);
menuItem2.setOnClickListener(mOnMenuItemClickListener);
menuItem2.setText("Vertical menu item 2");
menuItem2.setTextColor(Color.WHITE);
menuItem2.setTextSize(mTextSize);
VerticalLabelView menuItem3 = (VerticalLabelView)popupView.findViewById(R.id.menu_item3);
menuItem3.setOnClickListener(mOnMenuItemClickListener);
menuItem3.setText("Vertical menu item 3");
menuItem3.setTextColor(Color.WHITE);
menuItem3.setTextSize(mTextSize);
VerticalLabelView menuItem4 = (VerticalLabelView)popupView.findViewById(R.id.menu_item4);
menuItem4.setOnClickListener(mOnMenuItemClickListener);
menuItem4.setText("Vertical menu item 4");
menuItem4.setTextColor(Color.WHITE);
menuItem4.setTextSize(mTextSize);
popupWindow.setFocusable(true);
popupWindow.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
popupWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
popupWindow.setContentView(popupView);
return popupWindow;
}
private View.OnClickListener mOnMenuItemClickListener = new View.OnClickListener() {
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.menu_item1: {
Log.d(TAG, "menu_item1");
}
break;
case R.id.menu_item2: {
Log.d(TAG, "menu_item2");
}
break;
case R.id.menu_item3: {
Log.d(TAG, "menu_item3");
}
case R.id.menu_item4: {
Log.d(TAG, "menu_item4");
}
break;
default: {
}
}
if (mPopupMenu != null && mPopupMenu.isShowing()) {
mPopupMenu.dismiss();
}
}
};
}
Ultimatly, as result You should receive something like that:
P.S. Of course You need more elegant solution for createPopupMenu().
I am creating SlidingPanelLayout from right to left for the filter purpose.The panel work fine it come out from right side and does animation but when Animation is stop it directly go to left side full but I want the ratio is 70% means right side panel came out 70% of the total screen and when click again it goes to hind and full Activity is display.
When first time Animation is stop the side panel goes to left side in the screenshot .But I want it right side.
ScreenShot :
but i want to display it write side and when click again it will go right side and hide again.
activity_inventory.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#e6e6e6"
android:id="#+id/mainLayout"
tools:context="com.example.softeng.jogi.InventoryActivity">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/backLayout"
tools:ignore="NotSibling">
</RelativeLayout>
<include
layout="#layout/filter"/>
<com.rey.material.widget.FloatingActionButton
android:id="#+id/button_bt_float_wave_color"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
style="#style/LightFABWaveColor"
android:layout_margin="8dp"/>
</RelativeLayout>
filter.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:id="#+id/filter_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0072BA"
android:visibility="invisible">
</RelativeLayout>
</RelativeLayout>
filterAnimation.java
public class FilterAnimation implements Animation.AnimationListener
{
Context context;
RelativeLayout filterLayout, otherLayout;
private Animation filterSlideIn, filterSlideOut, otherSlideIn, otherSlideOut;
private static int otherLayoutWidth, otherLayoutHeight;
private boolean isOtherSlideOut = false;
private int deviceWidth;
private int margin;
public FilterAnimation(Context context)
{
this.context = context;
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
deviceWidth = displayMetrics.widthPixels; // as my animation is x-axis related so i gets the device width and will use that width,so that this sliding menu will work fine in all screen resolutions
}
public void initializeFilterAnimations(RelativeLayout filterLayout)
{
this.filterLayout = filterLayout;
filterSlideIn = AnimationUtils.loadAnimation(context, R.anim.filter_slide_in);
filterSlideOut = AnimationUtils.loadAnimation(context, R.anim.filter_slide_out);
}
public void initializeOtherAnimations(RelativeLayout otherLayout)
{
this.otherLayout = otherLayout;
otherLayoutWidth = otherLayout.getWidth();
otherLayoutHeight = otherLayout.getHeight();
otherSlideIn = AnimationUtils.loadAnimation(context, R.anim.other_slide_in);
otherSlideIn.setAnimationListener(this);
otherSlideOut = AnimationUtils.loadAnimation(context, R.anim.other_slide_out);
otherSlideOut.setAnimationListener(this);
}
public void toggleSliding()
{
if(isOtherSlideOut) //check if findLayout is already slided out so get so animate it back to initial position
{
filterLayout.startAnimation(filterSlideOut);
filterLayout.setVisibility(View.INVISIBLE);
otherLayout.startAnimation(otherSlideIn);
}
else //slide findLayout Out and filterLayout In
{
otherLayout.startAnimation(otherSlideOut);
filterLayout.setVisibility(View.VISIBLE);
filterLayout.startAnimation(filterSlideIn);
}
}
#Override
public void onAnimationEnd(Animation animation)
{
if(isOtherSlideOut) //Now here we will actually move our view to the new position,because animations just move the pixels not the view
{
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(otherLayoutWidth, otherLayoutHeight);
otherLayout.setLayoutParams(params);
isOtherSlideOut = false;
}
else
{
margin = (deviceWidth * 70) / 100; //here im coverting device percentage width into pixels, in my other_slide_in.xml or other_slide_out.xml you can see that i have set the android:toXDelta="80%",so it means the layout will move to 80% of the device screen,to work across all screens i have converted percentage width into pixels and then used it
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(otherLayoutWidth, otherLayoutHeight);
params.leftMargin = margin;
params.rightMargin = -margin; //same margin from right side (negavite) so that our layout won't get shrink
otherLayout.setLayoutParams(params);
isOtherSlideOut = true;
dimOtherLayout();
}
}
#Override
public void onAnimationRepeat(Animation animation)
{
}
#Override
public void onAnimationStart(Animation animation)
{
}
private void dimOtherLayout()
{
AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.5f);
alphaAnimation.setFillAfter(true);
otherLayout.startAnimation(alphaAnimation);
}
}
InventoryActivity.java
public class InventoryActivity extends AppCompatActivity implements View.OnClickListener {
RelativeLayout filterLayout, findLayout;
FilterAnimation filterAnimation;
FloatingActionButton bffilter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_inventory);
assert getSupportActionBar() != null;
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
filterLayout = (RelativeLayout)findViewById(R.id.filter_layout);
findLayout = (RelativeLayout)findViewById(R.id.backLayout);
bffilter = (FloatingActionButton)findViewById(R.id.button_bt_float_wave_color);
bffilter.setOnClickListener(this);
filterAnimation = new FilterAnimation(this);
initializeAnimations();
}
private void initializeAnimations(){
final ViewTreeObserver filterObserver = filterLayout.getViewTreeObserver();
filterObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onGlobalLayout() {
filterLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
int deviceWidth = displayMetrics.widthPixels;
int filterLayoutWidth = (deviceWidth * 70) / 100;
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(filterLayoutWidth, RelativeLayout.LayoutParams.MATCH_PARENT);
filterLayout.setLayoutParams(params);
filterAnimation.initializeFilterAnimations(filterLayout);
}
});
final ViewTreeObserver findObserver = findLayout.getViewTreeObserver();
findObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onGlobalLayout() {
findLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
filterAnimation.initializeOtherAnimations(findLayout);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_inventory, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == android.R.id.home) {
this.finish();
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onClick(View v) {
int id = v.getId();
switch (id){
case R.id.button_bt_float_wave_color:
filterAnimation.toggleSliding();
break;
}
}
}
filter_slide_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/decelerate_interpolator">
<translate
android:fromXDelta="130%"
android:toXDelta="30%"
android:duration="1000" />
</set>
filter_slide_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/decelerate_interpolator">
<translate
android:fromXDelta="30%"
android:toXDelta="130%"
android:duration="1000"/>
</set>
other_slide_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/decelerate_interpolator">
<translate
android:fromXDelta="-70%"
android:toXDelta="30%"
android:duration="1000"
android:fillEnabled="true"/>
</set>
other_slide_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/decelerate_interpolator" >
<translate
android:fromXDelta="30%"
android:toXDelta="-70%"
android:duration="1000"/>
</set>
My Question : How I want to set right side panel to display and when click again it goes away. simply I my this code I want to remove the panel goes to full left see in the screenshot. the other part working fine.
ScreenShot :
Thanks in Advance.
I think I found the Solution. I am Creating the new Project.
Sliding.java
public class Sliding extends LinearLayout
{
private Paint innerPaint, borderPaint ;
public Sliding(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public Sliding(Context context) {
super(context);
init();
}
private void init() {
innerPaint = new Paint();
innerPaint.setARGB(0, 255, 255, 255); //gray
innerPaint.setAntiAlias(true);
borderPaint = new Paint();
borderPaint.setARGB(255, 255, 255, 255);
borderPaint.setAntiAlias(true);
borderPaint.setStyle(Paint.Style.STROKE);
borderPaint.setStrokeWidth(2);
}
public void setInnerPaint(Paint innerPaint) {
this.innerPaint = innerPaint;
}
public void setBorderPaint(Paint borderPaint) {
this.borderPaint = borderPaint;
}
#Override
protected void dispatchDraw(Canvas canvas) {
RectF drawRect = new RectF();
drawRect.set(0,0, getMeasuredWidth(), getMeasuredHeight());
canvas.drawRoundRect(drawRect, 5, 5, innerPaint);
canvas.drawRoundRect(drawRect, 5, 5, borderPaint);
super.dispatchDraw(canvas);
}
}
Sliding2Activity.java
public class Sliding2Activity extends Activity {
CheckBox c1,c2,c3;
int key=0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sliding2);
final Sliding popup = (Sliding) findViewById(R.id.sliding1);
popup.setVisibility(View.GONE);
final FloatingActionButton btn=(FloatingActionButton)findViewById(R.id.show1);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
if (key == 0) {
key = 1;
popup.setVisibility(View.VISIBLE);
} else if (key == 1) {
key = 0;
popup.setVisibility(View.GONE);
}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_sliding2, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
activity_sliding2.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="right"
android:orientation="horizontal">
<com.rey.material.widget.FloatingActionButton
android:id="#+id/show1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
style="#style/LightFABWaveColor"
android:layout_margin="8dp"
android:layout_gravity="bottom" />
<com.example.softeng.panel.Sliding
android:id="#+id/sliding1"
android:layout_width="250dp"
android:layout_height="match_parent"
android:background="#0072BA"
android:gravity="left"
android:orientation="vertical"
android:padding="1px">
<CheckBox
android:id="#+id/check1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Option1"
android:textColor="#FFFFFF" />
<CheckBox
android:id="#+id/check2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Option2"
android:textColor="#FFFFFF" />
<CheckBox
android:id="#+id/check3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Option3"
android:textColor="#FFFFFF" />
</com.example.softeng.panel.Sliding>
</LinearLayout>
ScreenShot :
Normal screen when Activity is running.
When Click on FloatinActionButton. The layout is change.
When you click again the output is screen one.
I am working on morphing a floating action button (FAB) to a toolbar and things work smoothly and perfectly with the following code:
layout file:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="sg.com.saurabh.designlibraryexpirements.ToolbarMorphActivity">
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|right"
android:layout_marginTop="#dimen/activity_vertical_margin"
android:layout_marginRight="#dimen/activity_vertical_margin"
android:layout_marginBottom="#dimen/activity_vertical_margin"
android:src="#drawable/ic_add" />
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
style="#style/ToolBarTheme"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="top"
android:layout_marginTop="#dimen/activity_vertical_margin"
android:layout_marginBottom="#dimen/activity_vertical_margin"
android:visibility="invisible"
tools:visibility="visible" />
</FrameLayout>
activity:
package sg.com.saurabh.designlibraryexpirements;
import android.animation.Animator;
import android.os.Bundle;
import android.os.Handler;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.view.animation.FastOutLinearInInterpolator;
import android.support.v4.view.animation.LinearOutSlowInInterpolator;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnticipateOvershootInterpolator;
public class ToolbarMorphActivity extends AppCompatActivity {
Toolbar toolbar;
FloatingActionButton fab;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_toolbar_morph);
toolbar = (Toolbar) findViewById(R.id.toolbar);
fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(mFabClickListener);
}
private View.OnClickListener mFabClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
fab.animate()
.rotationBy(45)
.setInterpolator(new AnticipateOvershootInterpolator())
.setDuration(250)
.start();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
fab.setVisibility(View.GONE);
}
},50);
revealToolbar();
}
};
private void revealToolbar() {
toolbar.setVisibility(View.VISIBLE);
int x = (int)fab.getX() + fab.getWidth()/2;
int y = (int)fab.getY() + fab.getHeight()/2;
Animator animator = ViewAnimationUtils.createCircularReveal(toolbar, x, y, 0, toolbar.getWidth())
.setDuration(400);
animator.setInterpolator(new FastOutLinearInInterpolator());
animator.start();
}
private void dismissToolbar() {
int x = (int)fab.getX() + fab.getWidth()/2;
int y = (int)fab.getY() + fab.getHeight()/2;
Animator animator = ViewAnimationUtils.createCircularReveal(toolbar, x, y, toolbar.getWidth(), 0)
.setDuration(400);
animator.setInterpolator(new LinearOutSlowInInterpolator());
animator.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationEnd(Animator animation) {
toolbar.setVisibility(View.INVISIBLE);
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
animator.start();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
fab.setVisibility(View.VISIBLE);
fab.animate()
.rotationBy(-45)
.setInterpolator(new AccelerateInterpolator())
.setDuration(100)
.start();
}
},200);
}
#Override
public void onBackPressed() {
if(toolbar.getVisibility() == View.VISIBLE) {
dismissToolbar();
}
else
super.onBackPressed();
}
}
The circular reveal works as expected for the above layout. However thing break up when I change the layout_gravity of the fab and toolbar to bottom instead of top. The rotate animation works and then the toolbar just appears without the circular reveal animation. I am completely stumped by how that breaks the circular reveal animation.
The fix for you would be to replace:
private void revealToolbar() {
....
int x = (int)fab.getX() + fab.getWidth()/2;
int y = (int)fab.getY() + fab.getHeight()/2;
....
}
by
private void revealToolbar() {
...
int x = (int)fab.getX() + fab.getWidth()/2;
int y = fab.getHeight()/2;
...
}
The reason is that createCircularReveal is taking parameters centerY and centerX as coordinates of the center of the animating circle, relative to view (i.e. Toolbar, in our case).
See method ViewAnimationUtils.createCircularReveal definition:
........
* #param view The View will be clipped to the animating circle.
* #param centerX The x coordinate of the center of the animating circle, relative to
* <code>view</code>.
* #param centerY The y coordinate of the center of the animating circle, relative to
* <code>view</code>.
* #param startRadius The starting radius of the animating circle.
* #param endRadius The ending radius of the animating circle.
*/
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I would like to know how to make a layout, like in a Facebook App. I understand, not only me alone looking for it, but I cannot to find the correct words for the search system to find it. And may be here somebody will give me a good link with a sample code. I like a menu, which shows up from the left side in their App.
You can go for any of this link below you like, there are lots of docs and tutorial available.
Android sliding menu demo
Facebook-like slide out navigation for Android
How To Create A Slide-In MenuList, Like In Facebook App
Hope it will help you.
If you need a simple but effective one then you can see the code. I was using it in my last project.
You can download full source code here.
You can check my blog too if it helped you.
Main layout : res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<com.banglardin.test_code.SlidingView
xmlns:android = "http://schemas.android.com/apk/res/android"
android:layout_width ="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="#+id/list_activity_layout" >
<!-- Just make your sliding layout here -->
<LinearLayout
android:layout_width ="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#FF34495E"
android:id="#+id/slide_bar_list_activity" >
<!-- All the layout of sliding goes here -->
</LinearLayout>
<!-- Just make your content layout here -->
<LinearLayout
android:layout_width ="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#FF112131"
android:id="#+id/content_bar_list_activity" >
<!-- All the layout of content goes here -->
<RelativeLayout
android:id = "#+id/head1"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_alignParentTop = "true"
android:background="#336699"
android:maxWidth="48dp" >
<ImageButton
android:id ="#+id/main_menu_action_left_of_lable"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_alignParentLeft = "true"
android:layout_centerVertical ="true"
android:layout_weight="1"
android:src="#drawable/option_menu"
android:background="#drawable/all_image_button_press"
android:padding="5dp"/>
<!-- Title lable Of home bar. -->
<TextView
android:id ="#+id/main_toptext"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:gravity="center"
android:layout_weight="2"
android:shadowDy=".4"
android:shadowDx=".4"
android:clickable="true"
android:shadowRadius=".7"
android:shadowColor="#000000"
android:textColor = "#ffffff"
android:layout_toRightOf="#+id/main_menu_action_left_of_lable"
android:layout_toLeftOf="#+id/main_right_of_lable"
android:layout_centerInParent ="true"
android:textSize = "18dp"
android:layout_centerVertical ="true"
android:padding="5dp"
android:text = " Shiba prasad jana "
android:singleLine = "true"/>
<!-- Search -->
<ImageButton
android:id ="#+id/main_right_of_lable"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_alignParentRight = "true"
android:layout_centerVertical ="true"
android:layout_weight="1"
android:src="#drawable/search_icon"
android:background="#drawable/all_image_button_press"
android:padding="5dp"/>
</RelativeLayout>
</LinearLayout>
MainActivity: src/package_name/MainActivity
package com.banglardin.test_code;
import android.app.*;
import android.os.*;
import android.view.*;
import android.widget.*;
public class MainActivity extends Activity implements SlidingView.Listener {
protected SlidingView mSlidingView;
protected ImageButton menu;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
mSlidingView=(SlidingView)findViewById(R.id.list_activity_layout);
mSlidingView.setListener(this);
menu = (ImageButton) findViewById(R.id.main_menu_action_left_of_lable);
menu.setOnClickListener(new View.OnClickListener(){
public void onClick(View p1){
mSlidingView.toggleSidebar();
}
}
);
}
public void onSidebarOpened() {
}
public void onSidebarClosed() {
}
public boolean onContentTouchedWhenOpening() {
return false;
}
}
SlidingView : src/package_name/SlidingView
package com.banglardin.test_code;
import android.util.*;
import android.view.*;
import android.view.animation.*;
import android.content.Context;
public class SlidingView extends ViewGroup {
public final static int DURATION = 400; // time to show slding animation
protected boolean mPlaceLeft = true;
protected boolean mOpened;
protected View mSidebar;
protected View mContent;
protected int mSidebarWidth =-1; /* assign default value. It will be overwrite
in onMeasure by Layout xml resource. */
protected Animation mAnimation;
protected OpenListener mOpenListener;
protected CloseListener mCloseListener;
protected Listener mListener;
protected boolean mPressed = false;
public SlidingView(Context context) {
this(context, null);
int mSidebarWidth = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,50, getResources().getDisplayMetrics());
}
public SlidingView
(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public void onFinishInflate() {
super.onFinishInflate();
mSidebar = findViewById(R.id.slide_bar_list_activity);
mContent = findViewById(R.id.content_bar_list_activity);
if (mSidebar == null) {
throw new NullPointerException("no view id = animation_sidebar");
}
if (mContent == null) {
throw new NullPointerException("no view id = animation_content");
}
mOpenListener = new OpenListener(mSidebar, mContent);
mCloseListener = new CloseListener(mSidebar, mContent);
}
#Override
public void onLayout(boolean changed, int l, int t, int r, int b) {
/* the title bar assign top padding, drop it */
int sidebarLeft = l;
if (!mPlaceLeft) {
sidebarLeft = r - mSidebarWidth;
}
mSidebar.layout(sidebarLeft,
0,
sidebarLeft + mSidebarWidth,
0 + mSidebar.getMeasuredHeight());
if (mOpened) {
if (mPlaceLeft) {
mContent.layout(l + mSidebarWidth, 0, r + mSidebarWidth, b);
} else {
mContent.layout(l - mSidebarWidth, 0, r - mSidebarWidth, b);
}
} else {
mContent.layout(l, 0, r, b);
}
}
#Override
public void onMeasure(int w, int h) {
super.onMeasure(w, h);
super.measureChildren(w, h);
mSidebarWidth = mSidebar.getMeasuredWidth();
}
#Override
protected void measureChild(View child, int parentWSpec, int parentHSpec) {
/* the max width of Sidebar is 90% of Parent */
if (child == mSidebar) {
int mode = MeasureSpec.getMode(parentWSpec);
int width = (int)(getMeasuredWidth() * 0.9);
super.measureChild(child, MeasureSpec.makeMeasureSpec(width, mode), parentHSpec);
} else {
super.measureChild(child, parentWSpec, parentHSpec);
}
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (!isOpening()) {
return false;
}
int action = ev.getAction();
if (action != MotionEvent.ACTION_UP
&& action != MotionEvent.ACTION_DOWN) {
return false;
}
/* if user press and release both on Content while
* sidebar is opening, call listener. otherwise, pass
* the event to child. */
int x = (int)ev.getX();
int y = (int)ev.getY();
if (mContent.getLeft() < x
&& mContent.getRight() > x
&& mContent.getTop() < y
&& mContent.getBottom() > y) {
if (action == MotionEvent.ACTION_DOWN) {
mPressed = false;
}
if (mPressed
&& action == MotionEvent.ACTION_UP
&& mListener != null) {
mPressed = false;
return mListener.onContentTouchedWhenOpening();
}
} else {
mPressed = false;
}
return false;
}
public void setListener(Listener l) {
mListener = l;
}
/* to see if the Sidebar is visible */
public boolean isOpening() {
return mOpened;
}
public void toggleSidebar() {
if (mContent.getAnimation() != null) {
return;
}
if (mOpened) {
/* opened, make close animation*/
if (mPlaceLeft) {
mAnimation = new TranslateAnimation(0, -mSidebarWidth, 0, 0);
} else {
mAnimation = new TranslateAnimation(0, mSidebarWidth, 0, 0);
}
mAnimation.setAnimationListener(mCloseListener);
} else {
/* not opened, make open animation */
if (mPlaceLeft) {
mAnimation = new TranslateAnimation(0, mSidebarWidth, 0, 0);
} else {
mAnimation = new TranslateAnimation(0, -mSidebarWidth, 0, 0);
}
mAnimation.setAnimationListener(mOpenListener);
}
mAnimation.setDuration(DURATION);
mAnimation.setFillAfter(true);
mAnimation.setFillEnabled(true);
mContent.startAnimation(mAnimation);
}
public void openSidebar() {
if (!mOpened) {
toggleSidebar();
}
}
public void closeSidebar() {
if (mOpened) {
toggleSidebar();
}
}
class OpenListener implements Animation.AnimationListener {
View iSidebar;
View iContent;
OpenListener(View sidebar, View content) {
iSidebar = sidebar;
iContent = content;
}
public void onAnimationRepeat(Animation animation) {
}
public void onAnimationStart(Animation animation) {
iSidebar.setVisibility(View.VISIBLE);
}
public void onAnimationEnd(Animation animation) {
iContent.clearAnimation();
mOpened = !mOpened;
requestLayout();
if (mListener != null) {
mListener.onSidebarOpened();
}
}
}
class CloseListener implements Animation.AnimationListener {
View iSidebar;
View iContent;
CloseListener(View sidebar, View content) {
iSidebar = sidebar;
iContent = content;
}
public void onAnimationRepeat(Animation animation) {
}
public void onAnimationStart(Animation animation) {
}
public void onAnimationEnd(Animation animation) {
iContent.clearAnimation();
iSidebar.setVisibility(View.INVISIBLE);
mOpened = !mOpened;
requestLayout();
if (mListener != null) {
mListener.onSidebarClosed();
}
}
}
public interface Listener
{
public void onSidebarOpened();
public void onSidebarClosed();
public boolean onContentTouchedWhenOpening();
}
}
I want to implement a slider, which is basically two lines, one vertical and one horizontal, crossing where the screen is touched. I have managed to make one but I have to issues:
The slider is not very smooth, there is a slight delay when I'm moving the finger
If I place two sliders it is not multitouch, and I'd like to use both of them simultaneously
Here is the code:
public class Slider extends View {
private Controller controller = new Controller();
private boolean initialisedSlider;
private int sliderWidth, sliderHeight;
private Point pointStart;
private Paint white;
private int mode;
final static int VERTICAL = 0, HORIZONTAL = 1, BOTH = 2;
public Slider(Context context) {
super(context);
setFocusable(true);
// TODO Auto-generated constructor stub
}
public Slider(Context context, AttributeSet attrs) {
super(context, attrs);
setFocusable(true);
pointStart = new Point();
initialisedSlider = false;
mode = Slider.BOTH;
}
#Override
protected void onDraw(Canvas canvas) {
if(!initialisedSlider) {
initialisedSlider = true;
sliderWidth = getMeasuredWidth();
sliderHeight = getMeasuredHeight();
pointStart.x = (int)(sliderWidth/2.0);
pointStart.y = (int)(sliderHeight/2.0);
controller = new Controller(pointStart, 3);
white = new Paint();
white.setColor(0xFFFFFFFF);
}
canvas.drawLine(controller.getCoordX(),0,
controller.getCoordX(),sliderHeight,
white);
canvas.drawLine(0, controller.getCoordY(),
sliderWidth, controller.getCoordY(),
white);
}
public boolean onTouchEvent(MotionEvent event) {
int eventaction = event.getAction();
int X = (int)event.getX();
int Y = (int)event.getY();
switch (eventaction) {
case MotionEvent.ACTION_DOWN:
if(isInBounds(X,Y)) {
updateController(X, Y);
}
break;
case MotionEvent.ACTION_MOVE:
if(isInBounds(X,Y)) {
updateController(X, Y);
}
break;
case MotionEvent.ACTION_UP:
if(isInBounds(X,Y)) {
updateController(X, Y);
}
break;
}
invalidate();
return true;
}
private boolean isInBounds(int x, int y) {
return ((x<=(sliderWidth)) && (x>=(0))
&& (y<=(sliderHeight)) && (y>=(0)));
}
private void updateController(int x, int y) {
switch(mode) {
case Slider.HORIZONTAL:
controller.setCoordX(x);
break;
case Slider.VERTICAL:
controller.setCoordY(y);
break;
case Slider.BOTH:
controller.setCoordX(x);
controller.setCoordY(y);
break;
}
}
private class Controller {
private int coordX, coordY;
Controller() {
}
Controller(Point point, int width) {
setCoordX(point.x);
setCoordY(point.y);
}
public void setCoordX(int coordX) {
this.coordX = coordX;
}
public int getCoordX() {
return coordX;
}
public void setCoordY(int coordY) {
this.coordY = coordY;
}
public int getCoordY() {
return coordY;
}
}
}
And the XML file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello" />
<com.android.lasttest.Slider
android:id="#+id/slider"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center_horizontal"
android:adjustViewBounds="true"/>
<com.android.lasttest.Slider
android:id="#+id/slider"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_gravity="center_horizontal"
android:adjustViewBounds="true"/>
<com.android.lasttest.Slider
android:id="#+id/slider"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center_horizontal"
android:adjustViewBounds="true"/>
</LinearLayout>
How to implement a SeekBar
Add the SeekBar to your layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView"
android:layout_margin="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<SeekBar
android:id="#+id/seekBar"
android:max="100"
android:progress="50"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
Notes
max is the highest value that the seek bar can go to. The default is 100. The minimum is 0. The xml min value is only available from API 26, but you can just programmatically convert the 0-100 range to whatever you need for earlier versions.
progress is the initial position of the slider dot (called a "thumb").
For a vertical SeekBar use android:rotation="270".
Listen for changes in code
public class MainActivity extends AppCompatActivity {
TextView tvProgressLabel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// set a change listener on the SeekBar
SeekBar seekBar = findViewById(R.id.seekBar);
seekBar.setOnSeekBarChangeListener(seekBarChangeListener);
int progress = seekBar.getProgress();
tvProgressLabel = findViewById(R.id.textView);
tvProgressLabel.setText("Progress: " + progress);
}
SeekBar.OnSeekBarChangeListener seekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// updated continuously as the user slides the thumb
tvProgressLabel.setText("Progress: " + progress);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// called when the user first touches the SeekBar
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// called after the user finishes moving the SeekBar
}
};
}
Notes
If you don't need to do any updates while the user is moving the seekbar, then you can just update the UI in onStopTrackingTouch.
See also
SeekBar Tutorial With Example In Android Studio
Android provides slider which is horizontal
http://developer.android.com/reference/android/widget/SeekBar.html
and implement OnSeekBarChangeListener
http://developer.android.com/reference/android/widget/SeekBar.OnSeekBarChangeListener.html
If you want vertical Seekbar then follow this link
http://hoodaandroid.blogspot.in/2012/10/vertical-seek-bar-or-slider-in-android.html
For future readers!
Starting from material components android 1.2.0-alpha01, you have slider component
ex:
<com.google.android.material.slider.Slider
android:id="#+id/slider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:valueFrom="20f"
android:valueTo="70f"
android:stepSize="10" />
Release notes
Material Design Spec
Docs