Skip to content

Commit e75e86a

Browse files
committed
[demo] Wrote linkable label widget
1 parent 4e48cbb commit e75e86a

File tree

1 file changed

+164
-0
lines changed

1 file changed

+164
-0
lines changed
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/*
2+
* Copyright (C) 2019 Muhammad Tayyab Akram
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.mta.tehreer.demo;
18+
19+
import android.content.Context;
20+
import android.content.Intent;
21+
import android.graphics.Canvas;
22+
import android.graphics.Paint;
23+
import android.graphics.Path;
24+
import android.net.Uri;
25+
import android.text.Spanned;
26+
import android.text.style.URLSpan;
27+
import android.util.AttributeSet;
28+
import android.view.MotionEvent;
29+
30+
import androidx.annotation.Nullable;
31+
32+
import com.mta.tehreer.layout.ComposedFrame;
33+
import com.mta.tehreer.widget.TLabel;
34+
35+
public class LinkableLabel extends TLabel {
36+
private Paint mPaint = new Paint();
37+
38+
private URLSpan mActiveLinkSpan;
39+
private Path mActiveLinkPath;
40+
41+
public LinkableLabel(Context context) {
42+
super(context);
43+
setup();
44+
}
45+
46+
public LinkableLabel(Context context, @Nullable AttributeSet attrs) {
47+
super(context, attrs);
48+
setup();
49+
}
50+
51+
public LinkableLabel(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
52+
super(context, attrs, defStyleAttr);
53+
setup();
54+
}
55+
56+
private void setup() {
57+
mPaint.setStyle(Paint.Style.FILL);
58+
mPaint.setColor(0xFFCCCCEE);
59+
}
60+
61+
private URLSpan urlSpanAtIndex(int charIndex) {
62+
Spanned spanned = getSpanned();
63+
ComposedFrame composedFrame = getComposedFrame();
64+
65+
if (spanned == null || composedFrame == null) {
66+
return null;
67+
}
68+
if (charIndex < composedFrame.getCharStart() || charIndex >= composedFrame.getCharEnd()) {
69+
return null;
70+
}
71+
72+
URLSpan[] spans = spanned.getSpans(charIndex, charIndex, URLSpan.class);
73+
if (spans != null && spans.length > 0) {
74+
return spans[0];
75+
}
76+
77+
return null;
78+
}
79+
80+
private URLSpan urlSpanAtPoint(float x, float y) {
81+
return urlSpanAtIndex(hitTestPosition(x, y));
82+
}
83+
84+
private void refreshActiveLink() {
85+
Spanned spanned = getSpanned();
86+
ComposedFrame composedFrame = getComposedFrame();
87+
88+
if (spanned != null && composedFrame != null && mActiveLinkSpan != null) {
89+
int spanStart = spanned.getSpanStart(mActiveLinkSpan);
90+
int spanEnd = spanned.getSpanEnd(mActiveLinkSpan);
91+
92+
mActiveLinkPath = composedFrame.generateSelectionPath(spanStart, spanEnd);
93+
mActiveLinkPath.offset(composedFrame.getOriginX(), composedFrame.getOriginY());
94+
} else {
95+
mActiveLinkPath = null;
96+
}
97+
98+
invalidate();
99+
}
100+
101+
private void clearActiveLink() {
102+
mActiveLinkSpan = null;
103+
refreshActiveLink();
104+
}
105+
106+
private void openActiveLink() {
107+
Uri uri = Uri.parse(mActiveLinkSpan.getURL());
108+
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
109+
Context context = getContext();
110+
context.startActivity(intent);
111+
}
112+
113+
@Override
114+
protected void onDraw(Canvas canvas) {
115+
if (mActiveLinkPath != null) {
116+
canvas.drawPath(mActiveLinkPath, mPaint);
117+
}
118+
119+
super.onDraw(canvas);
120+
}
121+
122+
@Override
123+
public boolean onTouchEvent(MotionEvent event) {
124+
int action = event.getActionMasked();
125+
switch (action) {
126+
case MotionEvent.ACTION_DOWN:
127+
mActiveLinkSpan = urlSpanAtPoint(event.getX(), event.getY());
128+
if (mActiveLinkSpan != null) {
129+
refreshActiveLink();
130+
return true;
131+
}
132+
break;
133+
134+
case MotionEvent.ACTION_MOVE:
135+
if (mActiveLinkSpan != null) {
136+
URLSpan pointedLinkSpan = urlSpanAtPoint(event.getX(), event.getY());
137+
if (pointedLinkSpan != mActiveLinkSpan) {
138+
clearActiveLink();
139+
}
140+
141+
return true;
142+
}
143+
break;
144+
145+
case MotionEvent.ACTION_UP:
146+
if (mActiveLinkSpan != null) {
147+
performClick();
148+
openActiveLink();
149+
clearActiveLink();
150+
return true;
151+
}
152+
break;
153+
154+
case MotionEvent.ACTION_CANCEL:
155+
if (mActiveLinkSpan != null) {
156+
clearActiveLink();
157+
return true;
158+
}
159+
break;
160+
}
161+
162+
return super.onTouchEvent(event);
163+
}
164+
}

0 commit comments

Comments
 (0)