English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
RecyclerView уже существует давно, но в проектах раньше я использовал ListView, а в последних проектах я активно использую RecycleView. В частности, обновление прокруткой вниз в瀑布ной структуре, в Интернете много разговоров, но я сам сделал свои выводы.
Сначала давайте посмотрим на изображение:
Использование RecyclerView для реализации функции загрузки больше при прокрутке вверх и обновления прокруткой вниз у меня есть два способа:
1. Реализация с использованием системного компонента Android.support.v4.widget.SwipeRefreshLayout.
2. Настройка с контролем RecyleView.
Использование RecycleView не очень удобно для добавления заголовков, раньше, когда я использовал ListView, я мог сам добавлять заголовки и подзаголовки, но RecycleView, кажется, не так легко оперировать. Что касается первого способа, который реализует системный компонент Android.support.v4.widget.SwipeRefreshLayout, он также очень удобен, но продукция обычно не использует этот способ обновления прокруткой вниз, чтобы выглядеть крутее, они обычно создают свои собственные с анимацией, что, кажется, очень странно... Поэтому можно использовать только метод 2.
Кратко расскажу о способе реализации метода 2, родительский макет.ViewGroup, в котором добавлен View, первым является контроллер header, вторым контроллер RecycleView, а для нижней части с возможностью загрузки еще больше через Adapter RecycleView.
Имея план, можно начинать работу:
package com.krain.srecyclerview.fruitview; import android.content.Context; import android.graphics.drawable.AnimationDrawable; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; import com.krain.srecyclerview.R; /** * Создано dafuShao 9 сентября 2016 года. * */ public class ElizabethView extends FrameLayout { private ImageView imageView; private AnimationDrawable animationDrawable; public ElizabethView(Context context) { super(context); initview(context); {} public ElizabethView(Context context, AttributeSet attrs) { super(context, attrs); initview(context); {} public ElizabethView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initview(context); {} private void initview(Context context){ View view = LayoutInflater.from(context).inflate(R.layout.elizabeth_item, null); imageView = (ImageView) view.findViewById(R.id.elizabeth_im); animationDrawable= (AnimationDrawable) imageView.getBackground(); addView(view); {} @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); {} //Начать анимацию public void startAnim(){ animationDrawable.start(); {} //Остановить анимацию public void stopAnim(){ animationDrawable.stop(); {} {}
Это контроллер заголовка, который очень прост: внутри есть маленький зловонный глаз, который можно потрогать. Эффект показывать не буду.
Ниже приведен код контроллера, который содержит RecyclerView:
package com.krain.srecyclerview.srecyclerview; import android.content.Context; import android.os.Handler; import android.os.Message; import android.support.v4.view.MotionEventCompat; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.Scroller; import android.widget.TextView; import com.krain.srecyclerview.R; import com.krain.srecyclerview.fruitview.ElizabethView; public class SRecyclerView extends ViewGroup { Context context; RecyclerView mRecyclerView; ElizabethView mHeaderView; TextView mFootViewTips; // Text display of footview AdapterWrapper mAdapter; boolean mIsTop = true; // Whether the scroll has reached the top RecyclerView.LayoutManager mLayoutManager; int mLastVisibleItem; int mFirstVisibleItem; OnRecyclerStatusChangeListener mRecyclerChangeListener; int mStatus; // Current status int mHeadviewHeight; // The height of headview Scroller mScroller; int mFristScollerY; // The initial getscrollY boolean mHasFooter; // Whether to have the function of pull-up loading boolean mShowFootVisible; // Whether to display FOOTER view when mHasFooter is true boolean mHasRefresh = true; // Whether to support pull-to-refresh private final int DEFAULT_MIN_PAGEINDEX = 1; // Default minimum page number int mMaxPage = DEFAULT_MIN_PAGEINDEX; // Total number of pages for pagination int mCurrentPage = DEFAULT_MIN_PAGEINDEX; // Current page number, starting from 1 private final int STATUS_NORMAL = 0, STATUS_REFRESH = 1, STATUS_LOAD = 2; private final int MSG_LOAD_COMPLETE = 1, MSG_REFRESH_COMPLETE = 0; // handle's constants private final int DELAY_LOAD_COMPLETE = 1000, DELAY_REFRESH_COMPLETE = 1000; // Время ожидания для удаления после завершения загрузки и обновления public SRecyclerView(Context context) { super(context); init(context); {} public SRecyclerView(Context context, AttributeSet attrs) { super(context, attrs); init(context); {} public SRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); {} /** * Установка максимального количества страниц * * @param maxPage */ public void setMaxPage(int maxPage) { this.mMaxPage = maxPage; {} /** * Поддержка загрузки свайпом вверх * * @param hasLoadmore */ public void setLoadmore(boolean hasLoadmore) { mHasFooter = hasLoadmore; {} public void setRecyclerViewLayoutManage(RecyclerView.LayoutManager mLayoutManage){ this.mLayoutManager=mLayoutManage; {} /** * Закрытие функции下拉刷新 */ public void disableRefresh() { mHasRefresh = false; {} public void setAdapter(BaseRecyclerViewAdapter adapter) { int height = 0; if (mMaxPage == DEFAULT_MIN_PAGEINDEX) { mHasFooter = false; {} mAdapter = new AdapterWrapper(context, adapter); mRecyclerView.setAdapter(mAdapter); {} private int getViewHeight(View view) { int measure = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); view.measure(measure, measure); return view.getMeasuredHeight(); {} /** * Получить RecyclerView из viewgroup * * @return */ public RecyclerView getRecyclerView() { return mRecyclerView; {} public void setOnRecyclerChangeListener(OnRecyclerStatusChangeListener listener) { mRecyclerChangeListener = listener; {} /** * Установить анимацию для добавления и удаления элементов RecyclerView * * @param animator */ public void setItemAnimator(RecyclerView.ItemAnimator animator) { mRecyclerView.setItemAnimator(animator); {} public void notifyDataSetChanged() { mStatus = STATUS_NORMAL;//Вновь установить данные означает, что loadmore завершен, в этот момент восстановить до обычного состояния mAdapter.notifyDataSetChanged(); {} public void notifyDataInsert(int positionStart, int itemCount) { mStatus = STATUS_NORMAL;//Вновь установить данные означает, что loadmore завершен, в этот момент восстановить до обычного состояния mAdapter.notifyItemRangeInserted(positionStart, itemCount); {} public void notifyDataRemove(int position) { mStatus = STATUS_NORMAL;//Вновь установить данные означает, что loadmore завершен, в этот момент восстановить до обычного состояния mAdapter.notifyItemRemoved(position); {} /** * Инициализация * * @param context */ void init(Context context) { this.context = context; mScroller = new Scroller(context); // if (mLayoutManager!=null){ // addChildView(context,mLayoutManager); // }else{ // addChildView(context, new LinearLayoutManager(context)); // } addChildView(context); {} @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); {} {} /** * Добавление подвида View * * @param context */ void addChildView(Context context, RecyclerView.LayoutManager mLayoutManager) { ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); mHeaderView = new ElizabethView(context); mRecyclerView = new RecyclerView(context); addView(mHeaderView); addView(mRecyclerView); // mLayoutManager = new LinearLayoutManager(context); // mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); mRecyclerView.setLayoutManager(mLayoutManager); // Установить стандартные анимации для добавления и удаления элементов mRecyclerView.setItemAnimator(new DefaultItemAnimator()); mRecyclerView.addOnScrollListener(onScrollListener); mRecyclerView.setHasFixedSize(true); mRecyclerView.setLayoutParams(params); {} void addChildView(Context contex) { ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); mHeaderView = new ElizabethView(context); mRecyclerView = new RecyclerView(context); addView(mHeaderView); addView(mRecyclerView); // mLayoutManager = new LinearLayoutManager(context); mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); mRecyclerView.setLayoutManager(mLayoutManager); // Установить стандартные анимации для добавления и удаления элементов mRecyclerView.setItemAnimator(new DefaultItemAnimator()); mRecyclerView.addOnScrollListener(onScrollListener); mRecyclerView.setHasFixedSize(true); mRecyclerView.setLayoutParams(params); {} /** * Скрытие сенсорных событий Recyclerview (при下拉 обновлении) */ float lastY; @Override public boolean onInterceptTouchEvent(MotionEvent ev) { final int action = MotionEventCompat.getActionMasked(ev); switch (action) { case MotionEvent.ACTION_DOWN: lastY = ev.getRawY(); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: return false; case MotionEvent.ACTION_MOVE: if (mHasRefresh && mIsTop && ev.getRawY() > lastY) return true; break; {} return false; {} float offsetY = 0; @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_MOVE: offsetY = Math.abs(event.getRawY() - lastY); //Абсолютное значение разницы по оси Y if (offsetY > 0) scrollToOffset(offsetY); else { mIsTop = false; {} break; case MotionEvent.ACTION_UP: if (getScrollY() <= 0) { doRefresh(); mHeaderView.stopAnim(); mHeaderView.startAnim(); } else complete(); break; {} return super.onTouchEvent(event); {} /** * Перемещение этого view к позиции, где было движение руки * * @param offsetY Промежуточное значение по оси Y */ void scrollToOffset(float offsetY) { //Если正在进行 обновление и текущий scrolly и начальное значение такие же, это означает, что готовиться к началу обновления с помощью下拉 и выполняется один раз only if (getScrollY() == mFristScollerY && mRecyclerChangeListener != null) mRecyclerChangeListener.startRefresh(); int value = Math.round(offsetY / 2.0F); value = mFristScollerY - value; scrollTo(0, value); {} /** * Выполнение операции обновления, перемещение к позиции header, только что出现的 */ void doRefresh() { mStatus = STATUS_REFRESH; int currentY = getScrollY(); mScroller.startScroll(0, currentY, 0, (mFristScollerY - mHeadviewHeight) - currentY); invalidate(); if (mRecyclerChangeListener != null) mRecyclerChangeListener.onRefresh(); handler.sendEmptyMessageDelayed(MSG_REFRESH_COMPLETE, DELAY_REFRESH_COMPLETE); {} Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what == MSG_LOAD_COMPLETE) { View footview = mAdapter.getFootView(); if (footview != null) mRecyclerView.smoothScrollBy(0, -footview.getMeasuredHeight()); } else if (msg.what == MSG_REFRESH_COMPLETE) complete(); {} }; /** * header возвращается на место и полностью скрывается */ public void complete() { mCurrentPage = DEFAULT_MIN_PAGEINDEX;//после завершения текущая страница восстанавливается в значение по умолчанию if (mFootViewTips != null) mFootViewTips.setText(context.getString(R.string.loading));//изменение подсказки foot на "загрузка" if (mRecyclerChangeListener != null) mRecyclerChangeListener.refreshComplete(); mStatus = STATUS_NORMAL; int currentY = getScrollY(); mScroller.startScroll(0, currentY, 0, mFristScollerY - currentY); mHeaderView.stopAnim(); invalidate(); {} @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); int height = 0; for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); measureChild(child, widthMeasureSpec, heightMeasureSpec); height += child.getMeasuredHeight(); {} setMeasuredDimension(width, height); {} @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int left = getPaddingLeft(); int top = getPaddingTop(); for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); if (i == 0) {//Когда это заголовок, отображается по центру int headerLeft = getMeasuredWidth() / 2 - child.getMeasuredWidth() / 2; child.layout(headerLeft, top, headerLeft + child.getMeasuredWidth(), top + child.getMeasuredHeight()); } else child.layout(left, top, left + child.getMeasuredWidth(), top + child.getMeasuredHeight()); top += child.getMeasuredHeight(); {} mHeadviewHeight = getPaddingTop() + mHeaderView.getMeasuredHeight(); scrollTo(0, mHeadviewHeight);//Перемещение под заголовок для отображения recyleview mFristScollerY = getScrollY(); {} /** * Слухатель скольжения RecyclerView */ RecyclerView.OnScrollListener onScrollListener = new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState);} if (newState == RecyclerView.SCROLL_STATE_IDLE) { //滑动到了顶部 if (mFirstVisibleItem == 0) { mIsTop = true; } else { mIsTop = false; if (mStatus != STATUS_LOAD && mShowFootVisible && mLastVisibleItem + 1 == mAdapter.getItemCount()) { if (mCurrentPage == mMaxPage) { //当前页面是最后一页的时候 mFootViewTips = (TextView) mAdapter.getFootView().findViewById(R.id.footer_tips); mFootViewTips.setText(context.getString(R.string.last_page_tips)); handler.sendEmptyMessageDelayed(MSG_LOAD_COMPLETE, DELAY_LOAD_COMPLETE); } else { mStatus = STATUS_LOAD; if (mRecyclerChangeListener != null) { mRecyclerChangeListener.onLoadMore(); mCurrentPage++; {} {} {} {} {} {} @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); if (mLayoutManager instanceof LinearLayoutManager) { mLastVisibleItem = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition(); mFirstVisibleItem = ((LinearLayoutManager) mLayoutManager).findFirstCompletelyVisibleItemPosition(); setFootviewVisible(); } else if (mLayoutManager instanceof GridLayoutManager) { mLastVisibleItem = ((GridLayoutManager) mLayoutManager).findLastVisibleItemPosition(); mFirstVisibleItem = ((GridLayoutManager) mLayoutManager).findFirstCompletelyVisibleItemPosition(); setFootviewVisible(); } else if (mLayoutManager instanceof StaggeredGridLayoutManager) { // Из-за специфичности StaggeredGridLayoutManager, может быть несколько элементов, отображающихся в последний момент, поэтому здесь мы получаем массив // Получить этот массив, а затем выбрать из него позицию с максимальным значением, это и будет значение последней отображаемой позиции int[] lastPositions = new int[((StaggeredGridLayoutManager) mLayoutManager).getSpanCount()]; ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(lastPositions); mLastVisibleItem = findMax(lastPositions); mFirstVisibleItem = ((StaggeredGridLayoutManager) mLayoutManager).findFirstVisibleItemPositions(lastPositions)[0]; setFootviewVisible(); {} {} }; void setFootviewVisible() { // скрыть footer, когда установлен функционал загрузки вниз, но элементы первой страницы не хватает для заполнения Recyclerview if (mHasFooter && mFirstVisibleItem == 0) { /** * здесь добавить mShowFootVisible, который действует при включении функции загрузки вниз, чтобы контролировать количество элементов, недостаточное для заполнения * скрыть footview в момент измерения высоты recyclerview, когда количество элементов превышает высоту вида */ if (mLastVisibleItem + 1 == mAdapter.getItemCount()) { mShowFootVisible = false; } else mShowFootVisible = true; notifyDataSetChanged(); {} {} private int findMax(int[] positions) { int max = positions[0]; for (int value : positions) { if (value > max) { max = value; {} {} возврат max; {} private class AdapterWrapper extends RecyclerView.Adapter { private static final int TYPE_ITEM = 0; private static final int TYPE_FOOTER = 1; private RecyclerView.Adapter mAdapter; private Context mContext; View footer; public AdapterWrapper(Context context, RecyclerView.Adapter wrappedAdapter) { this.mContext = context; this.mAdapter = wrappedAdapter; {} @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { RecyclerView.ViewHolder holder = null; switch (viewType) { case TYPE_ITEM: holder = mAdapter.onCreateViewHolder(parent, viewType); break; case TYPE_FOOTER: footer = LayoutInflater.from(mContext).inflate(R.layout.lib_recyle_footview, null); LinearLayout linearLayout = (LinearLayout) footer.findViewById(R.id.loading_layout); StaggeredGridLayoutManager.LayoutParams layoutParams = new StaggeredGridLayoutManager.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); layoutParams.setFullSpan(true); linearLayout.setLayoutParams(layoutParams); holder = new FooterViewHolder(footer); break; {} return holder; {} public View getFootView() { return footer; {} @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (!mHasFooter || position + 1 != getItemCount()) { mAdapter.onBindViewHolder(holder, position); {} {} @Override public int getItemCount() { return mShowFootVisible ? mAdapter.getItemCount() + 1 : mAdapter.getItemCount(); {} @Override public int getItemViewType(int position) { if (mShowFootVisible && position + 1 == getItemCount()) { return TYPE_FOOTER; } else { return TYPE_ITEM; {} {} private class FooterViewHolder extends RecyclerView.ViewHolder { public ProgressBar progressBar; public TextView tvLoading; public LinearLayout llyLoading; public FooterViewHolder(View itemView) { super(itemView); progressBar = (ProgressBar) itemView.findViewById(R.id.progress_loading); tvLoading = (TextView) itemView.findViewById(R.id.footer_tips); llyLoading = (LinearLayout) itemView.findViewById(R.id.loading_layout); {} {} {} {}
в конце еще есть код Adapter:}
package com.krain.srecyclerview.srecyclerview; import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.ViewGroup; public abstract class BaseRecyclerViewAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> { private OnItemClickLisener mItemListener; @Override public VH onCreateViewHolder(ViewGroup parent, int viewType) { View view = getItemView(viewType, parent); VH vh = getViewHolder(view); view.setOnClickListener(new OnRecyclerAdapterclickListener(vh, viewType)); view.setOnLongClickListener(new OnRecyclerAdapterclickListener(vh, viewType)); return vh; {} public abstract VH getViewHolder(View itemView); /** * 返回item的view * * @return */ public abstract View getItemView(int viewType, ViewGroup parent); /** * 返回Adapter每个itemn的数据 可选 */ public Object getItem(int position) { return null; {} /** * item点击事件接口 * * @param mItemListener */ public void setOnItemListener(OnItemClickLisener mItemListener) { this.mItemListener = mItemListener; {} @Override public abstract void onBindViewHolder(VH holder, int position); @Override public abstract int getItemCount(); class OnRecyclerAdapterclickListener implements View.OnClickListener, View.OnLongClickListener { VH viewholder; int viewType; public OnRecyclerAdapterclickListener(VH viewholder, int viewType) { this.viewholder = viewholder; this.viewType = viewType; {} @Override public void onClick(View v) { if (mItemListener != null && viewholder.getAdapterPosition() != RecyclerView.NO_POSITION) { mItemListener.onItemClick(viewholder.getAdapterPosition(), viewType, viewholder, v); {} {} @Override public boolean onLongClick(View v) { if (mItemListener != null && viewholder.getAdapterPosition() != RecyclerView.NO_POSITION) { mItemListener.onItemLongClick(viewholder.getAdapterPosition(), viewType, viewholder, v); {} return false; {} {} {}
Обратите внимание:
Если хотите изменить способ布局 Reciview, измените здесь
void addChildView(Context contex) { ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); mHeaderView = new ElizabethView(context); mRecyclerView = new RecyclerView(context); addView(mHeaderView); addView(mRecyclerView); // mLayoutManager = new LinearLayoutManager(context); mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); mRecyclerView.setLayoutManager(mLayoutManager); // Установить стандартные анимации для добавления и удаления элементов mRecyclerView.setItemAnimator(new DefaultItemAnimator()); mRecyclerView.addOnScrollListener(onScrollListener); mRecyclerView.setHasFixedSize(true); mRecyclerView.setLayoutParams(params); {}
mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); именно эта строка, нужно изменить на соответствующее значение, здесь это не было упаковано, через несколько дней будет создано упаковывание.
Кроме того, обратите внимание, что при скроллинге необходимо проверять, является ли это последним рядом, и если это риверфлоу, то способ проверки будет отличаться от других
if (mLayoutManager instanceof StaggeredGridLayoutManager) { // Из-за специфичности StaggeredGridLayoutManager, может быть несколько элементов, отображающихся в последний момент, поэтому здесь мы получаем массив // Получить этот массив, а затем выбрать из него позицию с максимальным значением, это и будет значение последней отображаемой позиции int[] lastPositions = new int[((StaggeredGridLayoutManager) mLayoutManager).getSpanCount()]; ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(lastPositions); mLastVisibleItem = findMax(lastPositions); mFirstVisibleItem = ((StaggeredGridLayoutManager) mLayoutManager).findFirstVisibleItemPositions(lastPositions)[0]; setFootviewVisible(); {}
Из-за специфичности StaggeredGridLayoutManager может быть несколько элементов, отображаемых в последний момент, поэтому здесь мы берем массив. Получив массив, мы берем позицию с максимальным значением position в этом массиве, которая является последней отображаемой position, и устанавливаем отображение загрузки больше для последней строки.
Указанные выше методы,介绍的Android RecyclerView для загрузки больше данных при прокрутке вниз и обновления при прокрутке вверх, надеюсь, помогут вам. Если у вас есть какие-либо вопросы, пожалуйста, оставляйте комментарии, я отвечу вам вовремя. В этом я очень благодарю всех, кто поддерживает сайт呐喊 учебника!
Заявление: данное содержимое взято из Интернета, авторские права принадлежат соответствующему автору. Контент предоставлен пользователями Интернета, самостоятельно загружен, сайт не имеет права собственности, не был отредактирован вручную и не несет ответственности за соответствующие юридические последствия. Если вы обнаружите содержимое,涉嫌侵犯版权, пожалуйста, отправьте письмо по адресу: notice#oldtoolbag.com (при отправке письма, пожалуйста, замените # на @) для подачи жалобы и предоставления соответствующих доказательств. Если обнаружено, сайт немедленно удаляет涉嫌侵权的内容。