ShowcaseView 的详情文本不会换行

ShowcaseView's details text won't go to the new line

就是这个问题,我试过使用setPadding、setRight和其他愚蠢的方法,但它们没有帮助。

我需要文本在达到显示限制时换行,所以请帮助我。

它似乎只有在我用作目标时才有用,Target.NONE,其他时候,当我使用某些按钮等时,线条会正常下降,一切正常,但我需要这个介绍在未选择任何特定元素的情况下首次显示的文本。

我通过向 ShowCaseView 添加子视图解决了问题。

UPD,

我被要求分享解决方案,所以我将分享我使用的所有代码。

这是我使用 ShowCaseView 的完整代码: 我使用 Fragment 来展示它,因此我不需要每次都复制代码,我还做了一些改进,让使用起来更轻松:

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;
    }

}

这是我用来将 TargetsActivities 传递到该片段

的目标的 class

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;
        }    
    }

这是 ShowCaseView 自定义布局的 xml,当默认布局无法完成​​其工作时使用(文本从屏幕上消失,按钮不在应有的位置等)

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>

至于 cbActivity.BoolFromPref(getLocalClassName(), false) - 我使用共享首选项来检查这个 Activity 是否已经启动,所以这一行检查这个值,同样在 Fragment 的代码中你看到阻止布局的所有视图在演示时,如果您不需要它 - 不要调用它。

如果您需要使用自定义视图,您可以在创建 Target 时添加 "true",如下所示:

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

最后一件事是,活动的 cbActivity - mybase class,我在这里使用它作为对常用方法和变量的引用,所以位置枚举在 class,它看起来像:

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

这是我如何从活动中调用 ShowcaseView 的示例:

 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();
        }