日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

微信朋友圈,QQ空间,微博等列表展示的功能实现

發布時間:2025/4/16 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 微信朋友圈,QQ空间,微博等列表展示的功能实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

內容摘要

該控件能夠應用于內容資訊展示的功能模塊中,如:騰訊和新浪微博的微博列表,微信朋友圈及其它社交類應用的好友動態展示列表等;實現了類似騰訊微博的微博列表展示功能,包含微博文本內容,表情,圖片,話題和用戶可點超鏈接等(請參見如下效果圖)。該功能在實際項目開發中非常常見,除微博應用外,微信的朋友圈,陌陌、QQ空間的好友動態等也都有類似功能

  • RecyclerView使用和嵌套問題
  • 動態設置圖片網格寬高
  • 正則表達式的使用
  • Linkify實現自定義超鏈接
  • TextView富文本顯示
  • 點贊動畫漸變動畫效果
  • 效果圖

    列表的item布局文件

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginBottom="5dp"android:background="@color/white"android:descendantFocusability="blocksDescendants"android:orientation="vertical"><RelativeLayout android:layout_width="match_parent"android:layout_height="60dp"android:layout_marginTop="10dp"android:paddingLeft="10dp"android:paddingRight="10dp"><ImageView android:id="@+id/iv_avatar"android:layout_width="45dp"android:layout_height="45dp"android:layout_centerVertical="true"android:background="#11000000"android:scaleType="centerCrop"/><LinearLayout android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_centerVertical="true"android:layout_marginLeft="10dp"android:layout_toRightOf="@id/iv_avatar"android:orientation="vertical"><TextView android:id="@+id/tv_user"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginRight="120dp"android:text="用戶名"android:textColor="@color/black"android:textSize="16sp"/><TextView android:id="@+id/tv_user_introduction"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="5dp"android:singleLine="true"android:text="用戶相關介紹"android:textColor="@color/item_text_secondary"android:textSize="14sp"/></LinearLayout><TextView android:id="@+id/tv_date"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_marginTop="5dp"android:text="0000-00-00"android:textColor="@color/item_text_secondary"android:textSize="14sp"/></RelativeLayout><TextView android:id="@+id/tv_content"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginBottom="10dp"android:layout_marginLeft="10dp"android:layout_marginTop="5dp"android:text="這是微博內容...這是微博內容..."android:textColor="@color/item_text_main"android:textSize="16sp"/><!--顯示微博圖片--><android.support.v7.widget.RecyclerView android:id="@+id/rv_weibo_images"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginBottom="10dp"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"android:listSelector="@color/transparent"android:visibility="gone"/><View android:layout_width="match_parent"android:layout_height="1px"android:background="@color/activity_bg"/><LinearLayout android:layout_width="match_parent"android:layout_height="40dp"android:orientation="horizontal"><FrameLayout android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:clickable="true"><TextView android:id="@+id/tv_forward"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:drawableLeft="@drawable/selector_btn_share"android:textColor="@color/item_text_secondary"android:drawablePadding="5dp"android:gravity="center"android:text="0"/></FrameLayout><FrameLayout android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:clickable="true"><TextView android:id="@+id/tv_comment"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:drawableLeft="@drawable/selector_btn_comment"android:textColor="@color/item_text_secondary"android:drawablePadding="5dp"android:gravity="center"android:text="0"/></FrameLayout><LinearLayout android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center"android:clickable="true"><CheckBox android:id="@+id/cb_like"android:layout_width="40dp"android:layout_height="40dp"android:layout_gravity="center"android:button="@color/transparent"android:checked="false"android:drawableLeft="@drawable/selector_btn_prize"android:drawablePadding="5dp"android:background="@color/transparent"android:textColor="@color/item_text_secondary"android:gravity="center"/><TextView android:id="@+id/tv_like"android:text="0"android:textColor="@color/item_text_secondary"android:layout_width="wrap_content"android:layout_height="wrap_content"/></LinearLayout></LinearLayout></LinearLayout>

    item中的RecyclerView用于顯示0-9張圖片,根據服務器返回的圖片數量不同顯示的行列數和圖片的大小也不同,需要動態設置,由于這個列表是RecyclerView,item中也使用了RecyclerView,這就產生了RecyclerView的嵌套

    id為tv_content的TextView用于顯示內容,內容中包含了表情圖片和超鏈接

    json數據格式

    {"result":true,"weibo":[{"avatar":"avatar_01","comment":5,"content":"我裝作看不懂的樣子[呲牙][偷笑][偷笑],單身狗保重 [再見][再見] @冷笑話精選","date":1489223423501,"forward":8,"imageUrls":["pic_1","pic_2","pic_3","pic_4","pic_5","pic_6","pic_7","pic_8","pic_9"],"like":10,"user_introduction":"最冷笑話精選,每天分享笑話N枚,你的貼身開心果。","username":"冷笑話精選"}] }

    對應的實體類

    public class WeChat {public boolean result;public List<WeiboEntity> weibo;public static class WeiboEntity {public String avatar;public int comment;public String content;public long date;public int forward;public int like;public String user_introduction;public String username;public List<String> imageUrls;} }

    動態設置圖片宮格數

    根據圖片的數量,動態設置RecyclerView的列數和寬度

    • 如果圖片數量為0,則隱藏RecyclerView
    • 如果圖片數量為1,RecyclerView列數設為1列,寬度設為WRAP_CONTENT
    • 如果圖片數量為4,RecyclerView列數設為2列,寬度設為兩個圖片宮格的寬度
    • 其它,RecyclerView列數設為3列,寬度設為MATCH_PARENT
    // 刷新item布局中子控件的顯示@Overrideprotected void onRefreshView(WeChat.WeiboBean bean, int position) {// 顯示用戶名tvUser.setText(bean.getUsername());// 顯示用戶介紹if (TextUtils.isEmpty(bean.getUser_introduction())) {tvUserIntroduction.setVisibility(View.GONE);} else {tvUserIntroduction.setVisibility(View.VISIBLE);tvUserIntroduction.setText(bean.getUser_introduction());}// 顯示頭像int imageResId = Global.getResId(context, bean.getAvatar());ivAvatar.setBackgroundResource(imageResId);// 微博內容// tvContent.setText(bean.getContent());EmojiUtil.setText(tvContent, bean.getContent());LinkifyUtil.addCustomLink(tvContent);LinkifyUtil.addCustomLink2(tvContent);// 發表時間tvDate.setText(Global.formatDate(bean.getDate()));// 顯示微博圖片int imageCount = bean.getImageUrls() == null? 0 : bean.getImageUrls().size();if (imageCount == 0) { // 沒有微博圖片rvWeiboImages.setVisibility(View.GONE);} else { // 有微博圖片rvWeiboImages.setVisibility(View.VISIBLE);imageAdapter.setDatas(bean.getImageUrls()); // 刷新圖片顯示// 動態的指定圖片宮格的寬高和RecyclerView的寬度// 1張圖片 -> 1列// 4張圖片 -> 2列// 其它 -> 3列ViewGroup.LayoutParams param = rvWeiboImages.getLayoutParams();if (imageCount == 1) {layoutManager.setSpanCount(1);param.width = ViewGroup.LayoutParams.WRAP_CONTENT;} else if (imageCount == 4) {layoutManager.setSpanCount(2);// 兩個圖片宮格的寬度param.width = Global.getGridWidth() * 2;} else { // 3列layoutManager.setSpanCount(3);param.width = ViewGroup.LayoutParams.MATCH_PARENT;}}}

    動態設置圖片的大小

    • 1張圖片,宮格的寬高為圖片的寬高
    • 其它情況,宮格的寬高為屏幕寬度的三分之一
    // 刷新item子控件的顯示@Overrideprotected void onRefreshView(String imagePath, int position) {// 動態設置圖片宮格的寬高// 1張圖片 -> 宮格的寬高為圖片的寬高// 其它情況 -> 宮格的寬高為Global.getGridWidth()ViewGroup.LayoutParams param = super.itemView.getLayoutParams();if (super.adapter.getItemCount() == 1) { // 一張圖片// 圖片資源idint imageResId = Global.getResId(context, imagePath);Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), imageResId);// 指定宮格的寬高為圖片的寬高param.width = bitmap.getWidth();param.height = bitmap.getHeight();// 顯示圖片ivImage.setBackgroundResource(imageResId);} else { // 多張圖片// 顯示宮格圖片int imageResId = Global.getResId(context, imagePath);ivImage.setBackgroundResource(imageResId);param.width = Global.getGridWidth(); // 指定宮格圖片的寬param.height = Global.getGridWidth();}}

    TextView富文本顯示

    顯示文本中的表情,把文本中如[呲牙][偷笑][偷笑]的文字替換成表情圖片,實現TextView的富文本顯示(圖文混排)。需要用正則去匹配文本中是否包含表情,匹配成功,表示文本中包含表情,用ImageSpan封裝表情圖片,再ImageSpan將設置給SpannableString,把文本中的表示表情的文字替換掉,最后將SpannableString設置給TextView即可。

    正則參考:

    [高興] \\[([A-Za-z\u4E00-\u9FA5]+)\\] @用戶 \\@([A-Za-z0-9\u4E00-\u9FA5]+) #話題# \\#([A-Za-z0-9\u4E00-\u9FA5]+)\\# public class EmojiUtil {/** 顯示文本和表情 */public static void setText(TextView textView, String text) {Context context = textView.getContext();Resources resources = context.getResources();SpannableString ss = new SpannableString(text);// 正則表達式: [高興]Pattern p = Pattern.compile("\\[([A-Za-z\u4E00-\u9FA5]+)\\]");Matcher matcher = p.matcher(ss);while (matcher.find()) {// 匹配到一個表情字符串String emoji = matcher.group();// 過濾非表情符,比如: [xxx]if (EMOJI_DATAS.containsKey(emoji)) { // 是表情才處理// System.out.println("----------" + emoji);// 指定了一張圖片Bitmap bitmap = BitmapFactory.decodeResource(resources, EMOJI_DATAS.get(emoji));bitmap = Global.createBitmap(bitmap, Global.dp2px(20)); // 圖片的寬高為20dpImageSpan span = new ImageSpan(context, bitmap, ImageSpan.ALIGN_BOTTOM);int start = matcher.start();int end = matcher.end();ss.setSpan(span, start, end, 0);}}textView.setText(ss);}private static final HashMap<String, Integer> EMOJI_DATAS = new HashMap<String, Integer>();static {EMOJI_DATAS.put("[微笑]", R.drawable.smiley_0);...} }

    讓文字顯示顏色

    /*** 讓某幾個文字顯示顏色* @param string* @param color* @return*/private CharSequence showTextWithColor(String string,int color) {SpannableString ss = new SpannableString(string);// BackgroundColorSpan 背景色ForegroundColorSpan colorSpan = new ForegroundColorSpan(color);int end = string.indexOf("等");ss.setSpan(colorSpan, 0, end, SpannableString.SPAN_INCLUSIVE_EXCLUSIVE);return ss;}

    讓圖片和文字一起顯示

    /*** 讓圖片和文字一起顯示* @param text* @param imageRes* @return*/private SpannableString showTextWithImage(String text,int imageRes){SpannableString ss = new SpannableString(text);Drawable drawable = getResources().getDrawable(imageRes);//設置邊界 // drawable.setBounds(0,0,drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight());drawable.setBounds(0,0,20,20);ImageSpan span = new ImageSpan(drawable);int start = text.indexOf("[");int end = text.indexOf("]")+1;ss.setSpan(span, start,end,SpannableString.SPAN_INCLUSIVE_EXCLUSIVE);return ss;}

    設置超鏈接

    // 讓某段文字可以被點擊并跳轉超鏈接 String text = "詳情請點擊<a href='http://www.baidu.com'>百度</a>"; Spanned spanned = Html.fromHtml(text); text3.setText(spanned); text3.setMovementMethod(LinkMovementMethod.getInstance());//設置可以點擊超鏈接

    讓某段文字可以被點擊并自定義點擊的邏輯操作

    // 讓某段文字可以被點擊并自定義點擊的邏輯操作 String string = "王二,小明,大兵等覺得很贊"; SpannableString ss= new SpannableString(string); MyUrlSpan urlSpan= new MyUrlSpan(string.substring(0, string.indexOf(","))); ss.setSpan(urlSpan, 0, 2, SpannableString.SPAN_INCLUSIVE_EXCLUSIVE); text4.setText(ss); text4.setMovementMethod(LinkMovementMethod.getInstance()); class MyUrlSpan extends URLSpan{public MyUrlSpan(String url) {super(url);}@Overridepublic void onClick(View widget) {// 自定義點擊的操作邏輯,默認實現是獲取url,打開瀏覽器Toast.makeText(MainActivity.this, getURL(), 0).show();widget.clearFocus();}@Overridepublic void updateDrawState(TextPaint ds) {super.updateDrawState(ds);ds.setColor(Color.RED); // 設置文字顏色ds.setUnderlineText(false); // 設置是否顯示下劃線} }

    自定義超鏈接

    關于TextView 網頁,電話,郵箱的自動識別。設置android:autoLink=”email|web|phone|map”屬性后,TextView 可自動識別電話、郵箱、網址、地圖為超鏈接。

    <TextView android:id="@+id/tv"android:layout_width="match_parent"android:layout_height="wrap_content"android:scrollbarStyle="insideOverlay"android:scrollbars="vertical"android:autoLink="email|web|phone|map"android:text=" 電話:13609000000,郵箱:815612738@163.com,網址:http://www.google.com " />

    添加自定義超鏈接,把內容中如@冷笑話精選、#編程#、#講故事#的文本顯示為超鏈接,高亮顯示并支持點擊。先使用Linkify.MatchFilter 匹配過濾器過濾內容中的超鏈接,TextView在顯示的內容要識別鏈接時,調用Linkify.addLinks()

    public class LinkifyUtil {/*** 添加自定義超鏈接*/public static void addCustomLink(TextView textView) {// @用戶:Pattern pattern = Pattern.compile("\\@([A-Za-z0-9\u4E00-\u9FA5]+)\\.?");// http://www.qq.com/path?uid=1&username=xxString scheme = "weibo://user?uid=";// 匹配過濾器Linkify.MatchFilter matchFilter = new Linkify.MatchFilter() {@Overridepublic boolean acceptMatch(CharSequence s, int start, int end) {String text = s.subSequence(start, end).toString();// System.out.println("----text: " + text);if (text.endsWith(".")) { // 郵箱,不需要匹配return false;} else {return true; // 返回true會顯示為超鏈接}}};Linkify.TransformFilter transformFilter = null;Linkify.addLinks(textView, pattern, scheme, matchFilter, transformFilter);}public static void addCustomLink2(TextView textView) {// @用戶:Pattern pattern = Pattern.compile("\\#([A-Za-z0-9\u4E00-\u9FA5]+)\\#");// http://www.qq.com/path?uid=1&username=xxString scheme = "weibo://topic?uid=";// 匹配過濾器Linkify.MatchFilter matchFilter = new Linkify.MatchFilter() {@Overridepublic boolean acceptMatch(CharSequence s, int start, int end) {String text = s.subSequence(start, end).toString();System.out.println("----text: " + text);return true;}};Linkify.TransformFilter transformFilter = new Linkify.TransformFilter() {@Overridepublic String transformUrl(Matcher match, String url) {return match.group(1);}};Linkify.addLinks(textView, pattern, scheme, matchFilter, transformFilter);} }

    設置自定義的鏈接后,點擊超鏈接后會出錯。 因為沒有找到Activity可以處理發起的Intent, 需要定義兩個Activity來接收意圖中的參數。

    當點擊超鏈接的時候,會調起/啟動一個與Linkify.addLinks()方法中的scheme對應的Activity

    public class TopicActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// weibo://user?uid=@冷笑話精選Uri uri = getIntent().getData();String topic = uri.getQueryParameter("uid");TextView textView = new TextView(this);textView.setGravity(Gravity.CENTER);textView.setTextColor(Color.RED);textView.setText(topic);textView.setTextSize(20);setContentView(textView);}} public class UserActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// weibo://user?uid=@冷笑話精選Uri uri = getIntent().getData();String username = uri.getQueryParameter("uid");TextView textView = new TextView(this);textView.setGravity(Gravity.CENTER);textView.setTextColor(Color.GRAY);textView.setText(username);textView.setTextSize(20);setContentView(textView);}}

    在清單文件中配置以上Activity,給Activity設置action、category、data

    <!--點擊用戶鏈接時,要調起該Activity--> <activity android:name=".ui.activity.UserActivity"><intent-filter><action android:name="android.intent.action.VIEW"/><category android:name="android.intent.category.DEFAULT"/><data android:scheme="weibo" android:host="user"/></intent-filter> </activity> <activity android:name=".ui.activity.TopicActivity"><intent-filter><action android:name="android.intent.action.VIEW"/><category android:name="android.intent.category.DEFAULT"/><data android:scheme="weibo" android:host="topic"/></intent-filter> </activity>

    點贊動畫

    在MainActivity的布局文件中,有一個TextView,是用來執行點贊后的+1的動畫(向上平移,透明度變小,放大)。 該控件開始時隱藏,執行點贊動畫時,注意不是列表項中的控件執行動畫。

    // WeiboHolder.java cbLike.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {if (isChecked) {// 獲取當前點擊控件相對于窗口的所在位置int[] locations = new int[2];tvLike.getLocationInWindow(locations);((MainActivity) context).animateUp(locations);}} }); public void animateUp(int[] locations) {// 減去狀態欄高度24dpint currentY = locations[1] - Global.dp2px(24);tvLike.setVisibility(View.VISIBLE);tvLike.setTranslationX(locations[0]);tvLike.setTranslationY(currentY);tvLike.setScaleY(1);tvLike.setScaleX(1);tvLike.setAlpha(1f);// 往上移動30dpint top = currentY - Global.dp2px(30);tvLike.animate().alpha(0).translationY(top).setInterpolator(new DecelerateInterpolator()).scaleX(1.2f).scaleY(1.2f).setDuration(1000); }

    代碼:https://github.com/JackChan1999/WeChatDemo

    總結

    以上是生活随笔為你收集整理的微信朋友圈,QQ空间,微博等列表展示的功能实现的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。