web-dev-qa-db-ja.com

Android上のTextViewの複数のクリック可能なリンク

以下のスクリーンショットに示されている利用規約 AND プライバシーポリシーを使用して、Googleとフリップボードが以下で行ったのと同様のテキストビューに複数のリンクを追加しようとしています:

これまでのところ、私はこのアプローチを使用しました

textView.setText(Html.fromHtml(myHtml); textView.setMovementMethod(LinkMovementMethod.getInstance());

ここで、myHtmlはhrefです。

しかし、それは私にフラグメントを起動するためなどに必要な制御を与えません。

以下の2つの例でこれをどのように達成するか考えていますか?

Flipboard terms and conditions view

Google terms and conditions view

23

LinkifyAndroid.text.SpannableJava.util.regexを使用できます.PatternJava.lang.String

String termsAndConditions = getResources().getString(R.string.terms_and_conditions);
String privacyPolicy = getResources().getString(R.string.privacy_policy);

legalDescription.setText(
    String.format(
        getResources().getString(R.string.message),
        termsAndConditions,
        privacyPolicy)
);
legalDescription.setMovementMethod(LinkMovementMethod.getInstance());

Pattern termsAndConditionsMatcher = Pattern.compile(termsAndConditions);
Linkify.addLinks(legalDescription, termsAndConditionsMatcher, "terms:");

Pattern privacyPolicyMatcher = Pattern.compile(privacyPolicy);
Linkify.addLinks(legalDescription, privacyPolicyMatcher, "privacy:");

次に、スキームを使用して、たとえばAndroidManifestにスキームを追加することで、アクティビティを開始できます。

<intent-filter>
    <category Android:name="Android.intent.category.DEFAULT" />
    <action Android:name="Android.intent.action.VIEW" />
    <data Android:scheme="terms" />
    <data Android:scheme="privacy" />
</intent-filter>

カスタムアクションを実行する場合は、インテントフィルターを現在のアクティビティに設定できます。これには、singleTop起動モードがあります。

これにより、カスタムアクションを作成できる場所で onNewIntent が発生します。

@Override
protected void onNewIntent(final Intent intent) {
 ...
  if (intent.getScheme().equals(..)) {
    ..
  }
}
12
harrane

私はこれを共有するのが少し遅いと思いますが、私は SpannableStringBuilder を使用して同じことを達成しました。

2つ以上のリスナーを追加するTextViewを初期化し、それを私が作成した次のメソッドに渡すだけです。

private void customTextView(TextView view) {
        SpannableStringBuilder spanTxt = new SpannableStringBuilder(
                "I agree to the ");
        spanTxt.append("Term of services");
        spanTxt.setSpan(new ClickableSpan() {
            @Override
            public void onClick(View widget) {
                Toast.makeText(getApplicationContext(), "Terms of services Clicked",
                        Toast.LENGTH_SHORT).show();
            }
        }, spanTxt.length() - "Term of services".length(), spanTxt.length(), 0);
        spanTxt.append(" and");
        spanTxt.setSpan(new ForegroundColorSpan(Color.BLACK), 32, spanTxt.length(), 0);
        spanTxt.append(" Privacy Policy");
        spanTxt.setSpan(new ClickableSpan() {
            @Override
            public void onClick(View widget) {
                Toast.makeText(getApplicationContext(), "Privacy Policy Clicked",
                        Toast.LENGTH_SHORT).show();
            }
        }, spanTxt.length() - " Privacy Policy".length(), spanTxt.length(), 0);
        view.setMovementMethod(LinkMovementMethod.getInstance());
        view.setText(spanTxt, BufferType.SPANNABLE);
    } 

そして、XMLではAndroid:textColorLink選択したカスタムリンクの色を追加します。このような:

   <TextView
     Android:id="@+id/textView1"
     Android:layout_width="wrap_content"
     Android:layout_height="wrap_content"
     Android:text="TextView"
     Android:textColorLink="#C36241" />  //#C36241 - Rust

これは次のようになります。

enter image description here

それが誰かを助けることを願っています。 :)

90
Tushar Gogna

これが私の解決策です:

まず、TextViewにクリック可能なリンクが必要です:

  1. これがxmlレイアウトの私のTextViewです。パラメータを処理するリンクを追加しないでください。

    <TextView
            Android:id="@+id/sign_up_privacy"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:text="@string/terms_and_privacy"/>
    
  2. 文字列ファイルで、htmlタグ付きのリソーステキストを追加しました

    <string name="terms_and_privacy">By signing up you agree to our <a href="terms:">Terms of Service</a> and <a href="privacy:">Privacy Policy.</a></string>
    
  3. OnCreateViewでLinkMovementMethodをTextViewに設定します

    TextView privacyTextView = (TextView) root.findViewById(R.id.sign_up_privacy);
    privacyTextView.setMovementMethod(LinkMovementMethod.getInstance());
    

これで、TextViewリンクがクリック可能になります。

2番目に、これらのクリックを処理する必要があります:

  1. マニフェストファイルに、「terms」と「privacy」のインテントフィルターとシングルインスタンス起動モードを追加しました

    <activity
                Android:name=".MyActivity"
                Android:launchMode="singleInstance">
                <intent-filter>
                    <category Android:name="Android.intent.category.DEFAULT"/>
                    <action Android:name="Android.intent.action.VIEW"/>
    
                    <data Android:scheme="terms"/>
                    <data Android:scheme="privacy"/>
                </intent-filter>
            </activity>
    
  2. MyActivityで、プライバシーと条件インテントをキャッチするためにonNewIntentをオーバーライドします

    @Override
        protected void onNewIntent(Intent intent)
        {
            if (intent.getScheme().equalsIgnoreCase(getString("terms")))
            {
                //handle terms clicked
            }
            else if (intent.getScheme().equalsIgnoreCase(getString("privacy")))
            {
                //handle privacy clicked
            }
            else
            {
                super.onNewIntent(intent);
            }
        }
    
3
Ahmad Baraka

これは私のために働いています:

xmlで:

<TextView
    Android:id="@+id/tv_by_continuing_str"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:layout_marginTop="8dp"
    Android:layout_marginLeft="8dp"
    Android:layout_marginRight="8dp"
    Android:textSize="15sp"
    tools:text="Test msg 1 2, 3"
    Android:textColor="@color/translucent_less_white3"
    Android:textColorLink="@color/white"
    Android:gravity="center|bottom"
    Android:layout_above="@+id/btn_privacy_continue" />

Strings.xml内

< string name="by_continuing_str2">< ! [ CDATA[By continuing to use this app, you agree to our <a href="https://go.test.com" style="color:gray"/> Privacy Statement </a> and <a href="https://go.test.com" style="color:gray"/>Services Agreement.]]>< / string>

活動中:

TextView tv_by_continuing = (TextView) findViewById(R.id.tv_by_continuing);
tv_by_continuing.setText(Html.fromHtml(getString(R.string.by_continuing_str2)));
tv_by_continuing.setMovementMethod(LinkMovementMethod.getInstance());
1
techtinkerer

Textoo を使用すると、次のように実現できます。

res/values/strings.xml:

<resources>
     <string name="str_terms_and_privacy">By signing up you agree to our <a href="terms:">Terms of Service</a> and <a href="privacy:">Privacy Policy.</a></string>
</resources>

res/layout/myActivity.xml:

<TextView
    Android:id="@+id/view_terms_and_privacy"
    Android:text="@string/str_terms_and_privacy"
    />

Java/myPackage/MyActivity.Java:

public class MyActivity extends Activity {
    ...
    protected void onCreate(Bundle savedInstanceState) {
        ...
        TextView termsAndPrivacy = Textoo
            .config((TextView) findViewById(R.id.view_terms_and_privacy))
            .addLinksHandler(new LinksHandler() {
                @Override
                public boolean onClick(View view, String url) {
                    if ("terms:".equals(url)) {
                        // Handle terms click
                        return true;  // event handled
                    } else if ("privacy:".equals(url)) {
                        // Handle privacy click
                        return true;  // event handled
                    } else {
                        return false;  // event not handled.  continue default processing i.e. launch web browser and display the link
                    }
                }
            })
            .apply();
        ...
    }
    ...
}

このアプローチには、次のような利点があります。

  • テキストを文字列リソースとして外部化します。アプリのローカライズを簡単にします。
  • LinksHandlerを使用してクリックイベントを直接処理でき、追加のインテントフィルターを定義する必要はありません
  • よりシンプルで読みやすいコード
1
PH88

これを簡単に修正するには、複数のラベルを使用します。各リンクに1つ、テキストに1つ。

[TermsOfServiceLabel][andLabel][PrivacyPolicy]

または、ラベルを1つだけ使用する必要がありますか?

0
Deutro