Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >neo4j︱Cypher完整案例csv导入、关系联通、高级查询(三)

neo4j︱Cypher完整案例csv导入、关系联通、高级查询(三)

作者头像
悟乙己
发布于 2019-05-26 12:11:46
发布于 2019-05-26 12:11:46
3.3K00
代码可运行
举报
文章被收录于专栏:素质云笔记素质云笔记
运行总次数:0
代码可运行

数据库常规的有:neo4j(支持超多语言)、JanusGraph/Titan(分布式)、Orientdb,google也开源了图数据库Cayley(Go语言构成)、PostgreSQL存储RDF格式数据。

—- 目前的几篇相关:—–

neo4j︱图数据库基本概念、操作罗列与整理(一)

neo4j︱Cypher 查询语言简单案例(二)

neo4j︱Cypher完整案例csv导入、关系联通、高级查询(三)

第三篇,一个比较完整的csv导入,并进行查询的案例,涉及的数据量较大,更贴合实际场景。


NorthWind Introduction

案例解析,官网:https://neo4j.com/developer/guide-importing-data-and-etl/

Github地址:https://github.com/neo4j-contrib/developer-resources

如果要全部一次性运行的话,可以键入命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
bin/neo4j-shell -path northwind.db -file import_csv.cypher

本文是官方的一个比较完整的案例,包括三部分:csv载入、建立实体关联、查询

其中csv载入与建立实体关联可以了解到如何为Neo4j的数据集;

cypher的查询也有难易之分,该案例中较好得进行了使用,有初级查询与高级查询。

该数据集 NorthWind dataset 可以在github之中找到:neo4j-contrib/developer-resources

整个数据结构如图:

很复杂是吧…来理一下逻辑:

一、载入基本实体信息

保证数据格式

因为neo4j是utf-8的,而CSV默认保存是ANSI的,需要用记事本另存为成UTF-8的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Create customers
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///customers.csv" AS row
CREATE (:Customer {companyName: row.CompanyName, customerID: row.CustomerID, fax: row.Fax, phone: row.Phone});

// Create products
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///products.csv" AS row
CREATE (:Product {productName: row.ProductName, productID: row.ProductID, unitPrice: toFloat(row.UnitPrice)});

// Create suppliers
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///suppliers.csv" AS row
CREATE (:Supplier {companyName: row.CompanyName, supplierID: row.SupplierID});

// Create employees
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///employees.csv" AS row
CREATE (:Employee {employeeID:row.EmployeeID,  firstName: row.FirstName, lastName: row.LastName, title: row.Title});

// Create categories
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///categories.csv" AS row
CREATE (:Category {categoryID: row.CategoryID, categoryName: row.CategoryName, description: row.Description});

USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///orders.csv" AS row
MERGE (order:Order {orderID: row.OrderID}) ON CREATE SET order.shipName =  row.ShipName;

注意:

执行两次会重复加载,注意!

“file:///customers.csv”中的’///’请注意!

CREATE (:Product {productName: row.ProductName)})其中:

  • Product为图ID,可以通过Match (customers) return customers进行查看;
  • row.ProductName的用法,跟dataframe差不多;
  • 类似dict,其中的productName为Key

其中有一个比较奇怪的表格,那就是最后一个:orders.csv

为了查询更快,可以建立索引:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE INDEX ON :Product(productID);
CREATE INDEX ON :Product(productName);
CREATE INDEX ON :Category(categoryID);
CREATE INDEX ON :Employee(employeeID);
CREATE INDEX ON :Supplier(supplierID);
CREATE INDEX ON :Customer(customerID);
CREATE INDEX ON :Customer(customerName);

给每个节点比较重要的ID字段建立索引。

不能同时执行,不然会报错:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Neo.ClientError.Statement.SyntaxError

同时添加一个约束:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE CONSTRAINT ON (o:Order) ASSERT o.orderID IS UNIQUE;

同时,如果需要修改其中一部分内容,可参考下面案例:

如果Janet is now reporting to Steven那么久可以如以下方式进行修改:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
MATCH (mgr:Employee {EmployeeID:5})
MATCH (emp:Employee {EmployeeID:3})-[rel:REPORTS_TO]->()
DELETE rel
CREATE (emp)-[:REPORTS_TO]->(mgr)
RETURN *;

定位到emp,把有关联的都先删掉DELETE,然后create新的关联。

延伸一:csv载入的两种方式(参考:3.3.20. LOAD CSV

同时csv载入的方式有两种:本地载入+在线文档载入:

在线载入:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
LOAD CSV FROM 'https://neo4j.com/docs/developer-manual/3.3/csv/artists.csv' AS line
CREATE (:Artist { name: line[1], year: toInteger(line[2])})

本地载入中有个Bug,就是怎么写地址,难道要这么写?file:///C:\Users\mattzheng\Desktop\categories.csv,显然是不对的。

那么本地的话,需要把内容放到固定的文件夹之中,一个叫import文件夹之中。

有可能在:在XXX\Neo4j\graph.db\import文件夹内

也有可能在其他东西,笔者当时的文件夹路径藏得很深是:C:\Users\matt\.Neo4jDesktop\neo4jDatabases\database-b82284eb-23ab-4a42-8a83-f13af055ecf0\installation-3.3.4\import

笔者也是误打误撞找到了这个链接,是通过报错提醒得到的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///C:\\Desktop\\categories.csv" AS row
CREATE (:Customer {companyName: row.CompanyName, customerID: row.CustomerID, fax: row.Fax, phone: row.Phone});

然后他会报错:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Couldn't load the external resource at: file:/C:\Users\matt\.Neo4jDesktop\neo4jDatabases\database-b82284eb-23ab-4a42-8a83-f13af055ecf0\installation-3.3.4\import\categories.csv

.

.


二、建立关联

2.1 order与 products/employees关联

order与 products and employees的关联:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///orders.csv" AS row
MATCH (order:Order {orderID: row.OrderID})
MATCH (product:Product {productID: row.ProductID})
MERGE (order)-[pu:PRODUCT]->(product)
ON CREATE SET pu.unitPrice = toFloat(row.UnitPrice), pu.quantity = toFloat(row.Quantity);
//同时,创立新的关联属性,on create的作用

USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///orders.csv" AS row
MATCH (order:Order {orderID: row.OrderID})
MATCH (employee:Employee {employeeID: row.EmployeeID})
MERGE (employee)-[:SOLD]->(order);

USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///orders.csv" AS row
MATCH (order:Order {orderID: row.OrderID})
MATCH (customer:Customer {customerID: row.CustomerID})
MERGE (customer)-[:PURCHASED]->(order);

toFloat(row.UnitPrice)当数据中为数值型,则需要规定关系类型。

文本型可以不用规定具体的类似是啥。

MATCH (order:Order {orderID: row.OrderID})的意思为将图名称Order赋值为order,同时选中orderID=row.OrderID这些内容;

pu:PRODUCT中,pu代表关系的统称;PRODUCT代表关系的名称

2.2 products,suppliers,categories关联

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///products.csv" AS row
MATCH (product:Product {productID: row.ProductID})
MATCH (supplier:Supplier {supplierID: row.SupplierID})
MERGE (supplier)-[:SUPPLIES]->(product);

USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///products.csv" AS row
MATCH (product:Product {productID: row.ProductID})
MATCH (category:Category {categoryID: row.CategoryID})
MERGE (product)-[:PART_OF]->(category);

2.3 employees之间的关联

在employees构建 ‘REPORTS_TO’关系来表达上下级关系。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///employees.csv" AS row
MATCH (employee:Employee {employeeID: row.EmployeeID})
MATCH (manager:Employee {employeeID: row.ReportsTo})
MERGE (employee)-[:REPORTS_TO]->(manager);

那么最终就会生成如下的内容:


三、初级查询

来源于:From SQL to Cypher – A hands-on Guide

官方原文中还有跟sql的对比,比较了解sql的可以看原文。

查询一:单独查询两个关联表
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
MATCH (:Order)<-[:SOLD]-(e:Employee)
return *
查询二: product的价格,并排序:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
match (p:Product)
return p.productName,p.unitPrice order by p.unitPrice DESC
limit 10;

逻辑:先从图数据库中定位p;order by 表示排序;limit 表 显示限制。

查询三:product 中’Chocolade’产品价格并排序:where、排序order使用
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 写法一:
match (p:Product)
where p.productName = 'Chocolade'
return p.productName,p.unitPrice order by p.unitPrice DESC limit 10;

# 写法二:
match (p:Product {productName : 'Chocolade'})
return p.productName,p.unitPrice order by p.unitPrice DESC limit 10;

写法一通过where来进行定位,写法二通过在match变量时,定义产品来进行产品定位。

查询四:product 中’Chocolade’以及’Chai’产品价格并排序:where、排序order使用
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
match (p:Product)
where p.productName IN ['Chocolade','Chai']
return p.productName,p.unitPrice order by p.unitPrice DESC limit 10;
查询五:条件筛选:where使用
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
MATCH (p:Product)
WHERE p.productName STARTS WITH "C" AND p.unitPrice > 100
RETURN p.productName, p.unitPrice;

意义为:选择p.productName中,首字母为’C’,同时unitPrice的价格大于100的范围内。

Indexing的使用

如果要加速某一列属性的查询,可以设置Index

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE INDEX ON :Product(productName);
CREATE INDEX ON :Product(unitPrice);
查询六:买了’Chocolade’的人有谁? :join用法

这边涉及四个表格:

  • Product产品表,productID;
  • Customer顾客表 CustomerID;
  • orders索引表,orderID + CustomerID
  • orders_Details索引表,orderID + productID //正确: MATCH (p:Product {productName:”Chocolade”})<-:PRODUCT-(:Order)<-:PURCHASED-(c:Customer) RETURN distinct c.companyName; //错误 //match后面,跟的是主表,主表不带关系[],此时主表为Product MATCH (c:Customer)-:PURCHASED RETURN distinct c.companyName //思考用法:用optional match之后为什么错误? match (c:Customer) where (p:Product {productName:”Chocolade”})<-:Product-(:Order)<-:PURCHASED-(c) return distinct c.companyName

这里笔者的思考是,为什么Product是主表,需要遵循逻辑关系,逻辑关系是Customer表->order表->Product表,而不是Product表反向。

思考用法:此时命令返回的是全部的c.companyName,而不是买了巧克力的,optional match也是一个根据关系生成变量步骤,不是添加约束的步骤;此时也不能用where,where后面跟的对变量的约束,而不能嫁接关系

查询七:我买了啥+买了几件?:统计功能

‘Drachenblut Delikatessen’买了啥,买了几件东西。

客户和订单之间的匹配成为可选匹配,这与外连接相当。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//写法1+普通match写法
MATCH  (p:Product)<-[pu:PRODUCT]-(:Order)<-[:PURCHASED]-(c:Customer {companyName:"Drachenblut Delikatessen"})
RETURN p.productName, toInt(sum(pu.unitPrice * pu.quantity)) AS volume
ORDER BY volume DESC;

//写法2+OPTIONAL MATCH
MATCH (c:Customer {companyName:"Drachenblut Delikatessen"})
OPTIONAL MATCH (p:Product)<-[pu:PRODUCT]-(:Order)<-[:PURCHASED]-(c)
RETURN p.productName, toInt(sum(pu.unitPrice * pu.quantity)) AS volume
ORDER BY volume DESC ;

OPTIONAL MATCH在我看来更多的还是赋值操作,而且可以在match写不下的时候,补充。

写法二,match先定义变量,然后在OPTIONAL MATCH后面补充连接关系。

其中:toInt()整数、sum()求和;AS volume生成新一列列名为’volumne’

查询八:雇员ID计数
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
MATCH (:Order)<-[:SOLD]-(e:Employee)
RETURN e.employeeID,count(*) AS cnt ORDER BY cnt DESC LIMIT 10

按照e.employeeID,进行分类count(*)计数。

e.employeeID

cnt

“4”

156

“3”

127

“1”

123

查询九:内容返回list/array格式
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
MATCH (o:Order)<-[:SOLD]-(e:Employee)
RETURN collect(e.lastName)

collect 将内容聚合成 (list,array)

.


四、高级查询

查询复杂度较大。来源于:Tutorial: Import Data Into Neo4j

查询一:Which Employee had the Highest Cross-Selling Count of ‘Chocolade’ and Which Product?

查询语句为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
MATCH (choc:Product {productName:'Chocolade'})<-[:PRODUCT]-(:Order)<-[:SOLD]-(employee),
      (employee)-[:SOLD]->(o2)-[:PRODUCT]->(other:Product)
RETURN employee.employeeID, other.productName, count(distinct o2) as count
ORDER BY count DESC
LIMIT 5;

:PRODUCT-(:Order)代表的是:[]代表着关系名称;()代表着图名称;

第一条逻辑:(employee)-(:Order)-(choc:Product),定位到employee生产了叫Chocolade的product

第二条逻辑:(employee)-()-(other:Product),定位到的雇员生产了哪些其他Product(所有的)

查询二:How are Employees Organized? Who Reports to Whom?
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
MATCH path = (e:Employee)<-[:REPORTS_TO]-(sub)
RETURN e.employeeID AS manager, sub.employeeID AS employee;

一个简单的模式,寻找Employee关系中REPORTS_TO的Employee。此时e代表雇主,sub代表雇员。

请注意,5号员工有人向他报告,但他也向2号员工报告。

这里有一个逻辑是:雇员、雇主都在Employee库中,所以要以REPORTS_TO关系为切入点。

查询三:Which Employees Report to Each Other Indirectly?

比查询二更深入一些,间接的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
MATCH path = (e:Employee)<-[:REPORTS_TO*]-(sub)
WITH e, sub, [person in NODES(path) | person.employeeID][1..-1] AS path
RETURN e.employeeID AS manager, sub.employeeID AS employee, CASE WHEN LENGTH(path) = 0 THEN "Direct Report" ELSE path END AS via
ORDER BY LENGTH(path);

第一步跟查询二的逻辑一样,在同一个Employee库汇总,查找关系为:REPORTS_TO的employee.

第二步,with用法,with从句可以连接多个查询的结果,即将上一个查询的结果用作下一个查询的开始,

(哈哈哈… 后面有点不明白,查完资料再补充…)

查询四:How Many Orders were Made by Each Part of the Hierarchy?
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
MATCH (e:Employee)
OPTIONAL MATCH (e)<-[:REPORTS_TO*0..]-(sub)-[:SOLD]->(order)
RETURN e.employeeID, [x IN COLLECT(DISTINCT sub.employeeID) WHERE x <> e.employeeID] AS reports, COUNT(distinct order) AS totalOrders
ORDER BY totalOrders DESC;
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018年04月08日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Android属性动画完全解析(上),初识属性动画的基本用法
用户1158055
2018/01/05
1.8K0
Android属性动画完全解析(上),初识属性动画的基本用法
Android属性动画的高级技巧
在 Android 开发中,属性动画是非常常见的一种动画方式。它可以让我们实现各种复杂的动画效果,比如旋转、缩放、移动、渐变等。那么,Android 属性动画是如何实现的呢?本文将从原理的角度来介绍 Android 属性动画的实现方法。
Rouse
2023/08/31
4110
Android属性动画的高级技巧
Android 属性动画:这是一篇很详细的 属性动画 总结&攻略
实现动画效果在Android开发中非常常见,因此Android系统一开始就提供了两种实现动画的方式:
Carson.Ho
2019/02/22
4K0
Android 属性动画详解,属性动画基本用法
Hello,大家好,今天又来装逼了,装逼也上瘾啊,最近公司不是特别忙,我想这也就是我出来装逼的最好时机吧!额,,哈哈,进入正题。如有疑问欢迎留言,如有谬误欢迎批评指正。 在Tween动画的讨论中,我们提到在Android中动画可以分为三类:①帧动画②Tween(补间动画)③Property Animation(属性动画),在前面的文章中,分别对帧动画和Tween动画进行了非常详细的讨论,如果有兴趣可以去上面的链接去阅读。那么今天就来和大家一起讨论下Property Animation,相信通过本系列博客的讨
非著名程序员
2018/02/02
1.3K0
Android 属性动画详解,属性动画基本用法
工厂模式和策略模式区别
随着信息技术的迅猛发展,软件系统的规模和复杂度日益增加,这对软件的开发、维护和扩展提出了更高的要求。为了提高软件系统的可重用性、可维护性和可扩展性,设计模式应运而生,成为了软件开发领域的重要工具。其中,工厂模式和策略模式是两种广泛使用的设计模式,它们在提高软件质量方面发挥着重要作用。
小白的大数据之旅
2024/11/20
1470
工厂模式和策略模式区别
Carson带你学Android:这是一份全面&详细的属性动画学习攻略!
Android一开始提供了视图动画,即补间动画跟逐帧动画。但视图动画存在三个问题:
Carson.Ho
2022/03/24
3280
Carson带你学Android:这是一份全面&详细的属性动画学习攻略!
何时使用MongoDB而不是MySql
MySQL 和 MongoDB 是两个可用于存储和管理数据的数据库管理系统。MySQL 是一个关系数据库系统,以结构化表格格式存储数据。相比之下,MongoDB 以更灵活的格式将数据存储为 JSON 文档。两者都提供性能和可扩展性,但它们为不同的应用场景提供了更好的性能。
wayn
2023/08/09
1.2K0
何时使用MongoDB而不是MySql
Android属性动画完全解析(中),ValueAnimator和ObjectAnimator的高级用法
摘要总结:本文主要解析了属性动画的底层原理,包括逐帧动画、ValueAnimator、ObjectAnimator、Interpolator和ViewPropertyAnimator,并通过实例代码讲解了每个底层原理的应用和实现方式。同时,本文还介绍了如何通过编写自定义的TypeEvaluator来处理复杂的动画逻辑,以及通过ViewPropertyAnimator来控制视图的动画效果。通过本文的学习,读者可以掌握属性动画的底层原理和实现方法,并能够根据需求定制自己的动画系统。
用户1158055
2018/01/05
8840
Android属性动画完全解析(中),ValueAnimator和ObjectAnimator的高级用法
Android十八章:属性动画Android属性动画(第一话)
Android动画能给界面带来很炫的效果,如果我们要实现这些效果,在android3.0版本前实现动画主要有2种方式,帧动画和补间动画。
ppjun
2018/09/05
1.1K0
Carson带你学Android:这是一份全面 & 详细的补间动画学习指南
通过确定开始的视图样式 & 结束的视图样式、中间动画变化过程由系统补全来确定一个动画
Carson.Ho
2022/03/24
6920
Carson带你学Android:这是一份全面 & 详细的补间动画学习指南
Android开发笔记(九十六)集合动画与属性动画
补间动画有四大类:透明度动画AlphaAnimation、旋转动画RotateAnimation、缩放动画ScaleAnimation、平移动画TranslateAnimation,而集合动画AnimationSet便是用来将几个补间动画组装起来。即在同一时刻,让某视图呈现出多种动画效果,如一边缩放一边旋转。 下面是AnimationSet的常用方法: addAnimation : 添加动画。 setFillAfter : 设置是否维持结束画面。true表示动画结束后停留在结束画面,false表示动画结束后恢复到开始画面。 setRepeatMode : 设置重播模式。RESTART表示从头开始,REVERSE表示倒过来开始。 setDuration : 设置动画的持续时间。 setStartTime : 设置动画的开始时间。Animation.START_ON_FIRST_FRAME表示当前时间,其他值表示转换为整型数的时间。一般无需调用该方法,默认就是立即开始播放。 setInterpolator : 设置动画的插值器。
aqi00
2019/01/18
9740
Android:帧动画和补间动画看这篇就足够了!
为了使用户的交互更加流畅自然,动画也就成为了一个应用中必不可少的元素之一。在 Android 中常用的动画分类无外乎三种,最早的 帧动画 、补间动画,以及 3.0 之后加入的 属性动画,是它们组成了 Android 中各种炫酷亮眼的动画效果。
Android技术干货分享
2019/08/07
2K0
Android:帧动画和补间动画看这篇就足够了!
游戏开发设计模式之状态模式
状态模式(State Pattern)是一种行为设计模式,它允许对象在其内部状态改变时改变其行为,从而使对象看起来像改变了其类。这种模式的主要目的是将对象的某些功能封装到不同的状态对象中,使得对象的行为依赖于它的状态。
用户11315985
2024/10/16
2170
游戏开发设计模式之状态模式
Android动画基础详析 | 属性动画基础及ValueAnimator
在上篇博客Android动画基础详析 | 概述、逐帧动画、视图动画(附诸多实际运行效果动图)的基础上我们新建一个property包和一个PropertyActivity:
凌川江雪
2019/09/30
1.5K0
Android动画基础详析 | 属性动画基础及ValueAnimator
腾讯云轻量服务器和云服务器区别
腾讯云轻量服务器和云服务器是腾讯云提供的两种不同类型的计算资源,它们在多个方面存在显著的差异。以下是对这两种服务器的详细对比:
用户2182295
2024/10/20
2.8K0
一个项目用5款数据库?MySQL、PostgreSQL、ClickHouse、MongoDB区别,适用场景
关系型数据库的基本单位是表,表与表之间通过键关联,比如学生表和班级表,可以通过班级ID,把学生和班级关联起来。
寻求出路的程序媛
2024/10/09
1.3K0
一个项目用5款数据库?MySQL、PostgreSQL、ClickHouse、MongoDB区别,适用场景
Android 中的属性动画 --- 1(基本用法)
动画在提高用户体验里面起了巨大的作用,可以说是提高用用户体验的“主力军”。在 Android 3.0 之前,视图动画几乎承担了所有的动画效果,但是视图动画有一个很大的局限性:它改变的只是某个 View 的外观。但是响应事件位置并没有随着 View 的改变而改变。举个 case 来说,现在有一个按钮通过视图动画在 x 轴方向上向右移动了 200 px(像素) 的距离,按钮显示的位置虽然改变了,但是点击移动后的按钮并不能相应点击事件,只有点击这个按钮没有移动之前的位置才能响应这个按钮的点击事件。由于这个巨大的局限性,Google 在 Android 3.0 以上添加了一个新的动画框架:属性动画。下面来一起看一下属性动画的用法:
指点
2019/01/18
1.2K0
Android 中的属性动画 --- 1(基本用法)
四种数据库对比MySQL、PostgreSQL、ClickHouse、MongoDB——特点、性能、扩展性、安全性、适用场景
还记得什么是关系型数据库、非关系型数据库,以及两者区别吗?如果忘记可以到这里重新温习:一个项目用5款数据库?MySQL、PostgreSQL、ClickHouse、MongoDB区别,适用场景
寻求出路的程序媛
2024/10/09
1.4K0
四种数据库对比MySQL、PostgreSQL、ClickHouse、MongoDB——特点、性能、扩展性、安全性、适用场景
deepseek深度思考:OneCode低代码打个分
好的,用户让我给OneCode低代码打个分,我需要先全面了解这个平台的特点、优势、应用场景以及可能存在的不足。首先,我需要仔细分析提供的搜索结果,看看里面提到了哪些关键点。
onecode
2025/02/08
1250
deepseek深度思考:OneCode低代码打个分
android属性动画
1、概述 Android提供了几种动画类型:View Animation 、Drawable Animation 、Property Animation 。View Animation相当简单,不过只能支持简单的缩放、平移、旋转、透明度基本的动画,且有一定的局限性。比如:你希望View有一个颜色的切换动画;你希望可以使用3D旋转动画;你希望当动画停止时,View的位置就是当前的位置;这些View Animation都无法做到。这就是Property Animation产生的原因,本篇博客详细介绍Prope
xiangzhihong
2018/01/30
8990
android属性动画
推荐阅读
相关推荐
Android属性动画完全解析(上),初识属性动画的基本用法
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验