重写GridView实现仿今日头条的频道编辑页(1)

本文旨在通过重写GridView,配合系统弹窗实现仿今日头条的频道编辑页面

注:由于代码稍长,本文仅列出关键部分,完整工程请参见【https://github.com/G9YH/YHChannelEdit

在开始讲解盗版的实现方案前,让我们先来看看正版与盗版的实际使用效果对比,首先是正版

接下来是盗版

当然,在部分视图的设计方面还是存在着不小的差异的,但这一页面大部分基本功能已然实现了。那么接下来,就让我们开始我们的模仿秀

实现思想

事实上,我的频道列表中,如何实现长按拖拽并交换频道位置是整个页面的核心难点。大致实现思路如下

  • 长按某个频道后,在该频道上方生成一个与之相同的弹窗,同时隐藏该频道视图
  • 当手指按下时,该弹窗跟随触摸点移动
  • 弹窗移动过程中,根据触摸点交换其他频道位置
  • 当手指抬起时,在触摸点当前对应的位置处生成一个与弹窗相同的频道视图

抛开这一问题,其余部分的实现逻辑都较为简单,这里不再赘述,下文将更会有具体实现的介绍

实现要点

我的频道

正如前文所言,这一部分的核心在于重写GridView以及系统弹窗,那么,首先自然是系统弹窗权限的开启

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

接下来即是GridView的重写。首先定义了两个常量用户标识当前的模式,即编辑模式和普通模式

private static final int MODE_EDIT = 1;
private static final int MODE_NORMAL = 2;

然后实现了OnItemLongClickListener接口

    @Override
    public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
        //  已处于移动模式
        if (mode == MODE_EDIT) {
            return false;
        }
 
        textEdit.setText("完成");
 
        ....
 
        //  推荐标签无法移动或删除
        if (i == 0) {
            return false;
        }
 
        //  判断并获取弹窗权限
        permissionGetter.alertWindowPermissionRequest();
 
        ....
 
        //  初始化弹窗
        initWindow();
 
        return true;
    }

这里需要注意到的是PermissionGetter类,我们知道,尽管在manifests中定义了系统弹窗的权限,但通常而言手机是需要用户手动为app开启相关权限的。PermissionGetter类的作用即在于此,该类通过分别处理小米、魅族以及华为等几个较为特殊的Android系统,基本实现了大部分机型的弹窗权限申请功能

/**
 * 判断系统是否已为应用开启某项权限
 *
 * @param num 权限编号
 * @return 已开启则返回0,否则返回1
 */
private int checkPermission(int num) {
    int version = Build.VERSION.SDK_INT;
    if (version >= 19) {
        ....
    }
    return -1;
}
 
....
 
/**
 * Android 6.0之后的手机需要进行弹窗权限的申请
 * 其中小米、魅族以及华为三种机型需要特殊处理
 */
public void alertWindowPermission() {
    if (this.checkPermission(24) == 1) {
        Toast toast = Toast.makeText(
                context, "请先为您的手机开启悬浮窗权限", Toast.LENGTH_SHORT);
        toast.show();
        //  处理小米手机权限
        if ("Xiaomi".equals(Build.MANUFACTURER)) {
            ....
            }
        }
        //  处理魅族手机权限
        else if ("Meizu".equals(Build.MANUFACTURER)) {
            ....
        }
        //  处理华为手机权限
        else if ("Huawei".equals(Build.MANUFACTURER)) {
            ....
        }
        //  处理其他手机权限
        else if (Build.VERSION.SDK_INT >= 23) {
            ....
        }
    }
}

在长按接口中实现了弹窗的初始化后,将模式mode设置为MODE_EDIT。此时即可通过重写onTouchEvent(MovtionEvent motionEvent)方法来判断何时进行弹窗的更新以及关闭等工作

@Override
public boolean onTouchEvent(MotionEvent motionEvent) {
    switch (motionEvent.getAction()) {
        case MotionEvent.ACTION_DOWN:
            break;
        case MotionEvent.ACTION_MOVE:
            if (mode == MODE_EDIT) {
                updateWindow(motionEvent);
            }
            break;
        case MotionEvent.ACTION_UP:
            if (mode == MODE_EDIT) {
                closeWindow();
            }
            break;
    }
    return super.onTouchEvent(motionEvent);
}

当手指按下时,持续更新弹窗位置,并根据其位置交换其他频道的位置,当然不要忘记了交换动作相应的动画

当手指抬起时,将模式mode设置为MODE_NORMAL,并在弹窗当前对应的频道处生成一个与弹窗相同的视图,同时移除该弹窗视图即可

频道推荐

这一部分的实现就较为简单了,只需利用GridView展示频道,然后实现OnItemClickListener接口,点击时将该item移除并添加至我的频道视图中即可

@OnItemClick(R.id.grid_recommend) void gridRecommend(int position) {
    String string = listHolder.getRecommendList().get(position);
    //  我的频道中增加标签
    listHolder.getMineList().add(string);
    //  频道推荐中删除标签
    listHolder.getRecommendList().remove(position);
 
    //  更新各频道数据
    mineAdapter.moveNotifyDataSetChanged(false, -1);
    recommendAdapter.notifyDataSetChanged();
}

列表缓存

事实上,在实际开发中,通常可以采用SharedPreferences配合服务器端来实现我的频道以及频道推荐两个列表内容的持久化存储。但由于这里仅仅是实现一个demo,因此存储功能仅通过一个单例类ListHolder来模拟实现。其中ListHolder单例的实现方式如下,参考了我之前的一篇博客《单例模式的终极实现方案》

public class ListHolder {
    private List<String> mineList = new ArrayList<>();
    private List<String> recommendList = new ArrayList<>();
 
    private static class Instance {
        private static ListHolder instance = new ListHolder();
    }
 
    private ListHolder() {
    }
 
    public static ListHolder getInstance() {
        return Instance.instance;
    }
 
    public get() & set()
}

优化改进

尽管到目前为止,我们已经实现了大部分的基本功能,但仍与正版有部分差异,例如频道列表内容的存储、部分动画的实现以及视图设计的差别等等,这一系列问题都将在之后的开发工作中继续优化

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,520评论 25 707
  • 内容抽屉菜单ListViewWebViewSwitchButton按钮点赞按钮进度条TabLayout图标下拉刷新...
    皇小弟阅读 46,712评论 22 664
  • 1.什么是Activity?问的不太多,说点有深度的 四大组件之一,一般的,一个用户交互界面对应一个activit...
    JoonyLee阅读 5,728评论 2 51
  • 今年身为大三的临近毕业生,有很多的无奈和困惑,以自己为例简谈对一些鸡汤的看法。 我是一个极其自卑的人,可能是因为...
    间逸阅读 194评论 0 0
  • ——春天的主旋律 今夜 我注定孤独 更无力逃遁 只能与文字缱绻 组装快乐和忧伤 剪辑欢笑和哭泣 拼凑人世...
    春天的主旋律阅读 315评论 0 3