首页 文章 精选 留言 我的

精选列表

搜索[微信小程序音视频],共10000篇文章
优秀的个人博客,低调大师

马斯克 X 版微信 XChat 来了,采用 Rust 开发

马斯克旗下 X 平台打造的独立通讯应 XChat 正式上线 App Store开启预购,并定 4 月 17 日正式上线。 根据介绍,XChat 安装包大小为175.8 MB,支持 iOS 26 及以上系统。年龄评级为 16 岁以上,支持英文、中文等 45 种语言。 “在专为对话打造的私密专属空间,与X上的任何人畅聊。无广告,无追踪,全程端到端加密。” 马斯克此前曾披露,XChat 采用 Rust 语言开发,采用(Bitcoin style)加密,拥有全新的架构。具备加密、阅后即焚消息和发送任何类型文件的功能,以及音频/视频通话功能。且应用内部已深度集成 xAI 旗下的 Grok AI,可在对话界面中直接调用 Grok 助手。

优秀的个人博客,低调大师

IYqueCode V2.0 已经发布,企业微信活码神器

源雀SCRM AI开源版|V2.0 智能化能力重磅升级! 全新上线:AI智能营销助手+AI智能导航 • 全案策划与策略生成:基于 LangChain4j 接入的大模型能力,输入活动目标(如新品上市、节日大促),AI 自动生成包含活动主题、目标客群、优惠机制、执行排期的完整营销方案,告别经验主义。 • 场景感知与功能推荐:基于 LangChain4j 的自然语言理解能力,用户只需描述当前业务场景(如“我想搞一场拉新活动”),系统即可自动推荐并跳转至【员工活码】、【获客外链】等相关功能模块。 架构升级:基于 LangChain4j 的多模型支持重构 • 统一接口,多模兼容:全面重构 AI 底层架构,基于 LangChain4j 框架,实现对 OpenAI、智谱AI、通义千问、文心一言 等 20+ 主流 LLM 厂商的统一封装。 • ⚙️ 配置驱动,灵活切换:支持多种底层大模型配置,无需改动业务代码,轻松实现模型迁移或 A/B 测试,满足不同场景下的成本与效果需求。 • ️ 稳定可靠,持续进化:利用 LangChain4j 的标准化特性,提升了 AI 功能的稳定性与可维护性,为后续接入更多 AI 能力奠定坚实基础。 感谢您一直以来的支持与信任! 本次 V2.0 大版本更新,标志着源雀SCRM AI开源版正式迈入“多模型驱动、全流程智能”的新阶段。我们将继续坚持 100% 开源的策略,拥抱 LangChain4j 等前沿技术,助力企业构建更智能的私域增长引擎。 • AI 智能营销助手 助您轻松策划,高效获客; • AI 智能导航 让您操作无忧,所想即所得; • 多模型架构 赋予您极致的灵活性与选择权。 【源雀 SCRM AI开源版】 团队 如有任何疑问、建议,或希望参与开源贡献,欢迎随时通过我们的 Gitee/GitCode 社区或仓库联系我们! 祝您工作顺利,客户运营事半功倍! 源雀SCRM AI开源版 团队 2026年3月6日 详情查看:https://gitee.com/iyque/iYqueCode/releases/V2.0

优秀的个人博客,低调大师

Android仿微信图片详情页面,可下拉关闭页面

话不多说,直接上效果图 imagereview.gif ImageReview 在这个库里面用到了第三方的缩放图片查看库 1、要实现效果图的方案,需要操作重写ViewPager的事件处理。 2、下滑透明的方案可以使用设置背景来实现 下拉缩放的效果需要重写onInterceptTouchEvent和onTouchEvent, 在onInterceptTouchEvent中不拦截down事件,并且在move事件中判断是否满足下滑缩放的条件; 在onTouchEvent中实现具体的缩放以及透明度变化的效果; 同时在ViewPager的滑动要与下滑缩放区分开,因此需要监听OnPageChangeListener,并在onTouchEvent判断是否ViewPager在滑动中 public class DragViewPager extends ViewPager implements View.OnClickListener { public static final int STATUS_NORMAL = 0;//正常浏览状态 public static final int STATUS_MOVING = 1;//滑动状态 public static final int STATUS_RESETTING = 2;//返回中状态 public static final String TAG = "DragViewPager"; public static final float MIN_SCALE_SIZE = 0.3f;//最小缩放比例 public static final int BACK_DURATION = 300;//ms public static final int DRAG_GAP_PX = 50; private int currentStatus = STATUS_NORMAL; private int currentPageStatus; private float mDownX; private float mDownY; private float screenHeight; /** * 要缩放的View */ private View currentShowView; /** * 滑动速度检测类 */ private VelocityTracker mVelocityTracker; private IAnimClose iAnimClose; public void setIAnimClose(IAnimClose iAnimClose) { this.iAnimClose = iAnimClose; } public DragViewPager(Context context) { super(context); init(context); } public DragViewPager(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public void init(Context context) { screenHeight = ScreenUtils.getScreenHeight(context); setBackgroundColor(Color.BLACK); addOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { } @Override public void onPageScrollStateChanged(int state) { currentPageStatus = state; } }); } public void setCurrentShowView(View currentShowView) { this.currentShowView = currentShowView; if (this.currentShowView != null) { this.currentShowView.setOnClickListener(this); } } //配合SubsamplingScaleImageView使用,根据需要拦截ACTION_MOVE @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (getAdapter() instanceof ImagePagerAdapter) { ImagePagerAdapter adapter = ((ImagePagerAdapter) getAdapter()); SubsamplingScaleImageView mImage = (SubsamplingScaleImageView) adapter.getItem(getCurrentItem()).getView().findViewById(R.id.image); switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: Log.e("jc","onInterceptTouchEvent:ACTION_DOWN"); mDownX = ev.getRawX(); mDownY = ev.getRawY(); break; case MotionEvent.ACTION_MOVE: Log.e("jc","onInterceptTouchEvent:ACTION_MOVE"); if (mImage.getCenter() != null && mImage.getCenter().y <= mImage.getHeight() / mImage.getScale() / 2) { Log.e("jc","onInterceptTouchEvent:ACTION_MOVE"); int deltaX = Math.abs((int) (ev.getRawX() - mDownX)); int deltaY = (int) (ev.getRawY() - mDownY); if (deltaY > DRAG_GAP_PX && deltaX <= DRAG_GAP_PX) {//往下移动超过临界,左右移动不超过临界时,拦截滑动事件 return true; } } break; case MotionEvent.ACTION_UP: Log.e("jc","onInterceptTouchEvent:ACTION_UP"); break; } } return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent ev) { if (currentStatus == STATUS_RESETTING) return false; switch (ev.getActionMasked()) { case MotionEvent.ACTION_DOWN: mDownX = ev.getRawX(); mDownY = ev.getRawY(); addIntoVelocity(ev); break; case MotionEvent.ACTION_MOVE: addIntoVelocity(ev); int deltaY = (int) (ev.getRawY() - mDownY); //手指往上滑动 if (deltaY <= DRAG_GAP_PX && currentStatus != STATUS_MOVING) return super.onTouchEvent(ev); //viewpager不在切换中,并且手指往下滑动,开始缩放 if (currentPageStatus != SCROLL_STATE_DRAGGING && (deltaY > DRAG_GAP_PX || currentStatus == STATUS_MOVING)) { moveView(ev.getRawX(), ev.getRawY()); return true; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: if (currentStatus != STATUS_MOVING) return super.onTouchEvent(ev); final float mUpX = ev.getRawX(); final float mUpY = ev.getRawY(); float vY = computeYVelocity();//松开时必须释放VelocityTracker资源 if (vY >= 1200 || Math.abs(mUpY - mDownY) > screenHeight / 4) { //下滑速度快,或者下滑距离超过屏幕高度的一半,就关闭 if (iAnimClose != null) { iAnimClose.onPictureRelease(currentShowView); } } else { resetReviewState(mUpX, mUpY); } break; } return super.onTouchEvent(ev); } //返回浏览状态 private void resetReviewState(final float mUpX, final float mUpY) { currentStatus = STATUS_RESETTING; if (mUpY != mDownY) { ValueAnimator valueAnimator = ValueAnimator.ofFloat(mUpY, mDownY); valueAnimator.setDuration(BACK_DURATION); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float mY = (float) animation.getAnimatedValue(); float percent = (mY - mDownY) / (mUpY - mDownY); float mX = percent * (mUpX - mDownX) + mDownX; moveView(mX, mY); if (mY == mDownY) { mDownY = 0; mDownX = 0; currentStatus = STATUS_NORMAL; } } }); valueAnimator.start(); } else if (mUpX != mDownX) { ValueAnimator valueAnimator = ValueAnimator.ofFloat(mUpX, mDownX); valueAnimator.setDuration(BACK_DURATION); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float mX = (float) animation.getAnimatedValue(); float percent = (mX - mDownX) / (mUpX - mDownX); float mY = percent * (mUpY - mDownY) + mDownY; moveView(mX, mY); if (mX == mDownX) { mDownY = 0; mDownX = 0; currentStatus = STATUS_NORMAL; } } }); valueAnimator.start(); } else if (iAnimClose != null) iAnimClose.onPictureClick(); } //移动View private void moveView(float movingX, float movingY) { if (currentShowView == null) return; currentStatus = STATUS_MOVING; float deltaX = movingX - mDownX; float deltaY = movingY - mDownY; float scale = 1f; float alphaPercent = 1f; if (deltaY > 0) { scale = 1 - Math.abs(deltaY) / screenHeight; alphaPercent = 1 - Math.abs(deltaY) / (screenHeight / 2); } ViewHelper.setTranslationX(currentShowView, deltaX); ViewHelper.setTranslationY(currentShowView, deltaY); scaleView(scale); setBackgroundColor(getBlackAlpha(alphaPercent)); } //缩放View private void scaleView(float scale) { scale = Math.min(Math.max(scale, MIN_SCALE_SIZE), 1); ViewHelper.setScaleX(currentShowView, scale); ViewHelper.setScaleY(currentShowView, scale); } private int getBlackAlpha(float percent) { percent = Math.min(1, Math.max(0, percent)); int intAlpha = (int) (percent * 255); return Color.argb(intAlpha,0,0,0); } private void addIntoVelocity(MotionEvent event) { if (mVelocityTracker == null) mVelocityTracker = VelocityTracker.obtain(); mVelocityTracker.addMovement(event); } private float computeYVelocity() { float result = 0; if (mVelocityTracker != null) { mVelocityTracker.computeCurrentVelocity(1000); result = mVelocityTracker.getYVelocity(); releaseVelocity(); } return result; } private void releaseVelocity() { if (mVelocityTracker != null) { mVelocityTracker.clear(); mVelocityTracker.recycle(); mVelocityTracker = null; } } @Override public void onClick(View v) { if (iAnimClose != null) { iAnimClose.onPictureClick(); } } public interface IAnimClose { void onPictureClick(); void onPictureRelease(View view); } } 需要进行缩放的View我这里在Adapter中添加回调设置,并且adapter可以实现更新的效果 public class ImagePagerAdapter extends FragmentStatePagerAdapter { private DragViewPager mPager; private ArrayList<Fragment> mFragmentList; public ImagePagerAdapter(FragmentManager fm, List<String> datas,DragViewPager pager) { super(fm); mPager=pager; mPager.setAdapter(this); updateData(datas); } public void updateData(List<String> dataList) { ArrayList<Fragment> fragments = new ArrayList<>(); for (int i = 0, size = dataList.size(); i < size; i++) { final ImageDetailFragment fragment = ImageDetailFragment.newInstance(dataList.get(i)); fragment.setOnImageListener(new ImageDetailFragment.OnImageListener() { @Override public void onInit() { View view = fragment.getView(); mPager.setCurrentShowView(view); } }); fragments.add(fragment); } setViewList(fragments); } private void setViewList(ArrayList<Fragment> fragmentList) { if (mFragmentList != null) { mFragmentList.clear(); } mFragmentList = fragmentList; notifyDataSetChanged(); } @Override public int getCount() { return mFragmentList==null?0:mFragmentList.size(); } public int getItemPosition(Object object) { return POSITION_NONE; } @Override public Fragment getItem(int position) { return mFragmentList.get(position); } } 要实现透明度变化的效果还需要对activity设置theme <style name="translucent" parent="AppTheme"> <item name="windowActionBar">false</item> <item name="windowNoTitle">true</item> <item name="android:windowIsTranslucent">true</item> <item name="android:windowBackground">@android:color/transparent</item> </style> <activity android:name=".ui.ImagePagerActivity" android:theme="@style/translucent"/> 在需要使用的页面只需要调用即可 ImagePagerActivity.startImagePage(MainActivity.this, urls,pos,recyclerView.getLayoutManager().findViewByPosition(pos)); 在整个demo中采用的转场动画,需要设置共享元素,因此在需要使用的页面需要设置如下: 首先设置转场动画的共享元素,因为跳转和返回时都会调用onMapSharedElements,需要判断bundle是否为空,bundle会在返回的时候在onActivityReenter获取到 //设置转场动画的共享元素,因为跳转和返回时都会调用onMapSharedElements,需要判断bundle是否为空 setExitSharedElementCallback(new SharedElementCallback() { @Override public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) { if (bundle!=null){ int index = bundle.getInt(ImagePagerActivity.STATE_POSITION,0); sharedElements.clear(); sharedElements.put("img", recyclerView.getLayoutManager().findViewByPosition(index)); bundle=null; } } }); 其次在返回的时候获取数据bundle @Override public void onActivityReenter(int resultCode, Intent data) { super.onActivityReenter(resultCode, data); bundle = data.getExtras(); int currentPosition = bundle.getInt(ImagePagerActivity.STATE_POSITION,0); //做相应的滚动 recyclerView.scrollToPosition(currentPosition); //暂时延迟 Transition 的使用,直到我们确定了共享元素的确切大小和位置才使用 //postponeEnterTransition后不要忘记调用startPostponedEnterTransition ActivityCompat.postponeEnterTransition(this); recyclerView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { recyclerView.getViewTreeObserver().removeOnPreDrawListener(this); // TODO: figure out why it is necessary to request layout here in order to get a smooth transition. recyclerView.requestLayout(); //共享元素准备好后调用startPostponedEnterTransition来恢复过渡效果 ActivityCompat.startPostponedEnterTransition(MainActivity.this); return true; } }); } 完整的调用页面的代码如下: public class MainActivity extends AppCompatActivity { private RecyclerView recyclerView; private MainAdapter mainAdapter; //图片集合 private ArrayList<String> urls; //存放返回时当前页码 private Bundle bundle; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); urls=new ArrayList<>(); //为了显示效果,重复添加了三次 urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1524477979306&di=3eb07e9302606048abe13d7b6a2bc601&imgtype=0&src=http%3A%2F%2Fimg4.duitang.com%2Fuploads%2Fitem%2F201406%2F12%2F20140612211118_YYXAC.jpeg"); urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1524133463580&di=1315bc4db30999f00b89ef79c3bb06e5&imgtype=0&src=http%3A%2F%2Fpic36.photophoto.cn%2F20150710%2F0005018721870517_b.jpg"); urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1524133463575&di=6221f21bcb761675c5d161ebc53d5948&imgtype=0&src=http%3A%2F%2Fimg5.duitang.com%2Fuploads%2Fitem%2F201410%2F03%2F20141003112442_AkkuH.thumb.700_0.jpeg"); urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1524477979306&di=3eb07e9302606048abe13d7b6a2bc601&imgtype=0&src=http%3A%2F%2Fimg4.duitang.com%2Fuploads%2Fitem%2F201406%2F12%2F20140612211118_YYXAC.jpeg"); urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1524133463580&di=1315bc4db30999f00b89ef79c3bb06e5&imgtype=0&src=http%3A%2F%2Fpic36.photophoto.cn%2F20150710%2F0005018721870517_b.jpg"); urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1524133463575&di=6221f21bcb761675c5d161ebc53d5948&imgtype=0&src=http%3A%2F%2Fimg5.duitang.com%2Fuploads%2Fitem%2F201410%2F03%2F20141003112442_AkkuH.thumb.700_0.jpeg"); urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1524477979306&di=3eb07e9302606048abe13d7b6a2bc601&imgtype=0&src=http%3A%2F%2Fimg4.duitang.com%2Fuploads%2Fitem%2F201406%2F12%2F20140612211118_YYXAC.jpeg"); urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1524133463580&di=1315bc4db30999f00b89ef79c3bb06e5&imgtype=0&src=http%3A%2F%2Fpic36.photophoto.cn%2F20150710%2F0005018721870517_b.jpg"); urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1524133463575&di=6221f21bcb761675c5d161ebc53d5948&imgtype=0&src=http%3A%2F%2Fimg5.duitang.com%2Fuploads%2Fitem%2F201410%2F03%2F20141003112442_AkkuH.thumb.700_0.jpeg"); initView(); } private void initView() { recyclerView = (RecyclerView) findViewById(R.id.recycler); recyclerView.setLayoutManager(new GridLayoutManager(this, 2)); mainAdapter = new MainAdapter(urls); mainAdapter.setOnItemClickListener(new MainAdapter.OnItemClickListener() { @Override public void onItemClick(int pos) { ImagePagerActivity.startImagePage(MainActivity.this, urls,pos,recyclerView.getLayoutManager().findViewByPosition(pos)); } }); recyclerView.setAdapter(mainAdapter); //设置转场动画的共享元素,因为跳转和返回都会调用,需要判断bundle是否为空 setExitSharedElementCallback(new SharedElementCallback() { @Override public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) { if (bundle!=null){ int index = bundle.getInt(ImagePagerActivity.STATE_POSITION,0); sharedElements.clear(); sharedElements.put("img", recyclerView.getLayoutManager().findViewByPosition(index)); bundle=null; } } }); } //返回的时候获取数据 @Override public void onActivityReenter(int resultCode, Intent data) { super.onActivityReenter(resultCode, data); bundle = data.getExtras(); int currentPosition = bundle.getInt(ImagePagerActivity.STATE_POSITION,0); //做相应的滚动 recyclerView.scrollToPosition(currentPosition); //暂时延迟 Transition 的使用,直到我们确定了共享元素的确切大小和位置才使用 //postponeEnterTransition后不要忘记调用startPostponedEnterTransition ActivityCompat.postponeEnterTransition(this); recyclerView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { recyclerView.getViewTreeObserver().removeOnPreDrawListener(this); // TODO: figure out why it is necessary to request layout here in order to get a smooth transition. recyclerView.requestLayout(); //共享元素准备好后调用startPostponedEnterTransition来恢复过渡效果 ActivityCompat.startPostponedEnterTransition(MainActivity.this); return true; } }); } } 需要查看完整代码点击这里,喜欢的请给个star,谢谢 作者:JC_Hou 链接:https://www.jianshu.com/p/3c6384973db6 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册