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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

新闻频道管理的炫酷实现

發(fā)布時(shí)間:2025/4/16 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 新闻频道管理的炫酷实现 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

新聞?lì)l道管理的炫酷實(shí)現(xiàn)

自定義GridLayout控件,可以在新聞咨詢類APP中的管理頁(yè)面使用到,也可以應(yīng)用在類別管理中,總之,可以幫助我們?cè)O(shè)計(jì)更加規(guī)范和炫酷的手機(jī)頁(yè)面。

新聞?lì)恆pp是最常見的應(yīng)用之一,而頻道管理又是其必不可少的功能,該自定義控件不僅可以帶我們實(shí)現(xiàn)炫酷的頻道管理功能,還可以讓我們學(xué)習(xí)如何使用Android拖拽框架實(shí)現(xiàn)我們想要的多種功能,以及讓我們對(duì)自定義控件會(huì)有更多的理解。

知識(shí)點(diǎn)

  • GridLayout的使用

    • 從Google官方文檔學(xué)習(xí)GridLayout的功能以及用法
    • 使用GridLayout實(shí)現(xiàn)子控件排列顯示
  • View的拖拽功能實(shí)現(xiàn)

    • 通過(guò)查看Google文檔,學(xué)會(huì)調(diào)用view的拖拽方法
    • 拖拽事件的處理
    • 使用View的拖拽框架實(shí)現(xiàn)實(shí)現(xiàn)頻道切換位置效果
  • 自定義GridLayout控件

    自定義GridLayout控件,實(shí)現(xiàn)拖拽功能,繼而實(shí)現(xiàn)頻道管理操作

  • Rect類的使用

    使用Rect類確定被觸摸到的子控件

  • 新聞?lì)l道管理的多種實(shí)現(xiàn)

    實(shí)現(xiàn)類似于網(wǎng)易新聞?lì)l道管理有幾種方式

    實(shí)現(xiàn)方案1:使用兩個(gè)GridView實(shí)現(xiàn),這是比較早的一種解決方案,比較復(fù)雜,具體可以參考 Android 高仿 頻道管理—-網(wǎng)易、今日頭條、騰訊視頻

    實(shí)現(xiàn)方案2:使用兩個(gè)RecyclerView或ListView實(shí)現(xiàn),這種實(shí)現(xiàn)方式好于于方案1

    實(shí)現(xiàn)方案3:使用一個(gè)RecyclerView實(shí)現(xiàn),這是我目前見過(guò)的比較好的方式,貌似比網(wǎng)易新聞等客戶端的要流暢,具體可以參考:高仿網(wǎng)易新聞欄目動(dòng)畫效果 、 使用ItemTouchHelper高效地實(shí)現(xiàn) 今日頭條 、網(wǎng)易新聞 的頻道排序、移動(dòng)

    實(shí)現(xiàn)方案4:使用兩個(gè)GridLayout實(shí)現(xiàn),也就是本文要介紹的方式

    拖拽

    長(zhǎng)按item開始拖拽

    private View.OnLongClickListener longClickListener = new View.OnLongClickListener() {@Overridepublic boolean onLongClick(View v) {//長(zhǎng)按時(shí),開始拖拽操作,顯示出陰影//被拖拽的視圖其實(shí)就是v參數(shù)dragedView = v;v.startDrag(null, new View.DragShadowBuilder(v), null, 0);v.setEnabled(false);// v.startDragAndDrop(null, new View.DragShadowBuilder(v), null, 0);return false;}};

    拖拽方法參數(shù)說(shuō)明

    • startDragAndDrop() api24
    • startDrag(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flag)

    參數(shù)1:ClipData data 拖拽過(guò)程中可以transferred的數(shù)據(jù),可以為空

    參數(shù)2:DragShadowBuilder shadowBuilder,拖拽陰影效果創(chuàng)建者

    參數(shù)3:Object myLocalState,拖拽狀態(tài)

    參數(shù)4:int flag,可以控制拖拽操作的flag,未定義,傳0即可

    拖拽監(jiān)聽

    private View.OnDragListener dragListener = new View.OnDragListener() {/*** ACTION_DRAG_STARTED:當(dāng)拖拽操作執(zhí)行時(shí),就會(huì)執(zhí)行一次* DragEvent.ACTION_DRAG_ENDED:當(dāng)拖拽事件結(jié)束,手指抬起時(shí),就是執(zhí)行一次* DragEvent.ACTION_DRAG_ENTERED:當(dāng)手指進(jìn)入設(shè)置了拖拽監(jiān)聽的控件范圍內(nèi)的瞬間執(zhí)行一次* DragEvent.ACTION_DRAG_EXITED:當(dāng)手指離開設(shè)置了拖拽監(jiān)聽的控件范圍內(nèi)的瞬間執(zhí)行一次* DragEvent.ACTION_DRAG_LOCATION:當(dāng)手指在設(shè)置了拖拽監(jiān)聽的控件范圍內(nèi),移動(dòng)時(shí),實(shí)時(shí)會(huì)執(zhí)行,執(zhí)行N次* DragEvent.ACTION_DROP:當(dāng)手指在設(shè)置了拖拽監(jiān)聽的控件范圍內(nèi)松開時(shí),執(zhí)行一次*** @param v 當(dāng)前監(jiān)聽拖拽事件的view(其實(shí)就是mGridLayout)* @param event 拖拽事件* @return*/@Overridepublic boolean onDrag(View v, DragEvent event) {String dragEventAction = getDragEventAction(event);System.out.println(dragEventAction);// Rect rect = new Rect();// rect.contains()switch (event.getAction()) {//當(dāng)拖拽事件開始時(shí),創(chuàng)建出與子控件對(duì)應(yīng)的矩形數(shù)組case DragEvent.ACTION_DRAG_STARTED:initRects();break;case DragEvent.ACTION_DRAG_LOCATION://手指移動(dòng)時(shí),實(shí)時(shí)判斷觸摸是否進(jìn)入了某一個(gè)子控件int touchIndex = getTouchIndex(event);//說(shuō)明觸摸點(diǎn)進(jìn)入了某一個(gè)子控件,判斷被拖拽的視圖與進(jìn)入的子控件對(duì)象不是同一個(gè)的時(shí)候才進(jìn)行刪除添加操作if (touchIndex > -1&&dragedView != null&&dragedView != mGridLayout.getChildAt(touchIndex)) {mGridLayout.removeView(dragedView);mGridLayout.addView(dragedView,touchIndex);}break;case DragEvent.ACTION_DRAG_ENDED://拖拽事件結(jié)束后,讓被拖拽的view設(shè)置為可用,否則背景變紅,并且長(zhǎng)按事件會(huì)失效if (dragedView != null) {dragedView.setEnabled(true);}break;}return true;}};

    DragEvent

    拖拽事件說(shuō)明
    ACTION_DRAG_STARTED當(dāng)拖拽操作執(zhí)行時(shí),就會(huì)執(zhí)行一次
    DragEvent.ACTION_DRAG_ENDED當(dāng)拖拽事件結(jié)束,手指抬起時(shí),就是執(zhí)行一次
    DragEvent.ACTION_DRAG_ENTERED當(dāng)手指進(jìn)入設(shè)置了拖拽監(jiān)聽的控件范圍內(nèi)的瞬間執(zhí)行一次
    DragEvent.ACTION_DRAG_EXITED當(dāng)手指離開設(shè)置了拖拽監(jiān)聽的控件范圍內(nèi)的瞬間執(zhí)行一次
    DragEvent.ACTION_DRAG_LOCATION當(dāng)手指在設(shè)置了拖拽監(jiān)聽的控件范圍內(nèi),移動(dòng)時(shí),實(shí)時(shí)會(huì)執(zhí)行,執(zhí)行N次
    DragEvent.ACTION_DROP當(dāng)手指在設(shè)置了拖拽監(jiān)聽的控件范圍內(nèi)松開時(shí),執(zhí)行一次

    當(dāng)拖拽事件開始時(shí),創(chuàng)建出與子控件對(duì)應(yīng)的矩形數(shù)組

    private Rect[] mRects;private void initRects() {mRects = new Rect[mGridLayout.getChildCount()];for (int i = 0; i < mGridLayout.getChildCount(); i++) {View childView = mGridLayout.getChildAt(i);//創(chuàng)建與每個(gè)子控件對(duì)應(yīng)矩形對(duì)象Rect rect = new Rect(childView.getLeft(), childView.getTop(), childView.getRight(), childView.getBottom());mRects[i] = rect;}}

    手指移動(dòng)時(shí),實(shí)時(shí)判斷觸摸是否進(jìn)入了某一個(gè)子控件

    private int getTouchIndex(DragEvent event) {//遍歷所有的數(shù)組,如果包含了當(dāng)前的觸摸點(diǎn)返回索引即可for (int i = 0; i < mRects.length; i++) {Rect rect = mRects[i];if (rect.contains((int)event.getX(), (int)event.getY())) {return i;}}return -1;}

    是否允許拖拽

    public void setAllowDrag(boolean allowDrag) {this.allowdrag = allowDrag;if (this.allowdrag) {this.setOnDragListener(odl);} else {this.setOnDragListener(null);}}

    設(shè)置列數(shù)和動(dòng)畫

    //初始化方法 private void init() {// android:columnCount="4"// android:animateLayoutChanges="true"this.setColumnCount(columnCount);this.setLayoutTransition(new LayoutTransition()); }

    DragGridlayout

    public class DragGridlayout extends GridLayout{private static final int columnCount = 4;//列數(shù)private boolean isAllowDrag;//記錄當(dāng)前控件是否可以進(jìn)行拖拽操作public DragGridlayout(Context context) {this(context,null);}public DragGridlayout(Context context, AttributeSet attrs) {this(context, attrs,0);}public DragGridlayout(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}/* static SparseArray<String> dragEventType = new SparseArray<>();static{dragEventType.put(DragEvent.ACTION_DRAG_STARTED, "STARTED");dragEventType.put(DragEvent.ACTION_DRAG_ENDED, "ENDED");dragEventType.put(DragEvent.ACTION_DRAG_ENTERED, "ENTERED");dragEventType.put(DragEvent.ACTION_DRAG_EXITED, "EXITED");dragEventType.put(DragEvent.ACTION_DRAG_LOCATION, "LOCATION");dragEventType.put(DragEvent.ACTION_DROP, "DROP");}public static String getDragEventAction(DragEvent de){return dragEventType.get(de.getAction());}*///初始化方法private void init() {// android:columnCount="4"// android:animateLayoutChanges="true"this.setColumnCount(columnCount);this.setLayoutTransition(new LayoutTransition());}public void setItems(List<String> items) {for (String item : items) {addItem(item);}}public void addItem(String content, int index) {TextView tv = newItemView();tv.setText(content);addView(tv,index);}public void addItem(String content) {TextView tv = newItemView();tv.setText(content);addView(tv);}private TextView newItemView() {TextView tv = new TextView(getContext());int margin = dip2px(5);tv.setBackgroundResource(R.drawable.selector_tv_bg);GridLayout.LayoutParams layoutParams = new GridLayout.LayoutParams();layoutParams.width = getResources().getDisplayMetrics().widthPixels/4 - 2*margin;//寬為屏幕寬的4分之一layoutParams.height = dip2px(25);layoutParams.setMargins(margin,margin,margin,margin);tv.setGravity(Gravity.CENTER);tv.setLayoutParams(layoutParams);if (isAllowDrag) {//給條目設(shè)置長(zhǎng)按點(diǎn)擊事件tv.setOnLongClickListener(mLongClickListener);} else {tv.setOnLongClickListener(null);}//設(shè)置條目的點(diǎn)擊事件tv.setOnClickListener(onClickListener);return tv;}/** dip轉(zhuǎn)換px */public int dip2px(int dip) {final float scale = getResources().getDisplayMetrics().density;return (int) (dip * scale + 0.5f);}private View dragedView;//被拖拽的視圖private View.OnLongClickListener mLongClickListener = new View.OnLongClickListener() {@Overridepublic boolean onLongClick(View v) {//長(zhǎng)按時(shí),開始拖拽操作,顯示出陰影//被拖拽的視圖其實(shí)就是v參數(shù)dragedView = v;v.startDrag(null, new View.DragShadowBuilder(v), null, 0);v.setEnabled(false);//v.startDragAndDrop(null, new View.DragShadowBuilder(v), null, 0); // api24return true;}};private OnClickListener onClickListener = new OnClickListener() {@Overridepublic void onClick(View v) {if(onDragItemClickListener != null){onDragItemClickListener.onDragItemClick((TextView) v);}}};public void setAllowDrag(boolean isAllowDrag) {this.isAllowDrag = isAllowDrag;if (this.isAllowDrag) {this.setOnDragListener(mDragListener);} else {this.setOnDragListener(null);}}private View.OnDragListener mDragListener = new View.OnDragListener() {/*** ACTION_DRAG_STARTED:當(dāng)拖拽操作執(zhí)行時(shí),就會(huì)執(zhí)行一次* DragEvent.ACTION_DRAG_ENDED:當(dāng)拖拽事件結(jié)束,手指抬起時(shí),就是執(zhí)行一次* DragEvent.ACTION_DRAG_ENTERED:當(dāng)手指進(jìn)入設(shè)置了拖拽監(jiān)聽的控件范圍內(nèi)的瞬間執(zhí)行一次* DragEvent.ACTION_DRAG_EXITED:當(dāng)手指離開設(shè)置了拖拽監(jiān)聽的控件范圍內(nèi)的瞬間執(zhí)行一次* DragEvent.ACTION_DRAG_LOCATION:當(dāng)手指在設(shè)置了拖拽監(jiān)聽的控件范圍內(nèi),移動(dòng)時(shí),實(shí)時(shí)會(huì)執(zhí)行,執(zhí)行N次* DragEvent.ACTION_DROP:當(dāng)手指在設(shè)置了拖拽監(jiān)聽的控件范圍內(nèi)松開時(shí),執(zhí)行一次** @param v 當(dāng)前監(jiān)聽拖拽事件的view(其實(shí)就是mGridLayout)* @param event 拖拽事件* @return*/@Overridepublic boolean onDrag(View v, DragEvent event) {switch (event.getAction()) {//當(dāng)拖拽事件開始時(shí),創(chuàng)建出與子控件對(duì)應(yīng)的矩形數(shù)組case DragEvent.ACTION_DRAG_STARTED:initRects();break;case DragEvent.ACTION_DRAG_LOCATION://手指移動(dòng)時(shí),實(shí)時(shí)判斷觸摸是否進(jìn)入了某一個(gè)子控件int touchIndex = getTouchIndex(event);//說(shuō)明觸摸點(diǎn)進(jìn)入了某一個(gè)子控件,判斷被拖拽的視圖與進(jìn)入的子控件對(duì)象不是同一個(gè)的時(shí)候才進(jìn)行刪除添加操作if (touchIndex > -1 && dragedView != null && dragedView != DragGridlayout.this.getChildAt(touchIndex)) {DragGridlayout.this.removeView(dragedView);DragGridlayout.this.addView(dragedView,touchIndex);}break;case DragEvent.ACTION_DRAG_ENDED://拖拽事件結(jié)束后,讓被拖拽的view設(shè)置為可用,否則背景變紅,并且長(zhǎng)按事件會(huì)失效if (dragedView != null) {dragedView.setEnabled(true);}break;}return true;}};//手指移動(dòng)時(shí),實(shí)時(shí)判斷觸摸是否進(jìn)入了某一個(gè)子控件private int getTouchIndex(DragEvent event) {//遍歷所有的數(shù)組,如果包含了當(dāng)前的觸摸點(diǎn)返回索引即可for (int i = 0; i < mRects.length; i++) {Rect rect = mRects[i];if (rect.contains((int)event.getX(), (int)event.getY())) {return i;}}return -1;}//當(dāng)拖拽事件開始時(shí),創(chuàng)建出與子控件對(duì)應(yīng)的矩形數(shù)組private Rect[] mRects;private void initRects() {mRects = new Rect[this.getChildCount()];for (int i = 0; i < this.getChildCount(); i++) {View childView = this.getChildAt(i);//創(chuàng)建與每個(gè)子控件對(duì)應(yīng)矩形對(duì)象Rect rect = new Rect(childView.getLeft(), childView.getTop(), childView.getRight(), childView.getBottom());mRects[i] = rect;}}private OnDragItemClickListener onDragItemClickListener;public interface OnDragItemClickListener{public void onDragItemClick(TextView tv);}public void setOnDragItemClickListener(OnDragItemClickListener onDragItemClickListener) {this.onDragItemClickListener = onDragItemClickListener;} }

    MainActivity

    布局文件

    <?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayout android:id="@+id/activity_main"xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Button android:layout_width="match_parent"android:layout_height="36dp"android:gravity="center_vertical"android:onClick="addItem"android:text="添加條目"android:textColor="?android:attr/textColorPrimary"/><com.github.draggridlayout.DragGridlayout android:id="@+id/selectedChannel"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginBottom="16dp"android:layout_marginTop="16dp"/><TextView android:id="@+id/textView"android:layout_width="match_parent"android:layout_height="36dp"android:background="?attr/colorButtonNormal"android:gravity="center_vertical"android:padding="5dp"android:text="點(diǎn)擊選擇頻道"android:textColor="?android:attr/textColorPrimary"/><com.github.draggridlayout.DragGridlayout android:id="@+id/unSelectedChannel"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="16dp"/></LinearLayout></android.support.v4.widget.NestedScrollView>

    代碼實(shí)現(xiàn)

    public class MainActivity extends AppCompatActivity {private DragGridlayout mSelectedChannel;private DragGridlayout mUnSelectedChannel;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);initViews();initData();initEvent();}private void initViews() {setContentView(R.layout.activity_main);mSelectedChannel = (DragGridlayout) findViewById(R.id.selectedChannel);mUnSelectedChannel = (DragGridlayout) findViewById(R.id.unSelectedChannel);mSelectedChannel.setAllowDrag(true);mUnSelectedChannel.setAllowDrag(true);}private void initData() {List<String> selectedChannel = new ArrayList<>();selectedChannel.add("頭條");...mSelectedChannel.setItems(selectedChannel);List<String> unSelectedChannel = new ArrayList<>();unSelectedChannel.add("NBA");...mUnSelectedChannel.setItems(unSelectedChannel);}public void initEvent(){//設(shè)置條目點(diǎn)擊監(jiān)聽mSelectedChannel.setOnDragItemClickListener(new DragGridlayout.OnDragItemClickListener() {@Overridepublic void onDragItemClick(TextView tv) {//移除點(diǎn)擊的條目,把條目添加到下面的GridlayoutmSelectedChannel.removeView(tv);//移除是需要時(shí)間,不能直接添加mUnSelectedChannel.addItem(tv.getText().toString(),0);}});mUnSelectedChannel.setOnDragItemClickListener(new DragGridlayout.OnDragItemClickListener() {@Overridepublic void onDragItemClick(TextView tv) {//移除點(diǎn)擊的條目,把條目添加到上面的GridlayoutmUnSelectedChannel.removeView(tv);//移除是需要時(shí)間,不能直接添加mSelectedChannel.addItem(tv.getText().toString());}});}private int index = 0;public void addItem(View view) {mSelectedChannel.addItem("頻道" + index++,0);}}

    源代碼

    https://github.com/JackChan1999/DragGridLayout

    總結(jié)

    以上是生活随笔為你收集整理的新闻频道管理的炫酷实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。