JustLearningAgain
JustLearningAgain

Reputation: 2287

TextView with autoLink won't allow capture of click event on non-hyperlink portion of TextView

My Android project is loading a ListView with Twitter feed items. The problem I'm having is getting embedded hyperlinks to function WHILE still allowing for selection of the ListView item IF the user clicks on the ListView item OUTSIDE of the embedded hyperlink.

Let's say that the text for the Twitter feed item is:

 This is a sample tweet with an embedded link (https://t.co/eMnVvBEo7W).  And this is some random text.

This partially works. The link is colored (showing it's a hyperlink) and when I click on the link portion of the TextView, it correctly launches the browser and page.

The problem is that all other clicks on the TextView are not coming through. I need to be able to get click events on the ListView item so I can perform other functionality with the tweet (like share, etc...). But, as I've said, no click events are coming through. What I want is that when the user selects a NON-hyperlink portion of the tweet, for that item to become selected.

Here are some snippets of code

List View Item Layout:

     <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="1256dp"
    android:layout_width="1256dp"
    android:layout_height="match_parent"
    android:descendantFocusability="blocksDescendants">

    <ImageView
        android:id="@+id/imageViewTwitterFeed"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:paddingTop="5dp"
        android:paddingBottom="5dp"
        android:paddingLeft="5dp"
        android:paddingRight="5dp" />

    <TextView
        android:id="@+id/textViewTwitterFeed"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="18dp"
        android:layout_marginStart="18dp"
        android:layout_toRightOf="@+id/imageViewTwitterFeed"
        android:layout_toEndOf="@+id/imageViewTwitterFeed"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:ellipsize="end"
        android:singleLine="false"
        android:autoLink="web"
        android:focusable="false"
        android:paddingTop="5dp"
        android:paddingBottom="5dp"/>

</RelativeLayout>

Fragment Layout

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:id="@+id/tweetList"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:choiceMode="singleChoice"
        android:listSelector="#d3d3d3"/>

</LinearLayout>

Fragment Code:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    // Inflate view
    pageView = inflater.inflate(R.layout.page_twitter_feed_view_fragment, container, false);
    tweetsListView = (ListView) pageView.findViewById(R.id.tweetList);
    tweetsListView.setBackgroundColor(Color.WHITE);

    if(pageDefinition == null)
    {
        // Get page definition associated with this fragment
        if (getArguments().containsKey(MINPageDefinition.ARG_ITEM_ID))
        {
            pageDefinition = MINAppConfiguration.getSharedInstance().currentMarket.pageArray.get(Integer.valueOf(getArguments().getString(MINPageDefinition.ARG_ITEM_ID)));
        }
        // Provide a weak reference to this fragment for optimization purposes
        pageDefinition.weakFragment = new WeakReference<Fragment>(this);
    }

    // Set up specific controls/views
    initializePage();

    // Set up adapter & click listener
    adapter = new TwitterFeedAdapter(this, tweetStatusList);
    tweetsListView.setAdapter(adapter);
    tweetsListView.setOnItemClickListener(new AdapterView.OnItemClickListener()
    {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id)
        {
            twitter4j.Status tweetStatus = (twitter4j.Status)tweetStatusList.get(position);
            setTwitterShareIntent(tweetStatus);
        }
    });

    // Report to Flurry
    WeakHashMap<String, String> map = new WeakHashMap<String, String>();
    map.put(MINFlurryDefines.kFlurryKey_PageName, pageDefinition.pageName);
    FlurryAgent.logEvent(MINFlurryDefines.kFlurryEvent_PageView + " - " + pageDefinition.pageName, map, true);

    return pageView;
}

EDIT:

// Set up adapter & click listener
adapter = new TwitterFeedAdapter(this, tweetStatusList);
tweetsListView.setAdapter(adapter);
tweetsListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
tweetsListView.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
    @Override
    public void onItemClick(AdapterView<?> parent, View view, final int position, long id)
    {
        twitter4j.Status tweetStatus = (twitter4j.Status)tweetStatusList.get(position);
        setTwitterShareIntent(tweetStatus);

        // Show the item as selected
/*
        parent.requestFocusFromTouch();
        parent.setSelection(position);
        parent.requestFocus();
 */
    }
});



final TextView tweetTextView = (TextView)V.findViewById(R.id.textViewTwitterFeed);

    tweetTextView.setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            //tweetsListView.setSelection(position);
            //tweetsListView.smoothScrollToPosition(position);
            tweetsListView.performItemClick(v, position, 0);
        }
    });

    tweetTextView.setMovementMethod(new CustomLinkMovementMethod());
    tweetTextView.setFocusable(false);
    tweetTextView.setClickable(false);
    tweetTextView.setLongClickable(false);

Upvotes: 2

Views: 694

Answers (1)

dtx12
dtx12

Reputation: 4488

    textView.setMovementMethod(new CustomLinkMovementMethod());
            textView.setFocusable(false);
            textView.setClickable(false);
            textView.setLongClickable(false);

    public class CustomLinkMovementMethod extends LinkMovementMethod {
    @Override
    public boolean onTouchEvent(TextView textView, Spannable buffer, MotionEvent event) {
        int action = event.getAction();

        if (action == MotionEvent.ACTION_UP ||
                action == MotionEvent.ACTION_DOWN) {
            int x = (int) event.getX();
            int y = (int) event.getY();

            x -= textView.getTotalPaddingLeft();
            y -= textView.getTotalPaddingTop();

            x += textView.getScrollX();
            y += textView.getScrollY();

            Layout layout = textView.getLayout();
            int line = layout.getLineForVertical(y);
            int off = layout.getOffsetForHorizontal(line, x);

            if (!(textView.getText() instanceof Spannable)) {
                return false;
            }

            Spannable spannable = ((Spannable) textView.getText());
            ClickableSpan[] link = spannable.getSpans(off, off, ClickableSpan.class);

            if (link.length != 0) {
                if (action == MotionEvent.ACTION_UP) {
                    link[0].onClick(textView);
                } else {
                    Selection.setSelection(spannable,
                            spannable.getSpanStart(link[0]),
                            spannable.getSpanEnd(link[0]));
                }

                return true;
            } else {
                Selection.removeSelection(spannable);
            }
        }
        return false;
    }
}

Upvotes: 2

Related Questions