add some pagetransformers

This commit is contained in:
侯歌 2021-09-27 15:14:59 +08:00
parent e065767671
commit 23b76ea693
8 changed files with 403 additions and 88 deletions

View File

@ -27,12 +27,12 @@ public:
int main(int argc,const char*argv[]){
App app(argc,argv);
Window*w=new Window(100,100,800,600);
Window*w=new Window(0,0,1280,720);
MyAdapter*adapter=new MyAdapter();
w->setBackgroundColor(0xFF111111);
ListView*lv=(ListView*)&w->addView(new ListView(320,480));
lv->setPos(10,10);
lv->setPos(150,100);
lv->setId(1000);
for(int i=0;i<56;i++){
adapter->add("");
@ -43,18 +43,18 @@ int main(int argc,const char*argv[]){
lv->setOverScrollMode(View::OVER_SCROLL_ALWAYS);
lv->setSmoothScrollbarEnabled(true);
lv->setSelector(new ColorDrawable(0x8800FF00));
//lv->setSelection(2);
lv->setSelection(2);
lv->setDivider(new ColorDrawable(0x80224422));
lv->setDividerHeight(1);
lv->setRotation(30);
//lv->setRotation(30);
TextView*tv=new TextView("HelloWorld",200,40);
w->addView(tv).setPos(600,400);
tv->setBackgroundColor(0xFF00FF00);
float rotation=.0f;
Runnable r([&](){
lv->setRotation(rotation); lv->invalidate();
tv->setRotation(rotation); tv->invalidate();
lv->setRotation(rotation);
tv->setRotation(rotation);
rotation+=5;
w->postDelayed(r,80);
});

View File

@ -1,48 +1,73 @@
#include<windows.h>
#include<cdlog.h>
#include <windows.h>
#include <cdlog.h>
#include <getopt.h>
class TestView:public View{
private:
std::string mText;
public:
TestView(int w,int h):View(w,h){
TestView(const std::string&txt,int w,int h):View(w,h){
mText=txt;
}
void onDraw(Canvas&canvas)override{
void onDraw(Canvas&canvas)override{
canvas.set_color(SystemClock::uptimeMillis());
canvas.rectangle(0,0,getWidth(),getHeight());
canvas.fill_preserve();
canvas.fill();
canvas.set_color(0xFFFFFFFF);
canvas.arc(getWidth()/2,getHeight()/2,getWidth()/2,.0f,M_PI/3.f);
canvas.stroke();
canvas.set_color(0,0,1);
#if 0
Layout ll(48,mWidth);
ll.setText("Test");
#if 1
Layout ll(28,getWidth());
ll.setText(mText);
ll.draw(canvas);
#else
canvas.set_font_size(48);
canvas.move_to(0,50);
canvas.show_text("Test");
#else
canvas.set_font_size(28);
canvas.move_to(0,getHeight()/4);
canvas.show_text(mText);
#endif
}
};
class MyGroup:public ViewGroup{
public:
MyGroup(int w,int h):ViewGroup(w,h){}
void onDraw(Canvas&canvas)override{
canvas.set_color(SystemClock::uptimeMillis()+time(nullptr));
canvas.rectangle(0,0,getWidth(),getHeight());
canvas.fill();
canvas.move_to(40,200);
canvas.set_font_size(68);
canvas.set_source_rgb(1,1,1);
canvas.show_text("ViewGroup");
ViewGroup::onDraw(canvas);
}
};
static struct option appargs[]={
{"type" ,1,0,0},
{0,0,0,0}
};
int main(int argc,const char*argv[]){
App app(argc,argv);
Window*w=new Window(100,100,800,600);
ViewGroup*grp=new ViewGroup(400,400);
grp->setId(10);//.setRotation(30);
w->addView(grp).setPos(100,100).setBackgroundColor(0xFFFF0000);
App app(argc,argv,appargs);
Window*w=new Window(0,0,800,600);
ViewGroup*grp=new MyGroup(400,400);
//grp->setId(10).setRotation(45);
w->addView(grp).setBackgroundColor(0xFFFF0000);
w->setBackgroundColor(0xFF111111);
TestView*tv=new TestView(100,100);
View*tv=nullptr;
switch(app.getArgAsInt("type",1)){
default: //pass throught
case 0: tv=new TextView("TestButton",160,60); break;
case 1: tv=new TestView("TestButton",160,60); break;
case 2: tv=new ImageView(160,160);
((ImageView*)tv)->setImageResource("/home/houzh/images/1.png");
break;
}
tv->setId(100);
grp->addView(tv).setPos(50,200);
float rotation=.0f;
grp->addView(tv).setPos(50,50).setBackgroundColor(0xFF444444);
float rotation=15.f;
Runnable r([&](){
//grp->setRotation(rotation);
grp->setRotation(rotation);
tv->setRotation(rotation);
rotation+=5;
w->postDelayed(r,100);
w->postDelayed(r,300);
});
w->postDelayed(r,1000);
return app.exec();

View File

@ -1,5 +1,6 @@
#include <windows.h>
#include <widget/simplemonthview.h>
#include <widget/pagetransformers.h>
static int mPageCount=5;
class MyPageAdapter:public PagerAdapter{
public:
@ -56,18 +57,8 @@ int main(int argc,const char*argv[]){
gpAdapter->notifyDataSetChanged();
pager->setCurrentItem(0);
w->requestLayout();
const float MIN_SCALE=0.5f;
if(argc>1)
pager->setPageTransformer(true,[&](View&view,float position){
float scaleFactor=1.f;
float translationX=(float)view.getWidth()*.8f+20.f*std::abs(position);
view.setTranslationX(translationX);
scaleFactor=std::max(.1f,1.f-std::max(.1f,std::abs(position)*0.5f));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
LOGD("view at %f size=%dx%d scale=%f transx=%f",position,view.getWidth(),view.getHeight(),scaleFactor,translationX);
});
pager->setPageTransformer(true,new RotateUpTransformer());
app.exec();
}

View File

@ -1,5 +1,6 @@
#include <windows.h>
#include <dirent.h>
#include <widget/pagetransformers.h>
class MyPageAdapter:public PagerAdapter{
std::vector<std::string>urls;
@ -17,8 +18,11 @@ public:
int getCount()override{return urls.size();}
bool isViewFromObject(View* view, void*object)override{ return view==object;}
void* instantiateItem(ViewGroup* container, int position)override {
ImageView*iv=new ImageView(100,100);
container->addView(iv,new ViewPager::LayoutParams());
ImageView*iv=new ImageView(200,200);
ViewPager::LayoutParams*lp=new ViewPager::LayoutParams();
//lp->isDecor=true;
lp->gravity=Gravity::LEFT;
container->addView(iv,lp).setId(position);
iv->setScaleType(FIT_XY);
RefPtr<Cairo::ImageSurface>img;
if(imgs.find(position)==imgs.end()){
@ -60,43 +64,8 @@ int main(int argc,const char*argv[]){
};
pager->addOnPageChangeListener(listener);
pager->setOverScrollMode(View::OVER_SCROLL_ALWAYS);
constexpr float CENTER_PAGE_SCALE=.8f;
constexpr int pagerWidth=800;
const float MIN_SCALE = 0.5f;
const float MIN_ALPHA = 0.5f;
if(argc>1)
pager->setPageTransformer(true,[&](View&view,float position){
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();
if (position < -1){ // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 1){ //a页滑动至b页 a页从 0.0 -1 b页从1 ~ 0.0
// [-1,1]
// Modify the default slide transition to shrink the page as well
float scaleFactor = std::max(MIN_SCALE, 1 - std::abs(position));
float vertMargin = pageHeight * (1 - scaleFactor) / 2;
float horzMargin = pageWidth * (1 - scaleFactor) / 2;
if (position < 0){
view.setTranslationX(horzMargin - vertMargin / 2);
} else{
view.setTranslationX(-horzMargin + vertMargin / 2);
}
// Scale the page down (between MIN_SCALE and 1)
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
// Fade the page relative to its size.
view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE)
/ (1 - MIN_SCALE) * (1 - MIN_ALPHA));
} else{ // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
});
pager->setPageTransformer(true,new ParallaxTransformer());
layout->addView(pager);
tab->setupWithViewPager(pager);
w->addView(layout);

View File

@ -0,0 +1,214 @@
#include <widget/pagetransformers.h>
namespace cdroid{
void ABaseTransformer::transformPage(View& page, float position) {
onPreTransform(page, position);
onTransform(page, position);
onPostTransform(page, position);
}
bool ABaseTransformer::hideOffscreenPages(){
return true;
}
bool ABaseTransformer::isPagingEnabled(){
return false;
}
void ABaseTransformer::onPreTransform(View& page, float position) {
const float width = page.getWidth();
page.setRotationX(0);
page.setRotationY(0);
page.setRotation(0);
page.setScaleX(1);
page.setScaleY(1);
page.setPivotX(0);
page.setPivotY(0);
page.setTranslationY(0);
page.setTranslationX(isPagingEnabled() ? .0f : -width * position);
if (hideOffscreenPages()) {
page.setAlpha(position <= -1.f || position >= 1.f ? .0f : 1.f);
//page.setEnabled(false);
} else {
//page.setEnabled(true);
page.setAlpha(1.f);
}
}
void ABaseTransformer::onPostTransform(View& page, float position){
}
void AccordionTransformer::onTransform(View& view, float position) {
view.setPivotX(position < 0 ? 0 : view.getWidth());
view.setScaleX(position < 0 ? 1.f + position : 1.f - position);
}
void CubeInTransformer::onTransform(View& view, float position) {
LOGD("cubein %d,%d",view.getWidth(),view.getHeight());
// Rotate the fragment on the left or right edge
view.setPivotX(position > 0 ? 0 : view.getWidth());
view.setPivotY(0);
view.setRotationY(-90.f * position);
}
bool CubeInTransformer::isPagingEnabled() {
return true;
}
void CubeOutTransformer::onTransform(View& view, float position) {
view.setPivotX(position < .0f ? view.getWidth() : .0f);
view.setPivotY(view.getHeight() * 0.5f);
view.setRotationY(90.f * position);
}
bool CubeOutTransformer::isPagingEnabled() {
return true;
}
void DefaultTransformer::onTransform(View& view, float position){}
bool DefaultTransformer::isPagingEnabled(){return true;}
void FlipHorizontalTransformer::onTransform(View& view, float position){
const float rotation = 180.f * position;
view.setAlpha(rotation > 90.f || rotation < -90.f ? 0 : 1);
view.setPivotX(view.getWidth() * 0.5f);
view.setPivotY(view.getHeight() * 0.5f);
view.setRotationY(rotation);
}
void FlipHorizontalTransformer::onPostTransform(View& page, float position){
ABaseTransformer::onPostTransform(page, position);
//resolve problem: new page can't handle click event!
page.setVisibility((position > -0.5f && position < 0.5f)?View::VISIBLE:View::INVISIBLE);
}
void FlipVerticalTransformer::onTransform(View& view, float position) {
const float rotation = -180.f * position;
view.setAlpha(rotation > 90.f || rotation < -90.f ? .0f : 1.f);
view.setPivotX(view.getWidth() * 0.5f);
view.setPivotY(view.getHeight() * 0.5f);
view.setRotationX(rotation);
}
void FlipVerticalTransformer::onPostTransform(View& page, float position) {
ABaseTransformer::onPostTransform(page, position);
page.setVisibility((position > -0.5f && position < 0.5f)?View::VISIBLE:View::INVISIBLE);
}
void ParallaxTransformer::transformPage(View& page, float position){
const int width = page.getWidth();
if (position < -1) {
page.setScrollX((int) (width * 0.75 * -1));
} else if (position <= 1) {
if (position < 0) {
page.setScrollX((int) (width * 0.75 * position));
} else {
page.setScrollX((int) (width * 0.75 * position));
}
} else {
page.setScrollX((int) (width * 0.75));
}
}
void RotateDownTransformer::onTransform(View& view, float position) {
const float width = view.getWidth();
const float height = view.getHeight();
const float rotation = ROT_MOD * position * -1.25f;
view.setPivotX(width * 0.5f);
view.setPivotY(height);
view.setRotation(rotation);
}
bool RotateDownTransformer::isPagingEnabled() {
return true;
}
void RotateUpTransformer::onTransform(View& view, float position) {
const float width = view.getWidth();
const float rotation = ROT_MOD * position;
view.setPivotX(width * 0.5f);
view.setPivotY(.0f);
view.setTranslationX(.0f);
view.setRotation(rotation);
}
bool RotateUpTransformer::isPagingEnabled() {
return true;
}
void ScaleInOutTransformer::onTransform(View& view, float position){
view.setPivotX(position < 0 ? 0 : view.getWidth());
view.setPivotY(view.getHeight() / 2.f);
float scale = position < 0 ? 1.f + position : 1.f - position;
view.setScaleX(scale);
view.setScaleY(scale);
}
void StackTransformer::onTransform(View& view, float position) {
view.setTranslationX(position < 0 ? .0f : -view.getWidth() * position);
}
void ZoomInTransformer::onTransform(View& view, float position) {
const float scale = position < 0 ? position + 1.f : std::abs(1.f - position);
view.setScaleX(scale);
view.setScaleY(scale);
view.setPivotX(view.getWidth() * 0.5f);
view.setPivotY(view.getHeight()* 0.5f);
view.setAlpha(position < -1.f || position > 1.f ? .0f : 1.f - (scale - 1.f));
}
void ZoomOutTransformer::onTransform(View& view, float position) {
const float scale = position < 0 ? position + 1.f : std::abs(1.f - position);
view.setScaleX(scale);
view.setScaleY(scale);
view.setPivotX(view.getWidth() * 0.5f);
view.setPivotY(view.getHeight() * 0.5f);
view.setAlpha(position < -1.f || position > 1.f ? .0f : 1.f - (scale - 1.f));
}
ZoomOutSlideTransformer::ZoomOutSlideTransformer():ZoomOutSlideTransformer(.85f,.5f){
}
ZoomOutSlideTransformer::ZoomOutSlideTransformer(float minscale,float minalpha){
mMinScale=minscale;
mMinAlpha=minalpha;
}
void ZoomOutSlideTransformer::onTransform(View& view, float position) {
if (position >= -1 || position <= 1) {
// Modify the default slide transition to shrink the page as well
const float height = view.getHeight();
const float width = view.getWidth();
const float scaleFactor = std::max(mMinScale, 1.f - std::abs(position));
const float vertMargin = height * (1.f - scaleFactor) / 2.f;
const float horzMargin = width * (1.f - scaleFactor) / 2.f;
// Center vertically
view.setPivotY(0.5f * height);
view.setPivotX(0.5f * width);
if (position < 0) {
view.setTranslationX(horzMargin - vertMargin / 2.f);
} else {
view.setTranslationX(-horzMargin+ vertMargin / 2.f);
}
// Scale the page down (between MIN_SCALE and 1)
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
// Fade the page relative to its size.
view.setAlpha(mMinAlpha + (scaleFactor - mMinScale) / (1.f - mMinScale) * (1.f - mMinAlpha));
}
}
}//endof namespace

105
src/gui/widget/pagetransformers.h Executable file
View File

@ -0,0 +1,105 @@
#pragma once
#include <widget/viewpager.h>
namespace cdroid{
//refto: https://github.com/OCNYang/PageTransformerHelp
class ABaseTransformer:public ViewPager::PageTransformer{
protected:
virtual void onTransform(View&page,float position)=0;
virtual bool hideOffscreenPages();
virtual bool isPagingEnabled();
virtual void onPreTransform(View&page,float position);
virtual void onPostTransform(View&page,float position);
public:
void transformPage(View&page,float position)override;
};
class AccordionTransformer:public ABaseTransformer {
protected:
void onTransform(View& view, float position)override;
};
class CubeInTransformer:public ABaseTransformer{
protected:
void onTransform(View& view, float position)override;
bool isPagingEnabled()override;
};
class CubeOutTransformer:public ABaseTransformer{
protected:
void onTransform(View& view, float position)override;
bool isPagingEnabled()override;
};
class DefaultTransformer:ABaseTransformer{
protected:
void onTransform(View& view, float position)override;
bool isPagingEnabled()override;
};
class FlipHorizontalTransformer:public ABaseTransformer{
protected:
void onTransform(View& view, float position)override;
void onPostTransform(View&page,float position)override;
};
class FlipVerticalTransformer:public ABaseTransformer{
protected:
void onTransform(View& view, float position)override;
void onPostTransform(View&page,float position)override;
};
class ParallaxTransformer:public ViewPager::PageTransformer{
public:
void transformPage(View& page, float position)override;
};
class RotateDownTransformer:public ABaseTransformer{
private:static constexpr float ROT_MOD = -15.f;
protected:
void onTransform(View& view, float position)override;
bool isPagingEnabled()override;
};
class RotateUpTransformer:public ABaseTransformer{
private:static constexpr float ROT_MOD = -15.f;
protected:
void onTransform(View& view, float position)override;
bool isPagingEnabled()override;
};
class ScaleInOutTransformer:public ABaseTransformer{
protected:
void onTransform(View& view, float position)override;
};
class StackTransformer:public ABaseTransformer{
protected:
void onTransform(View& view, float position)override;
};
class ZoomInTransformer:public ABaseTransformer{
protected:
void onTransform(View& view, float position)override;
};
class ZoomOutTransformer:public ABaseTransformer{
protected:
void onTransform(View& view, float position)override;
};
class ZoomOutSlideTransformer:public ABaseTransformer{
private:
float mMinScale;
float mMinAlpha;
protected:
void onTransform(View& view, float position);
public:
ZoomOutSlideTransformer();
ZoomOutSlideTransformer(float minscale,float minalpha);
};
}//endof namespace

View File

@ -17,6 +17,13 @@ ViewPager::ViewPager(int w,int h):ViewGroup(w,h){
initViewPager();
}
ViewPager::~ViewPager(){
delete mLeftEdge;
delete mRightEdge;
delete mMarginDrawable;
delete mScroller;
}
ViewPager::ViewPager(Context* context,const AttributeSet& attrs):ViewGroup(context,attrs){
initViewPager();
}
@ -54,7 +61,7 @@ void ViewPager::initViewPager(){
mTempItem=new ItemInfo();
mFlingDistance = (int) (MIN_DISTANCE_FOR_FLING * density);
mCloseEnough = (int) (CLOSE_ENOUGH * density);
mCloseEnough = (int) (CLOSE_ENOUGH * density);
mDefaultGutterSize = (int) (DEFAULT_GUTTER_SIZE * density);
}
@ -270,7 +277,7 @@ void ViewPager::dispatchOnScrollStateChanged(int state) {
}
}
void ViewPager::setPageTransformer(bool reverseDrawingOrder, PageTransformer transformer) {
void ViewPager::setPageTransformer(bool reverseDrawingOrder, PageTransformer* transformer) {
const bool hasTransformer = transformer != nullptr;
const bool needsPopulate = hasTransformer != (mPageTransformer != nullptr);
mPageTransformer = transformer;
@ -1118,7 +1125,7 @@ void ViewPager::onPageScrolled(int position, float offset, int offsetPixels){
if (lp->isDecor) continue;
float transformPos = (float) (child->getLeft() - scrollX) / getClientWidth();
mPageTransformer(*child, transformPos);
mPageTransformer->transformPage(*child, transformPos);
}
}
mCalledSuper = true;

View File

@ -16,7 +16,10 @@ namespace cdroid{
class ViewPager:public ViewGroup{
public:
typedef std::function<void(View&v,float position)>PageTransformer;
class PageTransformer{
public:
virtual void transformPage(View& page, float position)=0;//typedef std::function<void(View&v,float position)>PageTransformer;
};
struct OnPageChangeListener{
CallbackBase<void,int,float,int>onPageScrolled;//void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
CallbackBase<void,int>onPageSelected;//void onPageSelected(int position);
@ -101,7 +104,7 @@ private:
bool mInLayout;
std::vector<OnPageChangeListener> mOnPageChangeListeners;
OnPageChangeListener mInternalPageChangeListener;
PageTransformer mPageTransformer;
PageTransformer* mPageTransformer;
bool mScrollingCacheEnabled;
@ -198,6 +201,7 @@ protected:
public:
ViewPager(int w,int h);
ViewPager(Context* context,const AttributeSet& attrs);
~ViewPager();
void setAdapter(PagerAdapter* adapter);
PagerAdapter* getAdapter();
void addOnAdapterChangeListener(OnAdapterChangeListener listener);
@ -210,7 +214,7 @@ public:
int getCurrentItem();
void setCurrentItem(int item);
void setCurrentItem(int item, bool smoothScroll);
void setPageTransformer(bool reverseDrawingOrder, PageTransformer transformer);
void setPageTransformer(bool reverseDrawingOrder, PageTransformer* transformer);
int getOffscreenPageLimit()const;
void setOffscreenPageLimit(int limit);
int getPageMargin()const;