1. ホーム
  2. android

Android TextViewは、テキスト内容が表示省略記号を超えているかどうかを判断する

2022-02-18 19:38:53
<パス

TextViewはテキストがellipsisを越えているかどうかを判断する


最近、Qzoneのソーシャルサークルに似たモジュールに取り組んでいます。ある要件は、ユーザーが4行以上の内容を投稿したときにボタンを表示し、ボタンをクリックすると全文が表示されることです。TextViewは、テキストコンテンツに省略記号が表示されていないことを取得するメソッドを持っていることが本当に見つかりませんでした。仕方なく自分で考えてみました。

  • アイデア・想い
    textviewは勝手に楕円を表示するので、コンテンツが最大行数を超えているかどうかを判断する内部アルゴリズムがあるはずですが、このメソッドを見つけるか、このメソッドの戻り値を見つけることができますか?
    答えはイエスで、TextViewにはメソッド getLayout()を使用します。 このLayoutオブジェクトには、メソッド
 /**
     * Returns the number of characters to be ellipsized away, or 0 if
     * no ellipsis is to take place.
     */
    public abstract int getEllipsisCount(int line);

省略された文字の数を取得することができます。0を返せば、省略がないことを意味します。そして、この戻り値から、テキストが省略されているかどうかを判断することができます。

デモ

  • MainActivityです。TextView、テキストをクリックすると折りたたまれ、すべて表示されるButton。

public class MainActivity extends AppCompatActivity {
    /**
     * Display up to 2 lines.
     */
    private static final int LINES = 2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final TextView textView = findViewById(R.id.tv);
        findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // get the number of omitted characters, 0 means no and omitted
                int ellipsisCount = textView.getLayout().getEllipsisCount(textView.getLineCount() - 1);
                textView.getLayout().getEllipsisCount(textView.getLineCount() - 1);
                //ellipsisCount>0 means that not all of them are displayed and there are omitted parts.
                if (ellipsisCount > 0) {
                    //Show all, button is set to click to close.
                    textView.setMaxHeight(getResources().getDisplayMetrics().heightPixels);
                    ((TextView) findViewById(R.id.btn)).setText("put away");
                } else {
                    //Show 2 rows, button set to show all on click.
                    ((TextView) findViewById(R.id.btn)).setText("Show All"));
                    textView.setMaxLines(LINES);
                }
            }
        });
    }
}


  • レイアウト

  • 備考
    onCreateメソッド内でtextView.getLayout()を直接呼び出すと、nullを返す場合があります。textViewが描画された後に呼び出すとよいでしょう。
 textView.post(new Runnable() {
            @Override
            public void run() {
                //Get the number of characters omitted, 0 means no and omitted
                int ellipsisCount = textView.getLayout().getEllipsisCount(textView.getLineCount() - 1);
                textView.getLayout().getEllipsisCount(textView.getLineCount() - 1);
            }
        });

  • を使ったリストでは
    テキストが3行を超えたら省略記号を付けてリスト表示し、クリックすると全部表示されるようなニーズがあるとします。WeChatの友達の輪のようなものです。

  • アイデア:リストにテキストを設定した後、textView.getLayout()メソッドを直接呼ぶとnullが返ってくるので、非同期に取得する方法が必要なので、全部表示されているか、テキストは範囲外か、などの情報を保持するデータモデルが必要です。

  • DEMO

public class TestListActivity extends AppCompatActivity {
    /**
     * Display up to 3 rows.
     */
    private static final int LINES = 3;
    /**
     * Data
     */
    private List<DataModel> data = new ArrayList<>();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_list);
        RecyclerView mRecyclerView = findViewById(R.id.rv);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
        String temp = "Display up to 3 rows. ";
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 20; i++) {
            sb.append(temp);
            data.add(new DataModel(null, sb.toString()));
        }
        mRecyclerView.setAdapter(new RecyclerView.Adapter<RecyclerView.ViewHolder>() {
            @Override
            public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                return new RecyclerView.ViewHolder(LayoutInflater.from(TestListActivity.this).inflate(R.layout.activity_main, parent, false)) {
                };
            }

            @Override
            public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
                holder.itemView.findViewById(R.id.btn_list_demo).setVisibility(View.GONE);
                final TextView textView = holder.itemView.findViewById(R.id.tv);
                final DataModel model = data.get(position);
                textView.setText(model.text);
                // save the state of the text first
                if (model.hasEllipsis == null) {
                    //If textView.getLayout() is null, retrieve the Layout object when the TextView is finished rendering.
                    textView.post(new Runnable() {
                        @Override
                        public void run() {
                            int ellipsisCount = textView.getLayout().getEllipsisCount(textView.getLineCount() - 1);
                            //Is it out of range: if the line count is greater than 3 or ellipsisCount>0 is out of range, an ellipsis will be displayed.
                            if (model.hasEllipsis == null) {
                                model.hasEllipsis = ! (textView.getLineCount() <= LINES && ellipsisCount == 0);
                            }
                            // Hide the button if the text is not out of range.
                            holder.itemView.findViewById(R.id.btn).setVisibility(model.hasEllipsis ? View.VISIBLE : View.GONE);
                            // If or not all the text is shown.
                            model.isShowAll = ellipsisCount > 0;
                            setTextViewLines(textView, ((TextView) holder.itemView.findViewById(R.id.btn)), !model.hasEllipsis || model.isShowAll);
                        }
                    });
                } else {
                    holder.itemView.findViewById(R.id.btn).setVisibility(model.hasEllipsis ? View.VISIBLE : View.GONE);
                    setTextViewLines(textView, ((TextView) holder.itemView.findViewById(R.id.btn)), !model.hasEllipsis || model.isShowAll);
                }

                holder.itemView.findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        model.isShowAll = !model.isShowAll;
                        notifyItemChanged(po

レイアウト:RecyclerViewは1つだけ

Code.
https://github.com/gentlemanyc/TestTextView/tree/master