0

That's the problem, I tried using setPadding, setRight and other stupid methods, but they won't help.

I need the text to go to new lines when display limits has reached, so, please help me.

It seems to have place only if I use as Target, Target.NONE, other times, when I use some button and etc, the lines go down as they should and everything ok, but I need this intro text to show up for a first time without any specific elements selected.

Movsar Bekaev
  • 888
  • 1
  • 12
  • 30

1 Answers1

0

I solved the problem through adding a child view to ShowCaseView.

UPD,

I've been asked to share the solution, so I'll share with all code that I use.

Here's my complete code as to using ShowCaseView: I use a Fragment to show it, therefore I don't need to copy code in every time, also I made some improvements to make life easier using it:

frShowCase.java:

/**
 * Created by Movsar Bekaev on 02/09/2015.
 */
public class frShowCase extends Fragment {
    static boolean is_sc_done;
    static ArrayList<xSchowCaseTarget> elements;
    static ShowcaseView sv;

    int svStep = 0;
    RelativeLayout.LayoutParams svButtonParams;
    TextView tvSvTitle, tvSvDetail;
    View additional_view = null;
    Handler mHandler;


    //SHOWCASE THING************************************
    private View.OnClickListener showCaseListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            sv.hideButton();
            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                public void run() {
                    showCaseSwitcher();
                    sv.showButton();
                }
            }, 50);
        }
    };


    public static frShowCase newInstance(ArrayList<xSchowCaseTarget> _elements) {
        frShowCase f = new frShowCase();
        Bundle args = new Bundle();
        elements = new ArrayList<xSchowCaseTarget>();
        sv = null;
        for (xSchowCaseTarget se : _elements) {
            elements.add(se);
        }
        is_sc_done = false;
        f.setArguments(args);
        return f;
    }

    public void svSetButtonPosition(cbActivity.position buttonPortraitPosition) {
        switch (buttonPortraitPosition) {
            case BOTTOM_LEFT:
                svButtonParams = new RelativeLayout.LayoutParams((int) getActivity().getResources().getDimension(R.dimen.btns_width), (int) getActivity().getResources().getDimension(R.dimen.btns_heigh));
                svButtonParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
                svButtonParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
                svButtonParams.topMargin = 0;
                break;
            case BOTTOM_RIGHT:
                svButtonParams = new RelativeLayout.LayoutParams((int) getActivity().getResources().getDimension(R.dimen.btns_width), (int) getActivity().getResources().getDimension(R.dimen.btns_heigh));
                svButtonParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
                svButtonParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
                svButtonParams.topMargin = 0;
                break;
            case TOP_LEFT:
                svButtonParams = new RelativeLayout.LayoutParams((int) getActivity().getResources().getDimension(R.dimen.btns_width), (int) getActivity().getResources().getDimension(R.dimen.btns_heigh));
                svButtonParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
                svButtonParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
                svButtonParams.topMargin = (int) getActivity().getResources().getDimension(R.dimen.btns_heigh);
                break;
            case TOP_RIGHT:
                svButtonParams = new RelativeLayout.LayoutParams((int) getActivity().getResources().getDimension(R.dimen.btns_width), (int) getActivity().getResources().getDimension(R.dimen.btns_heigh));
                svButtonParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
                svButtonParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
                svButtonParams.topMargin = (int) getActivity().getResources().getDimension(R.dimen.btns_heigh);
                break;
            case CENTER:
                svButtonParams = new RelativeLayout.LayoutParams((int) getActivity().getResources().getDimension(R.dimen.btns_width), (int) getActivity().getResources().getDimension(R.dimen.btns_heigh));
                svButtonParams.addRule(RelativeLayout.CENTER_IN_PARENT);
                svButtonParams.topMargin = 0;
                break;
            case FILL_BOTTOM:
                svButtonParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, (int) getActivity().getResources().getDimension(R.dimen.btns_heigh));
                svButtonParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
                svButtonParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
                svButtonParams.topMargin = 0;
                break;
            case FILL_TOP:
                svButtonParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, (int) getActivity().getResources().getDimension(R.dimen.btns_heigh));
                svButtonParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
                svButtonParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
                svButtonParams.topMargin = (int) getActivity().getResources().getDimension(R.dimen.btns_heigh);
                break;
            case BOTTOM_CENTER:
                svButtonParams = new RelativeLayout.LayoutParams((int) getActivity().getResources().getDimension(R.dimen.btns_width), (int) getActivity().getResources().getDimension(R.dimen.btns_heigh));
                svButtonParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
                svButtonParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
                svButtonParams.topMargin = 0;
                break;
            case CENTER_TOP:
                svButtonParams = new RelativeLayout.LayoutParams((int) getActivity().getResources().getDimension(R.dimen.btns_width), (int) getActivity().getResources().getDimension(R.dimen.btns_heigh));
                svButtonParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
                svButtonParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
                svButtonParams.topMargin = (int) getActivity().getResources().getDimension(R.dimen.btns_heigh);
                break;
        }
        sv.setButtonPosition(svButtonParams);
    }

    private void svSetUpOtherView() {
        sv.setContentTitle("");
        sv.setContentText("");
        additional_view = View.inflate(getActivity(), R.layout.showcase_text, null);
        RelativeLayout.LayoutParams lps = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        lps.addRule(RelativeLayout.CENTER_IN_PARENT);
        tvSvTitle = (TextView) additional_view.findViewById(R.id.tvSvTitle);
        tvSvTitle.setText(elements.get(svStep).title);
        tvSvDetail = (TextView) additional_view.findViewById(R.id.tvSvDetailText);
        tvSvDetail.setText(elements.get(svStep).description);
        sv.addView(additional_view, 0, lps);
    }

    private void showCaseSwitcher() {
        if (svStep < elements.size()) {
            if (additional_view != null)
                sv.removeView(additional_view);

            sv.setShowcase(elements.get(svStep).target, true);
            svSetButtonPosition(elements.get(svStep).b_pos);

            if (elements.get(svStep).use_splashscreen) {
                svSetUpOtherView();
            } else {
                sv.setContentTitle(elements.get(svStep).title);
                sv.setContentText(elements.get(svStep).description);
            }

            svStep++;
        } else {
            ViewGroup mRootView = (ViewGroup) getActivity().getWindow().getDecorView().findViewById(android.R.id.content);
            for (View v : getAllChildrenBFS(mRootView)) v.setEnabled(true);

            sv.hide();
            if (elements.get(svStep - 1).title.equals(getString(R.string.sv_intention_addweek_title))) {
                final Message m1 = mHandler.obtainMessage(123);
                mHandler.sendMessage(m1);
            }

            getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
        }
    }

    public void setHandler(Handler handler) {
        this.mHandler = handler;
    }

    @Override
    public void onAttach(Activity ac) {
        super.onAttach(ac);
        Log.d("123", "onattach");

    }


    private List<View> getAllChildrenBFS(View v) {
        List<View> visited = new ArrayList<View>();
        List<View> unvisited = new ArrayList<View>();
        unvisited.add(v);

        while (!unvisited.isEmpty()) {
            View child = unvisited.remove(0);
            visited.add(child);
            if (!(child instanceof ViewGroup)) continue;
            ViewGroup group = (ViewGroup) child;
            final int childCount = group.getChildCount();
            for (int i=0; i<childCount; i++) unvisited.add(group.getChildAt(i));
        }

        return visited;
    }

    @Override
    public void onCreate(Bundle b) {
        super.onCreate(b);
        Log.d("123", "oncreate");
    }


    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        //SHOWCASE INITIALIZATION THING*************************************************************

        if (!is_sc_done && frShowCase.elements != null) {
            getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
                PowerManager pm = (PowerManager) getActivity().getSystemService(Context.POWER_SERVICE);
                boolean isScreenOn = pm.isScreenOn();
                if (isScreenOn) {
                    is_sc_done = true;

                    ViewGroup mRootView = (ViewGroup) getActivity().getWindow().getDecorView().findViewById(android.R.id.content);
                    for (View v : getAllChildrenBFS(mRootView)) v.setEnabled(false);

                    cbActivity.BoolToPref(getActivity().getLocalClassName(), false);

                    sv = new ShowcaseView.Builder(getActivity())
                            .setTarget(frShowCase.elements.get(0).target)
                            .setContentTitle(frShowCase.elements.get(svStep).title)
                            .setContentText(frShowCase.elements.get(svStep).description)
                            .setStyle(R.style.CustomShowcaseTheme)
                            .setOnClickListener(showCaseListener)
                            .build();

                    if (elements.get(svStep).use_splashscreen)
                        svSetUpOtherView();


                    svSetButtonPosition(frShowCase.elements.get(0).b_pos);
                    sv.setButtonText(getActivity().getString(R.string.next));

                    svStep++;
                }
            }
            return sv;
        }
        //**************************************************************************************
        return container;
    }

}

Here is a class for targets I use to pass Targets from Activities to that Fragment

xShowCaseTargets.java

 import com.github.amlcurran.showcaseview.targets.Target;

    /**
     * Created by Movsar Bekaev on 15/09/2015.
     */
    public class xSchowCaseTarget{
        protected cbActivity.position b_pos = cbActivity.position.BOTTOM_RIGHT;
        protected Target target = null;
        protected String title = "";
        protected String description = "";
        protected boolean use_splashscreen = false;

        public xSchowCaseTarget(Target target, String title, String desc, cbActivity.position position, Boolean useSplash) {
            this.b_pos = position;
            this.target = target;
            this.title = title;
            this.description = desc;
            this.use_splashscreen = useSplash;
        }

        public xSchowCaseTarget(Target target, String title, String desc, cbActivity.position position) {
            this.b_pos = position;
            this.target = target;
            this.title = title;
            this.description = desc;
            this.use_splashscreen = false;
        }    
    }

This is the xml for custom layout for ShowCaseView to use when default one won't do his job (text go off from the screen, button not there where it should be and etc.)

showcase_text.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <ScrollView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/scvShowCase" >

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/welcome"
                android:id="@+id/tvSvTitle"
                android:layout_gravity="center_horizontal"
                android:layout_marginTop="50dp"
                android:textColor="?attr/color_7"
                android:textSize="@dimen/h1_size"
                android:textStyle="bold" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/welcome_text"
                android:id="@+id/tvSvDetailText"
                android:layout_gravity="center_horizontal"
                android:textColor="?attr/color_4"
                android:layout_marginTop="30dp"
                android:layout_marginLeft="5dp"
                android:layout_marginRight="5dp"
                android:textSize="@dimen/text_normal_size"
                android:gravity="center" />
        </LinearLayout>
    </ScrollView>

</FrameLayout>

As to cbActivity.BoolFromPref(getLocalClassName(), false) - I use shared preferences to check whether or not this Activity has been started, so this line checks this value, also in Fragment's code you see blocking all views of layout while presentation, if you don't need it - don't call that.

If you need to use custom view, you add "true" when creating a Target like this:

svElements.add(new xSchowCaseTarget(Target.NONE, getString(R.string.welcome), getString(R.string.welcome_text), position.FILL_BOTTOM, true));

And the last thing is, the cbActivity - mybase class for Activities, I use it here as reference to the common methods and vars, so the position enum is declared in that class, and it looks like:

 public enum position {TOP_RIGHT, TOP_LEFT, BOTTOM_RIGHT, BOTTOM_LEFT, CENTER, BOTTOM_CENTER, CENTER_TOP, FILL_BOTTOM, FILL_TOP}

Here is an example of how I call ShowcaseView from Activities:

 if (cbActivity.BoolFromPref(getLocalClassName(), false)) {
            ArrayList<xSchowCaseTarget> svElements = new ArrayList<xSchowCaseTarget>();
            svElements.add(new xSchowCaseTarget(Target.NONE, getString(R.string.welcome), getString(R.string.welcome_text), position.FILL_BOTTOM, true));
            svElements.add(new xSchowCaseTarget(new ViewTarget(R.id.xxx, ActMain.this), getString(R.string.xxx), getString(R.string.xxx), position.BOTTOM_LEFT));
            svElements.add(new xSchowCaseTarget(new ViewTarget(R.id.xxx, ActMain.this), getString(R.string.xxx), getString(R.xxx), position.BOTTOM_RIGHT));
            if (isThereActionMenuButton())
                svElements.add(new xSchowCaseTarget(new ActionViewTarget(ActMain.this, ActionViewTarget.Type.OVERFLOW), getString(R.string.xxx), getString(R.string.xxx), position.FILL_BOTTOM));
            svElements.add(new xSchowCaseTarget(new ViewTarget(R.id.xxx, ActMain.this), getString(R.string.xxx), getString(R.string.xxx), position.CENTER));

            frShowCase frSC = frShowCase.newInstance(svElements);
            fm.beginTransaction().add(frSC , "xxx").commit();
        }
Movsar Bekaev
  • 888
  • 1
  • 12
  • 30