Reputation: 2287
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
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