Android开发-仿Soul社交应用首页3D星球视图旋转样式

前 言

前段时间看到Soul社交应用首页的3D星球视图旋转样式(如下图),所以就想自己能不能实现一个类似的功能。本着不要重复造轮子的原则,所以在网上找有没有开源的轮子,果然真找到有大神开源的依赖库,大神开源的依赖库如下:https://github.com/misakuo/3dTagCloudAndroid,那么下面看看如何实现仿Soul社交应用首页3D星球视图旋转样式的功能。

在这里插入图片描述

编码实现
  • 首先在AS的内层build.gradle里添加3d星球视图旋转样式的依赖
dependencies {
    ........
    // 3d星球视图旋转样式
    implementation 'com.moxun:tagcloudlib:1.2.0'
}
  • 添加 Layout 布局
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#12121F"
    tools:context=".MainActivity">

    <com.moxun.tagcloudlib.view.TagCloudView
        android:id="@+id/mTagCloudView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:autoScrollMode="uniform"
        app:radiusPercent="0.8"
        app:scrollSpeed="1" />

</androidx.constraintlayout.widget.ConstraintLayout>

xml布局文件中的<com.moxun.tagcloudlib.view.TagCloudView />就是用来加载3D星球视图旋转的视图的。

  • 设置3d星球视图Adapter

自定义的适配器Adapter要继承TagsAdapter,代码如下:

/**
 * 3d星球View适配器
 */
public class TagCloudViewAdapter extends TagsAdapter {

    private Context mContext;
    private List<StarModel> mList;
    private LayoutInflater inflater;

    public TagCloudViewAdapter(Context mContext, List<StarModel> mList) {
        this.mContext = mContext;
        this.mList = mList;
        inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    /**
     * 返回Tag数量
     *
     * @return
     */
    @Override
    public int getCount() {
        return mList.size();
    }

    /**
     * 返回每个Tag实例
     *
     * @param context
     * @param position
     * @param parent
     * @return
     */
    @Override
    public View getView(Context context, int position, ViewGroup parent) {
        StarModel model = mList.get(position);
        View mView = null;
        ViewHolder viewHolder = null;
        if (mView == null) {
            viewHolder = new ViewHolder();
            //初始化View
            mView = inflater.inflate(R.layout.layout_3d_item, null);
            //初始化控件
            viewHolder.iv_star_icon = mView.findViewById(R.id.iv_star_icon);
            viewHolder.tv_star_name = mView.findViewById(R.id.tv_star_name);
            mView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) mView.getTag();
        }
        if (!TextUtils.isEmpty(model.getPhotoUrl())) {
            RequestOptions options = new RequestOptions()
                    .placeholder(R.drawable.ic_user)
                    .error(R.drawable.ic_user);
            Glide.with(mContext).load(model.getPhotoUrl()).apply(options).into(viewHolder.iv_star_icon);
        } else {
            viewHolder.iv_star_icon.setImageResource(R.drawable.ic_user);
        }
        viewHolder.tv_star_name.setText(model.getNickName());
        return mView;
    }

    /**
     * 返回Tag数据
     *
     * @param position
     * @return
     */
    @Override
    public Object getItem(int position) {
        return mList.get(position);
    }

    /**
     * 针对每个Tag返回一个权重值,该值与ThemeColor和Tag初始大小有关;
     * 一个简单的权重值生成方式是对一个数N取余或使用随机数
     *
     * @param position
     * @return
     */
    @Override
    public int getPopularity(int position) {
        return 7;
    }

    /**
     * Tag主题色发生变化时会回调该方法
     *
     * @param view
     * @param themeColor
     */
    @Override
    public void onThemeColorChanged(View view, int themeColor) {

    }

    class ViewHolder {
        private ImageView iv_star_icon;
        private TextView tv_star_name;
    }
    
}

其中继承后回调以下几个方法和作用如下:
public int getCount() —> 返回Tag数量;
public View getView(Context context, int position, ViewGroup parent) —> 返回每个Tag实例;
public Object getItem(int position) —> 返回Tag数据;
public int getPopularity(int position) —> 针对每个Tag返回一个权重值,该值与ThemeColor和Tag初始大小有关;一个简单的权重值生成方式是对一个数N取余或使用随机数;
public void onThemeColorChanged(View view,int themeColor) —> Tag主题色发生变化时会回调该方法。

  • 加载视图

在Activity或者Fragment设置视图的适配器数据以及加载视图,代码以下:

// 设置适配器数据
mTagCloudViewAdapter = new TagCloudViewAdapter(this, mStarModelList);
mTagCloudView.setAdapter(mTagCloudViewAdapter);

设置 3d Tag View 条目点击事件

 // 设置 3d Tag View 条目点击事件
mTagCloudView.setOnTagClickListener(new TagCloudView.OnTagClickListener() {
     @Override
     public void onItemClick(ViewGroup parent, View view, int position) {
          String userId = mStarModelList.get(position).getUserId();
          String nickName = mStarModelList.get(position).getNickName();
          Toast.makeText(MainActivity.this, String.format("用户id:%s;用户昵称:%s", userId, nickName), Toast.LENGTH_LONG).show();
     }
});

相关的定制属性如下:

属性xml代码值类型
自动滚动app:autoScrollModesetAutoScrollMode(int mode)enum [disable,uniform,decelerate]
半径百分比app:radiusPercentsetRadiusPercent(float percent)float [0,1]
滚动速度app:scrollSpeedsetScrollSpeed(float scrollSpeed)float [0,+]
起始颜色app:lightColorsetLightColor(int color)int
终止颜色app:darkColorsetDarkColor(int color)int

完整的代码以下:

public class MainActivity extends AppCompatActivity {

    @BindView(R.id.mTagCloudView)
    TagCloudView mTagCloudView;

    private TagCloudViewAdapter mTagCloudViewAdapter;
    private List<StarModel> mStarModelList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        // 获取用户数据
        getData();

        // 设置适配器数据
        mTagCloudViewAdapter = new TagCloudViewAdapter(this, mStarModelList);
        mTagCloudView.setAdapter(mTagCloudViewAdapter);

        // 设置 3d Tag View 条目点击事件
        mTagCloudView.setOnTagClickListener(new TagCloudView.OnTagClickListener() {
            @Override
            public void onItemClick(ViewGroup parent, View view, int position) {
                String userId = mStarModelList.get(position).getUserId();
                String nickName = mStarModelList.get(position).getNickName();
                Toast.makeText(MainActivity.this, String.format("用户id:%s;用户昵称:%s", userId, nickName), Toast.LENGTH_LONG).show();
            }
        });

    }

    /**
     * 模拟从网络获取100条用户数据
     */
    private void getData() {

        if (mStarModelList != null) mStarModelList.clear();
        for (int i = 0; i < 100; i++) {
            StarModel data = new StarModel();
            data.setUserId("" + i);
            data.setNickName("彼岸雨敲窗" + i);
            data.setPhotoUrl("https://fukaimei.oss-cn-beijing.aliyuncs.com/images/ic_user.png?x-oss-process=style/thumb");
            mStarModelList.add(data);
        }

    }

}
界面运行效果图如下:

在这里插入图片描述

apk安装包下载体验地址:

可以扫描以下二维码进行下载安装,或者点击以下链接 http://app.fukaimei.top/3dTagView 进行下载安装体验。
在这里插入图片描述

———————— The end ————————

码字不易,如果您觉得这篇博客写的比较好的话,可以赞赏一杯咖啡吧~~
在这里插入图片描述


Demo程序源码下载地址一(GitHub)
Demo程序源码下载地址二(码云)

<think>好的,我现在要解决用户的问题:麒麟安全更新安装向导卡住不动,是否可以终止。首先,我需要了解用户的具体情况。用户在使用麒麟系统时,进行安全更新安装,结果向导界面卡住不动,无法继续。用户想知道是否可以终止这个进程,以及如何操作。 首先,我应该考虑麒麟系统是基于哪个发行版的,比如是Ubuntu还是CentOS,或者其他。不同的Linux发行版在包管理和进程处理上可能有差异。不过麒麟系统通常是基于Debian或Ubuntu的,所以可能需要用apt或dpkg相关的命令来处理。 接下来,用户的问题是关于安全更新安装卡住的情况。这时候需要考虑可能的原因:软件源问题、包依赖冲突、硬件资源不足(如CPU、内存、磁盘空间)、进程死锁等。但用户当前更关心的是能否终止以及如何安全终止,而不是原因分析。 用户询问是否可以终止,我需要确定终止安装进程可能带来的风险。通常来说,在包管理过程中终止进程可能导致系统状态不一致,比如部分安装的软件包、未完成的配置,甚至系统不稳定。但有时候卡死的情况下,可能不得不终止。 接下来,我需要给出步骤:首先检查系统资源,比如使用top或htop查看是否有进程占用过高,或者是否有磁盘I/O瓶颈。然后尝试等待一段时间,可能只是暂时卡顿。如果确定卡死,可能需要终止相关进程,比如dpkg或apt的进程,然后进行清理和修复。 然后,在终止后,用户需要如何修复可能的问题。比如使用apt的修复命令,如sudo apt install -f,或者dpkg --configure -a来修复未完成的配置。此外,可能需要清除锁文件,如/var/lib/dpkg/lock,但需要注意权限和正确的方法,避免直接删除导致其他问题。 另外,用户可能需要检查日志,如/var/log/apt/下的日志文件,或者使用journalctl来查看系统日志,找出卡住的原因,以便后续解决。 最后,建议用户在更新前做好数据备份,避免重要数据丢失,并在必要时联系技术支持。 需要确保回答结构清晰,分步骤说明,同时提醒用户潜在风险,并给出安全操作的指导。还要注意使用中文,避免使用专业术语过于复杂,让用户容易理解。</think>麒麟安全更新安装向导卡条不动时,可按以下步骤安全处理: ### 一、初步判断与等待 1. **观察等待** 若进度条停滞时间未超过 **30分钟**,建议保持当前状态: - 可能是后台正在处理复杂依赖或大型文件 - 可打开终端执行 `top` 或 `htop`,观察 `apt`/`dpkg` 进程是否占用 CPU/磁盘资源 2. **检查系统资源** - 使用快捷键 `Ctrl+Alt+T` 打开终端 - 输入 `df -h` 检查磁盘空间是否充足(重点关注 `/` 和 `/boot` 分区) - 输入 `free -h` 确认内存是否耗尽 ### 二、强制终止操作(慎用!) 若确认进程完全卡死且超过 **1小时** 无响应: 1. **终止更新进程** ```bash sudo killall apt-get dpkg ``` 2. **解除锁定文件** ```bash sudo rm /var/lib/dpkg/lock sudo rm /var/lib/apt/lists/lock ``` ### 三、修复系统状态 1. **修复包管理器** ```bash sudo dpkg --configure -a sudo apt install -f ``` 2. **清理残留** ```bash sudo apt autoremove sudo apt clean ``` ### 四、后续处理建议 1. **重新尝试更新** ```bash sudo apt update && sudo apt upgrade ``` 2. **日志排查(可选)** - 查看更新日志:`cat /var/log/apt/history.log` - 检查错误信息:`journalctl -u apt.service` 3. **预防措施** - 更新前创建系统快照:`sudo timeshift --create` - 使用 `nohup` 后台更新: ```bash nohup sudo apt upgrade -y & ``` ### 五、风险说明 | 操作类型 | 潜在风险 | 发生概率 | |----------------|-----------------------------------|----------| | 强制终止进程 | 软件包半安装状态导致依赖损坏 | 中 | | 直接断电 | 文件系统损坏或系统无法启动 | 高 | | 不修复直接使用 | 后续安装/更新功能异常 | 高 | 建议优先通过 SSH 远程连接检查系统状态,若物理机直接卡死且无法通过终端操作,可长按电源键 **6秒** 强制关机,但需做好数据丢失准备。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值