BottomAppBar Navigation Icon with Badge - android

I am using the new BottomAppBar in an app.
But I can't make the badge to work.
I tried using the same logic used on BottomNavigationView, but it is not working.(In another app I have a BottomNavigationView inside a BottomAppBar where the badge works, but couldn't use the same code in the BottomAppBar app(Navigation Icon).
MenuView.ItemView itemView = (MenuView.ItemView) bottomAppBar.getChildAt(posicao);
notificationBadge = LayoutInflater.from(this).inflate(R.layout.view_notification_badge, (ViewGroup) itemView, false);
TextView notific = notificationBadge.findViewById(R.id.badge);
notific.setText(notificacao);
itemView.addView(notificationBadge);
What I want to do:
I tried the BadgeNavigationDrawable class. But couldn't find the right reference to the navigation icon in the BottomAppBar.
Thanks.

you can have a try like this:
in the xml ,set "app:navigationIcon"(the left icon in the bottomAppBar):
<android.support.design.bottomappbar.BottomAppBar
android:id="#+id/bottom_appbar"
android:layout_width="match_parent"
android:layout_height="44dp"
android:layout_gravity="bottom"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:fabAttached="true"
app:backgroundTint="#color/colorPrimary"
app:navigationIcon="#android:drawable/ic_dialog_email"
app:fabCradleVerticalOffset="12dp"/>
then in the activity:
BottomAppBar bottomAppBar = (BottomAppBar) findViewById(R.id.bottom_appbar);
bottomAppBar.setNavigationOnClickListener(this);
#Override
public void onClick(View v) {
//do something
}

Related

Didn't set position ActionBar Logo with NavigationDrawer android

I m using navigation drawer and want to put a launcher icon to the right of navigation drawer icon and put a title on right of launcher icon in ActionBar. I m trying this but didn't get the expected result.
Image here :
I m using
actionbar.setLogo(imageId); //to set the launchericon
actionbar.setTitle("home"); //to set the title
but the problem is, didn't able to set the launcher icon position in ActionBar.
please help me out.
Thanks in advance.
Use below code to set logo and title on your ActionBar :
RESULT / OUTPUT :
CODE:
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setLogo(R.mipmap.ic_launcher);
getSupportActionBar().setDisplayUseLogoEnabled(true);
getSupportActionBar().setTitle("Home");
FULL CODE :
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Here is the code
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setLogo(R.mipmap.ic_launcher);
getSupportActionBar().setDisplayUseLogoEnabled(true);
getSupportActionBar().setTitle("Home");
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
I hope you mean to say that your toolbar logo is not getting displayed for a custom toolbar. A possible workaround for that would be to an <ImageView> to your custom toolbar itself and set the image.
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/my_custom_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_custom"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Custom Title"
android:id="#+id/custom_title"
android:layout_toRightOf="#id/menu_icon"/>
</RelativeLayout>
</android.support.v7.widget.Toolbar>
Note that you could also add the android:centerHorizontal="true" to the textview if you want the title to be in center. Next declare the toolbar and call the textview in the required file by the id
TextView customTitle = (TextView) findViewById(R.id.custom_title);
customTitle.setText("My Custom Title");
Instead of using the getSupportActionBar().setLogo(R.mipmap.ic_launcher); we have defined it in the xml. Now use this code in the java.
ImageView cumstomIcon = (ImageView) findViewById(R.id.my_custom_icon);
customIcon.setImageResource(R.drawable.some_image);
You can also directly set the image in the xml but if you need to keep diff. images for various activities, then set the image programmatically..
Any doubts drop a comment!

How to change overflow menu icon with imageview

I have an toolbar with overflow menu icon with menu items. I need to change the overflow icon to the circular imageview.
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="?attr/actionBarSize"
android:background="#color/white"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light">
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/profile_image"
android:layout_width="38dp"
android:layout_height="30dp"
android:layout_gravity="right|end"
app:srcCompat="#android:drawable/sym_def_app_icon"/>
</android.support.v7.widget.Toolbar>
And the code looks like.
Toolbar toolbarTop = (Toolbar) findViewById(R.id.toolbar);
CircleImageView mciv = (CircleImageView) findViewById(R.id.profile_image);
setSupportActionBar(toolbarTop);
I have tried to change the overflow icon but most of SO mentioned about of using drawable. But i need to use the imageview. I have tried with the below
#Override
public boolean onOptionsItemSelected(MenuItem item) {
item.setActionView(mciv);
return super.onOptionsItemSelected(item);
}
But its not working. How to change overflow menu icon with imageview?
You can set click event of imageview and on click open menu.
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openOptionsMenu();
}
});
or you can manually create Popup menu, here is the example for popup menu

How to align action bar title to centre without using custom view

I want to align the action bar title to centre without the help of custom view . I would appreciate any help.
Without using the custom view, modifying only default action bar title
You can align the title to the center when you use ActionBar, but you can use Toolbar to do this.
Toolbar is more useful and easier than ActionBar, you can use this layout to define the center title TextView for you activity:
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="40dip">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="#string/app_name" />
</android.support.v7.widget.Toolbar>
And use this code for a back button:
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.activity_toolbar);
Toolbar toolbar = (Toolbar) findViewById(R.id.single_toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if(actionBar != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
You also need to override onCreateOptionsMenu method for the menu, and you can refer to this project : chrisbanes/cheesesquare.
Ok, You can try this:
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay" >
<TextView
android:textColor="#fff"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_gravity="center"
android:text="#string/app_name" />
</android.support.v7.widget.Toolbar>
And remember to add this line in your activity's java code:
getSupportActionBar.setTitle("");
It seems there is no way to do this without custom view. You can get the title view:
View decor = getWindow().getDecorView();
TextView title = (TextView) decor.findViewById(getResources().getIdentifier("action_bar_title", "id", "android"));
But changing of gravity or layout_gravity doesn't have an effect. The problem in the ActionBarView, which layout its children by itself so changing of layout params of its children also doesn't have an effect. To see this excecute following code:
ViewGroup actionBar = (ViewGroup) decor.findViewById(getResources().getIdentifier("action_bar", "id", "android"));
View v = actionBar.getChildAt(0);
ActionBar.LayoutParams p = new ActionBar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
p.gravity= Gravity.CENTER;
v.setLayoutParams(p);
v.setBackgroundColor(Color.BLACK);

Use of setVisibility(View.INVISIBLE) with pre Lollipop Circular Reveal library

I'm working on a project in which I want to use the Circular Reveal effect as per the Material Design. Project has minSDK = 11, so for compatibility with pre-Lollipop devices, I'm using this library https://github.com/ozodrukh/CircularReveal
I've a fragment with a FloatingActionButton that, when tapped, will transform itself in the CardView, like described here FAB transformations.
Once the card is revealed it has a button to revert the animation, re-transforming the card into the FAB. Now my problem is this: let's say that a user tap the FAB and the CardView is revealed. Now the user rotate his device, so the activity resets the fragment. What I want to achieve is the card stay visible and revealed, while the FAB should be disabled and invisible. The problem is that if I simply use setVisibility(View.INVISIBLE) on my FAB it doesn't work (note that if I use getVisibility() on it just after setting it invisible, it correctly returns me the value 4 == View.INVISIBLE, but the fab is still visible). I've to wrap the setVisibility(...) call inside a postDelayed() with at least 50-100 ms of delay to make the fab invisible.
So my question is: am I doing things right or there's a better way to accomplish what I want (because it seems very ugly to me)?
Here's some code. This is my XML layout of the fragment:
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="#+id/my_appbar"
android:layout_width="match_parent"
android:layout_height="#dimen/toolbar_expanded_height"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="70dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="#style/ToolbarPopupTheme"
app:layout_collapseMode="pin"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
...
<io.codetail.widget.RevealFrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="#layout/my_fragment" />
</io.codetail.widget.RevealFrameLayout>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/fab_margin"
app:fabSize="mini"
app:layout_anchor="#+id/my_appbar"
app:layout_anchorGravity="bottom|left|start" />
</android.support.design.widget.CoordinatorLayout>
This is the XML layout of the included CardView:
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:layout_gravity="center"
card_view:cardCornerRadius="2dp"
android:visibility="invisible"
android:focusableInTouchMode="true">
<RelativeLayout android:layout_width="match_parent"
android:layout_height="match_parent">
...
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="end">
<Button android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="Ok" />
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cancel" />
</LinearLayout>
</RelativeLayout>
</android.support.v7.widget.CardView>
And this is the code of my Fragment:
public class MyFragment extends Fragment {
private static final String CARD_OPEN_TAG = "CARD_OPEN_TAG";
public static MyFragment newInstance(){
return new MyFragment();
}
private int cardOpen;
private FloatingActionButton fabAddPublication;
private CardView card;
private Button cardCancel;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_magazines, container, false);
toolbar = (Toolbar) rootView.findViewById(R.id.layout);
...
// Initialize view status
if (savedInstanceState != null){
cardOpen = savedInstanceState.getInt(CARD_OPEN_TAG);
} else {
cardOpen = -1;
}
...
// Get FAB reference
fab = (FloatingActionButton) rootView.findViewById(R.id.fab_id);
// Get card reference
card = (CardView) rootView.findViewById(R.id.card_id);
editorPublication.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// Using this event because I need my card to be measured to move correctly fab at his center
if (cardOpen != -1){
// Move FAB to center of card
fab.setTranslationX(coordX); // WORKS
fab.setTranslationY(coordY); // WORKS
// fab.setVisibility(View.INVISIBLE) -> DOESN'T WORK, fab remain visible on top and at center of my card
// Ugly workaround
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// Hide FAB
fab.setVisibility(View.INVISIBLE);
}
}, 50); // Sometimes fails: if device/emulator use too much time to "rotate" screen, fab stay visible
// Remove listener
ViewTreeObserver obs = card.getViewTreeObserver();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
obs.removeOnGlobalLayoutListener(this);
else obs.removeGlobalOnLayoutListener(this);
}
}
});
if (editorOpen != -1){
fab.setEnabled(false); // WORKS
card.setVisibility(View.VISIBLE); // WORKS
}
// Get editors buttons reference
cardCancel = (Button) card.findViewById(R.id.card_cancel_id);
// Set FAB listener
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Explode FAB
explodeFab(fab, card); // This method trigger the reveal animation
cardOpen = card.getId();
}
});
// Set editors button listeners
cardCancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Implode FAB
implodeFAB(fab, card); // This card reverts the reveal animation
cardOpen = -1;
}
});
...
return rootView;
}
#Override
public void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
...
outState.putInt(CARD_OPEN_TAG, cardOpen);
}
}
I don't think that what you're doing is correct and here's why:
1.
That circular reveal library you're using is incompatible with hardware acceleration on Android 11 to 17 (3.0 to 4.2). It's using Canvas.clipPath() - a method which was implemented in software only up to Android 4.3. It means that you have to turn hardware acceleration off or your app will crash on not supported OpenGL call.
The best way to clip layouts is to use Canvas.saveLayer()/restoreLayer(). It's the only way to support all devices, get antialiased image and support invalidate/layout/draw flow correctly.
2.
Relying on timers and layout listeners to change layouts means that something is not really working for you. Each change can be executed directly without waiting. You just have to find the right place for that piece of code.
Timers can also trigger when your app is in background. It means that it will crash while trying to access UI from Timer thread.
Maybe you're calling setVisibility(true) somewhere in the code and that's why your FAB is visible? Setting visibility is ok and should work without any delayed calls. Just save visibility as FAB's state and restore it after orientation change.
If you wish to position the FAB at the center of the toolbar, wrap them both in a FrameLayout (wrap_content) and position the FAB with layout_gravity="center". That should allow you to remove layout listener.
3.
support.CardView is broken and shouldn't be used at all. It looks and works a little bit different on Lollipop and on older systems. The shadow is different, the padding is different, content clipping doesn't work on pre-Lollipop devices, etc. That's why it's hard to get consistent, good results on all platforms.
You should consider using plain layouts for that purpose.
4.
Some animations are cool-looking, but hard to implement, doesn't give any value and quickly become irritating, because the user has to wait for the animation to finish each time he/she clicks the button.
I'm not saying no for your case, but you may consider removing the transformation and using a drop down menu, a bottom sheet, a static toolbar or a dialog for that purpose.

Contextual Action Mode not filtering touches

The contextual action mode, when overlayed on top of an android.support.v7.widget.Toolbar, does not appear to filter touches over its entire width, but lets touches "fall through" to (invisible) widgets on the Toolbar.
My Toolbar contains a custom widget (one of the declared benefits of Toolbar). I have the contextual action mode styled to overlay the toolbar, and it hides it entirely. However, when I touch where the (now obscured) custom widget was located, the touch passes through to it. I wonder if this is a bug/oversight, but I may not have grasped this right, or my expectations may be lofty. I assume that the touch would not pass through if there was something on the contextual action overlay in the location of the obscured custom component.
I am testing this on Kitkat.
Here is some sample code:
MainActivity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.actionbar_toolbar);
setSupportActionBar(toolbar);
TextView barTextView = (TextView) toolbar.findViewById(R.id.textview_bar);
barTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "Bar TextView clicked", Toast.LENGTH_SHORT).show();
}
});
mActionModeCallback = new ActionModeCallback();
TextView mainTextView = (TextView) findViewById(R.id.textview_main);
mainTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "Main TextView clicked", Toast.LENGTH_SHORT).show();
if (mActionMode != null) {
return;
}
getSupportActionBar().startActionMode(mActionModeCallback);
}
});
}
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/actionbar_toolbar"
android:layout_height="?attr/actionBarSize"
android:layout_width="match_parent"
android:background="?attr/colorPrimary"
app:theme="#style/ThemeOverlay.AppCompat.ActionBar">
<TextView
android:id="#+id/textview_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="Bar"
android:textColor="#FF0000"/>
</android.support.v7.widget.Toolbar>
<TextView
android:id="#+id/textview_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="SomeTextToClick"/>
</LinearLayout>
styles.xml
<resources>
<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
<item name="windowActionModeOverlay">true</item>
</style>
</resources>
I also tried setting up the action mode with the following alternative, but the behavior was the same:
Toolbar toolbar = (Toolbar) MainActivity.this.findViewById(R.id.actionbar_toolbar);
mActionMode = toolbar.startActionMode(mActionModeCallback);
At this point I can only think of either explicitly disabling the custom component whenever the contextual action mode comes on, or somehow filling the contextual action bar with invisible junk to more seriously obscure the toolbar.
Some screenshots below.
Before clicking anything:
After clicking "SomeTextToClick" - contextual action mode is now on, and the text in the toolbar is obscured, but at this point I can click in the center of the contextual action bar, and the click gets handled by the listener on the "Bar" TextView in the toolbar:
Can anyone help ?

Categories

Resources