Android Tooltips on MenuItem

2020-03-06 03:05发布

问题:

I'm trying to show a tooltip on a MenuItem.

I'm using this library: compile 'com.github.xizzhu:simple-tool-tip:0.5.0' from this Maven repository: maven { url "https://jitpack.io" }. I'm getting the view for the MenuItem, to use it as an anchor for the ToolTip but it is launching a nullPointerException in the toolTipView.show() method. When I debug the app, the View item is correct. If i replace the View item with the floating button fab, it works perfectly.

At some point, it worked, but the ToolTip position was wrong, it appears on the left top corner of the screen, instead of the right position, which would be at bottom of View item.

Note: I'm creating the ToolTip inside OnCreateOptionsMenu() because OnViewCreated() run before this method, so I have to do it there.

Here is where it happens, if you need any other piece of code I can upload it.

Menu:

<menu
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tooltipproto="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/action_settings"
        tooltipproto:actionViewClass="android.widget.ImageButton"
        android:title="@string/action_settings"
        tooltipproto:showAsAction="always" />

</menu>

Fragment:

package com.tooltipproto;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;

import com.github.xizzhu.simpletooltip.ToolTip;
import com.github.xizzhu.simpletooltip.ToolTipView;

public class ShowFragment extends Fragment{

    View item;
    FloatingActionButton fab;

    public ShowFragment(){
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        inflater.inflate(R.menu.menu_main, menu);
        MenuItem menuItem = menu.findItem(R.id.action_settings);
        item = menuItem.getActionView();

        ToolTip toolTip = new ToolTip.Builder()
                .withText("Simple Tool Tip!")
                .withTextSize(50)
                .withPadding(10,10,10,10)
                .withCornerRadius(10)
                .build();
        final ToolTipView toolTipView = new ToolTipView.Builder(getActivity())
                .withAnchor(item)
                .withToolTip(toolTip)
                .withGravity(Gravity.BOTTOM)
                .build();
        toolTipView.show();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
        // Defines the xml file for the fragment
        setHasOptionsMenu(true);
        fab = (FloatingActionButton) getActivity().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();
            }
        });
        setHasOptionsMenu(true);
        return inflater.inflate(R.layout.fragment, parent, false);
    }


}

回答1:

Method 1:

First create custom toolbar

Tooltip library link Visit

activity_login.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:banner="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:fitsSystemWindows="true"
android:background="@mipmap/background"
tools:context="com.and.postanads.LoginActivity">

<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppTheme.AppBarOverlay">

    <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:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:text="SKIP"
            android:textColor="#FFFFFF"
            android:textStyle="bold"
            android:fontFamily="sans-serif"
            android:id="@+id/txt_skip"
            android:layout_marginRight="15dp"
            android:layout_gravity="right"/>

    </android.support.v7.widget.Toolbar>

</android.support.design.widget.AppBarLayout>

LoginActivity.java

public class LoginActivity extends AppCompatActivity implements Tooltip.Callback {


private Tooltip.ClosePolicy mClosePolicy = Tooltip.ClosePolicy.TOUCH_ANYWHERE_CONSUME;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    Tooltip.dbg = true;

    TextView textView = (TextView)findViewById(R.id.txt_skip);
    Tooltip.make(this, new Tooltip.Builder(101)
                .anchor(textView, Tooltip.Gravity.BOTTOM)
                .closePolicy(mClosePolicy, 5000)
                .text("Tooltip on a TabLayout child...Tooltip on a TabLayout child...")
                .withStyleId(R.style.ToolTipLayoutDefaultStyle_CustomFont)
                .fadeDuration(200)
                .fitToScreen(true)
                .activateDelay(2000)
                .withCallback(this)
                .floatingAnimation(Tooltip.AnimationBuilder.DEFAULT)
                .showDelay(400)
                .build()
        ).show();
    }
}

Sample image

Method 2:

Using Menu_item

menu_login.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/menu_skip"
    android:orderInCategory="100"
    android:title="Skip"
    app:showAsAction="always"/>
</menu>

LoginActivity.java

public class LoginActivity extends AppCompatActivity implements Tooltip.Callback {
private Tooltip.ClosePolicy mClosePolicy = Tooltip.ClosePolicy.TOUCH_ANYWHERE_CONSUME;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    Tooltip.dbg = true;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_login, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    if (id == R.id.menu_skip) {
        View view = findViewById(R.id.menu_skip);
        Tooltip.make(this, new Tooltip.Builder(101)
                .anchor(view, Tooltip.Gravity.BOTTOM)
                .closePolicy(mClosePolicy, 5000)
                .text("Tooltip on a TabLayout child...Tooltip on a TabLayout child...")
                .fadeDuration(200)
                .fitToScreen(true)
                .activateDelay(2000)
                .withCallback(this)
                .floatingAnimation(Tooltip.AnimationBuilder.DEFAULT)
                .showDelay(400)
                .build()
        ).show();
        return true;
    }
    return super.onOptionsItemSelected(item);
}
}