├── nestedScrollView └── src │ ├── NestedParent.java │ ├── NestedScrollActivity.java │ └── activity_nested_scroll.xml ├── sectionRecyclerView └── src │ ├── SectionRecyclerActivity.java │ ├── activity_section_recycler.xml │ ├── item_section_list_item.xml │ └── item_section_list_title.xml └── watermark ├── WatermarkActivity.java └── WatermarkDecoration.java /nestedScrollView/src/NestedParent.java: -------------------------------------------------------------------------------- 1 | package eebochina.com.testtechniques.nestedScroll; 2 | 3 | import android.content.Context; 4 | import android.support.v4.view.NestedScrollingParent; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.util.AttributeSet; 7 | import android.view.View; 8 | import android.widget.ScrollView; 9 | 10 | /** 11 | * Created by User on 2017/1/17. 12 | */ 13 | public class NestedParent extends ScrollView implements NestedScrollingParent { 14 | 15 | //方便测试先固定。 16 | private int maxHeight = 464; 17 | private RecyclerView mRecyclerView; 18 | 19 | public NestedParent(Context context) { 20 | super(context); 21 | } 22 | 23 | public NestedParent(Context context, AttributeSet attrs) { 24 | super(context, attrs); 25 | } 26 | 27 | public NestedParent(Context context, AttributeSet attrs, int defStyleAttr) { 28 | super(context, attrs, defStyleAttr); 29 | } 30 | 31 | 32 | public void setMaxHeight(int maxHeight) { 33 | this.maxHeight = maxHeight; 34 | } 35 | 36 | @Override 37 | public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) { 38 | return super.onStartNestedScroll(child, target, nestedScrollAxes); 39 | } 40 | 41 | @Override 42 | public void onNestedScrollAccepted(View child, View target, int axes) { 43 | super.onNestedScrollAccepted(child, target, axes); 44 | } 45 | 46 | @Override 47 | public void onStopNestedScroll(View target) { 48 | super.onStopNestedScroll(target); 49 | } 50 | 51 | @Override 52 | public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { 53 | super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); 54 | } 55 | 56 | @Override 57 | public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) { 58 | return consumed; 59 | } 60 | 61 | //返回true代表父view消耗滑动速度,子View将不会滑动 62 | @Override 63 | public boolean onNestedPreFling(View target, float velocityX, float velocityY) { 64 | if (null == mRecyclerView) mRecyclerView = (RecyclerView) target; 65 | if (mRecyclerView.computeVerticalScrollOffset() != 0) { 66 | return false; 67 | } 68 | this.fling((int) velocityY); 69 | return true; 70 | } 71 | 72 | //对应子view 的dispatchNestedPreScroll方法, 最后一个数组代表消耗的滚动量,下标0代表x轴,下标1代表y轴 73 | @Override 74 | public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) { 75 | //判断是否滚动到最大值 76 | if ( dy >= 0 && this.getScrollY() < maxHeight) { 77 | if (null == mRecyclerView) mRecyclerView = (RecyclerView) target; 78 | //计算RecyclerView的偏移量, 等于0的时候说明recyclerView没有滑动,否则应该交给recyclerView自己处理 79 | if (mRecyclerView.computeVerticalScrollOffset() != 0) return; 80 | this.smoothScrollBy(dx, dy); 81 | consumed[1] = dy; //consumed[1]赋值为 dy ,代表父类已经消耗了改滚动。 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /nestedScrollView/src/NestedScrollActivity.java: -------------------------------------------------------------------------------- 1 | package eebochina.com.testtechniques.nestedScroll; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.support.v7.widget.LinearLayoutManager; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.util.Log; 8 | import android.view.LayoutInflater; 9 | import android.view.MotionEvent; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.widget.TextView; 13 | import android.widget.Toast; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | import eebochina.com.testtechniques.R; 19 | 20 | public class NestedScrollActivity extends AppCompatActivity { 21 | 22 | private RecyclerView mRecyclerView; 23 | private LayoutInflater mInflater; 24 | private List mContentDatas; 25 | 26 | @Override 27 | protected void onCreate(Bundle savedInstanceState) { 28 | super.onCreate(savedInstanceState); 29 | setContentView(R.layout.activity_nested_scroll); 30 | 31 | mRecyclerView = (RecyclerView) findViewById(R.id.nested_scroll_recycler); 32 | 33 | mInflater = LayoutInflater.from(this); 34 | mContentDatas = new ArrayList<>(); 35 | final LinearLayoutManager contentManager = new LinearLayoutManager(this); 36 | contentManager.setOrientation(LinearLayoutManager.VERTICAL); 37 | mRecyclerView.setLayoutManager(contentManager); 38 | for (int i = 0; i < 50; i++) { 39 | mContentDatas.add("str" + i); 40 | } 41 | mRecyclerView.setAdapter(new ContentAdapter()); 42 | } 43 | 44 | 45 | class ContentAdapter extends RecyclerView.Adapter { 46 | @Override 47 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 48 | return new ContentViewHolder(mInflater.inflate(R.layout.item_layout, parent, false)); 49 | } 50 | 51 | @Override 52 | public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { 53 | final ContentViewHolder viewHolder = (ContentViewHolder) holder; 54 | viewHolder.mTextView.setText(mContentDatas.get(position)); 55 | viewHolder.itemView.setOnClickListener(new View.OnClickListener() { 56 | @Override 57 | public void onClick(View view) { 58 | Toast.makeText(NestedScrollActivity.this, mContentDatas.get(position), Toast.LENGTH_SHORT).show(); 59 | } 60 | }); 61 | } 62 | 63 | @Override 64 | public int getItemCount() { 65 | return mContentDatas.size(); 66 | } 67 | } 68 | 69 | class ContentViewHolder extends RecyclerView.ViewHolder { 70 | private TextView mTextView; 71 | 72 | public ContentViewHolder(View itemView) { 73 | super(itemView); 74 | mTextView = (TextView) itemView.findViewById(R.id.item_layout_text); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /nestedScrollView/src/activity_nested_scroll.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 15 | 20 | 21 | 29 | 30 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /sectionRecyclerView/src/SectionRecyclerActivity.java: -------------------------------------------------------------------------------- 1 | package eebochina.com.testtechniques.pinnedsection; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.support.v7.widget.LinearLayoutManager; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.FrameLayout; 11 | import android.widget.TextView; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | import eebochina.com.testtechniques.R; 17 | 18 | public class SectionRecyclerActivity extends AppCompatActivity { 19 | 20 | public static final int TITLE_TYPE = 22; 21 | public static final int ITEM_TYPE = 33; 22 | 23 | private RecyclerView mRecyclerView; 24 | 25 | private TextView mTopTitle; 26 | 27 | private CalendarListAdapter mAdapter; 28 | private List mDatas; 29 | private LinearLayoutManager mLayoutManager; 30 | 31 | private LayoutInflater mInflater; 32 | private FrameLayout.LayoutParams mTopTitleLayoutParams; 33 | private int mMaxHeight; 34 | 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | setContentView(R.layout.activity_section_recycler); 39 | 40 | mRecyclerView = (RecyclerView) findViewById(R.id.section_list); 41 | mTopTitle = (TextView) findViewById(R.id.item_calendar_list_title_text); 42 | 43 | mDatas = new ArrayList<>(); 44 | mInflater = LayoutInflater.from(this); 45 | 46 | mLayoutManager = new LinearLayoutManager(this); 47 | mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); 48 | mRecyclerView.setLayoutManager(mLayoutManager); 49 | mAdapter = new CalendarListAdapter(); 50 | mRecyclerView.setAdapter(mAdapter); 51 | 52 | mTopTitleLayoutParams = (FrameLayout.LayoutParams) mTopTitle.getLayoutParams(); 53 | addFakeData(); 54 | 55 | mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { 56 | @Override 57 | public void onScrollStateChanged(RecyclerView recyclerView, int newState) { 58 | super.onScrollStateChanged(recyclerView, newState); 59 | } 60 | 61 | @Override 62 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 63 | super.onScrolled(recyclerView, dx, dy); 64 | int position = (mLayoutManager.findFirstVisibleItemPosition() < 0) ? 0 : mLayoutManager.findFirstVisibleItemPosition(); 65 | int totalSize = mLayoutManager.getItemCount(); 66 | if (mAdapter.getItemViewType(position) == TITLE_TYPE) { 67 | mTopTitle.setText(mDatas.get(position).content); 68 | } 69 | int nextPosition = position + 1; 70 | if (nextPosition < totalSize) { 71 | //获取下个章节标题的位置, 如果小于0说明后面没有章节标题。 如果下个章节标题位置还未显示出来,也不用做改变。 72 | int sectionPosition = findNextSection(nextPosition, totalSize); 73 | if (sectionPosition < 0 || sectionPosition > (position + mRecyclerView.getChildCount() - 1)) { 74 | refreshTopTitle(); 75 | return; 76 | } 77 | 78 | //获取下一个章节标题的top, 如果top 大于 展示label的高度, 无须做改动。 79 | int nextTopMargin = mLayoutManager.findViewByPosition(sectionPosition).getTop(); 80 | if (nextTopMargin < mMaxHeight) { 81 | mTopTitleLayoutParams.topMargin = -(mMaxHeight - nextTopMargin); 82 | mTopTitle.setLayoutParams(mTopTitleLayoutParams); 83 | //如果当前第一个显示的不是章节标题, 需要显示上一个章节标题 84 | if (mAdapter.getItemViewType(position) != TITLE_TYPE) { 85 | mTopTitle.setText(findPreSectionText(position)); 86 | } 87 | } else { 88 | refreshTopTitle(); 89 | } 90 | } 91 | } 92 | }); 93 | } 94 | 95 | private void refreshTopTitle() { 96 | if (mTopTitleLayoutParams.topMargin == 0) return; 97 | mTopTitleLayoutParams.topMargin = 0; 98 | mTopTitle.setLayoutParams(mTopTitleLayoutParams); 99 | } 100 | 101 | private int findNextSection(int position, int size) { 102 | for (; position < size; position++) { 103 | if (mAdapter.getItemViewType(position) == TITLE_TYPE) return position; 104 | } 105 | return -1; 106 | } 107 | 108 | private String findPreSectionText(int position) { 109 | for (; position > -1; position--) { 110 | if (mAdapter.getItemViewType(position) == TITLE_TYPE) return mDatas.get(position).content; 111 | } 112 | return ""; 113 | } 114 | 115 | 116 | private void addFakeData() { 117 | TestEntity testEntity; 118 | for (int i = 0, j = 6; i < 50; i++) { 119 | if (i % j == 0) { 120 | testEntity = new TestEntity("标题" + i, TITLE_TYPE); 121 | } else { 122 | testEntity = new TestEntity("内容" + i, ITEM_TYPE); 123 | } 124 | mDatas.add(testEntity); 125 | } 126 | } 127 | 128 | private boolean isInit = false; 129 | 130 | @Override 131 | public void onWindowFocusChanged(boolean hasFocus) { 132 | super.onWindowFocusChanged(hasFocus); 133 | //当activity可以获取焦点的时候,获取固定标题栏的高度 134 | if (hasFocus && !isInit) { 135 | isInit = true; 136 | mMaxHeight = mTopTitle.getHeight(); 137 | } 138 | } 139 | 140 | class CalendarListAdapter extends RecyclerView.Adapter { 141 | 142 | @Override 143 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 144 | switch (viewType) { 145 | case TITLE_TYPE: 146 | return new CalendarTitleViewHolder(mInflater.inflate(R.layout.item_section_list_title, parent, false)); 147 | case ITEM_TYPE: 148 | return new CalendarItemViewHolder(mInflater.inflate(R.layout.item_section_list_item, parent, false)); 149 | } 150 | return null; 151 | } 152 | 153 | @Override 154 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 155 | TestEntity testEntity = mDatas.get(position); 156 | switch (testEntity.type) { 157 | case TITLE_TYPE: 158 | CalendarTitleViewHolder titleViewHolder = (CalendarTitleViewHolder) holder; 159 | titleViewHolder.mTitle.setText(testEntity.content); 160 | break; 161 | case ITEM_TYPE: 162 | CalendarItemViewHolder itemViewHolder = (CalendarItemViewHolder) holder; 163 | itemViewHolder.mContent.setText(testEntity.content); 164 | break; 165 | } 166 | } 167 | 168 | @Override 169 | public int getItemCount() { 170 | return mDatas.size(); 171 | } 172 | 173 | @Override 174 | public int getItemViewType(int position) { 175 | return mDatas.get(position).type; 176 | } 177 | } 178 | 179 | 180 | class CalendarTitleViewHolder extends RecyclerView.ViewHolder { 181 | TextView mTitle; 182 | 183 | public CalendarTitleViewHolder(View itemView) { 184 | super(itemView); 185 | mTitle = (TextView) itemView.findViewById(R.id.item_calendar_list_title_text); 186 | } 187 | } 188 | 189 | class CalendarItemViewHolder extends RecyclerView.ViewHolder { 190 | 191 | TextView mLabel; 192 | TextView mContent; 193 | 194 | public CalendarItemViewHolder(View itemView) { 195 | super(itemView); 196 | mLabel = (TextView) itemView.findViewById(R.id.item_calendar_list_item_label); 197 | mContent = (TextView) itemView.findViewById(R.id.item_calendar_list_item_content); 198 | } 199 | } 200 | 201 | class TestEntity { 202 | String content; 203 | int type; 204 | 205 | 206 | public TestEntity(String content, int type) { 207 | this.content = content; 208 | this.type = type; 209 | } 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /sectionRecyclerView/src/activity_section_recycler.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /sectionRecyclerView/src/item_section_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 13 | 14 | 20 | 21 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /sectionRecyclerView/src/item_section_list_title.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | -------------------------------------------------------------------------------- /watermark/WatermarkActivity.java: -------------------------------------------------------------------------------- 1 | package eebochina.com.testtechniques.watermark; 2 | 3 | import android.graphics.Color; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.os.Bundle; 6 | import android.support.v7.widget.LinearLayoutManager; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.TextView; 12 | import android.widget.Toast; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | import eebochina.com.testtechniques.R; 18 | import eebochina.com.testtechniques.nestedScroll.NestedScrollActivity; 19 | 20 | public class WatermarkActivity extends AppCompatActivity { 21 | 22 | private RecyclerView mRecyclerView; 23 | private LayoutInflater mInflater; 24 | private List mContentDatas; 25 | 26 | @Override 27 | protected void onCreate(Bundle savedInstanceState) { 28 | super.onCreate(savedInstanceState); 29 | setContentView(R.layout.activity_watermark); 30 | mInflater = LayoutInflater.from(this); 31 | mRecyclerView = (RecyclerView) findViewById(R.id.watermark_content); 32 | 33 | mContentDatas = new ArrayList<>(); 34 | final LinearLayoutManager contentManager = new LinearLayoutManager(this); 35 | contentManager.setOrientation(LinearLayoutManager.VERTICAL); 36 | mRecyclerView.setLayoutManager(contentManager); 37 | for (int i = 0; i < 50; i++) { 38 | mContentDatas.add("测试水印" + i); 39 | } 40 | mRecyclerView.setAdapter(new ContentAdapter()); 41 | setWatermark(); 42 | } 43 | 44 | private WatermarkDecoration mWatermarkDecoration; 45 | 46 | private void setWatermark() { 47 | // WatermarkDecoration.Builder builder = new WatermarkDecoration.Builder("单个水印") 48 | // .setColumnNum(3) 49 | // .setTextColor(Color.GRAY) 50 | // .setTextSize(35); 51 | //多个水印 52 | WatermarkDecoration.Builder builder = new WatermarkDecoration.Builder(getMultiple()) 53 | .setColumnNum(3) 54 | .setTextColor(Color.GRAY) 55 | .setTextSize(35); 56 | 57 | mWatermarkDecoration = builder.builder(); 58 | 59 | mRecyclerView.addItemDecoration(mWatermarkDecoration); 60 | mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { 61 | @Override 62 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 63 | super.onScrolled(recyclerView, dx, dy); 64 | //设置水印滚动位置 65 | mWatermarkDecoration.setScrollY(dy); 66 | } 67 | }); 68 | } 69 | 70 | private List getMultiple() { 71 | List strings = new ArrayList<>(); 72 | for (int i = 0; i < 10; i++) { 73 | strings.add("多个水印" + i); 74 | } 75 | return strings; 76 | } 77 | 78 | class ContentAdapter extends RecyclerView.Adapter { 79 | @Override 80 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 81 | return new ContentViewHolder(mInflater.inflate(R.layout.item_layout, parent, false)); 82 | } 83 | 84 | @Override 85 | public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { 86 | final ContentViewHolder viewHolder = (ContentViewHolder) holder; 87 | viewHolder.mTextView.setText(mContentDatas.get(position)); 88 | 89 | } 90 | 91 | @Override 92 | public int getItemCount() { 93 | return mContentDatas.size(); 94 | } 95 | } 96 | 97 | class ContentViewHolder extends RecyclerView.ViewHolder { 98 | private TextView mTextView; 99 | 100 | public ContentViewHolder(View itemView) { 101 | super(itemView); 102 | mTextView = (TextView) itemView.findViewById(R.id.item_layout_text); 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /watermark/WatermarkDecoration.java: -------------------------------------------------------------------------------- 1 | package eebochina.com.testtechniques.watermark; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Color; 5 | import android.graphics.ColorFilter; 6 | import android.graphics.Paint; 7 | import android.graphics.PixelFormat; 8 | import android.graphics.Rect; 9 | import android.graphics.drawable.Drawable; 10 | import android.support.annotation.ColorInt; 11 | import android.support.annotation.NonNull; 12 | import android.support.annotation.Nullable; 13 | import android.support.v7.widget.RecyclerView; 14 | 15 | import java.util.List; 16 | 17 | /** 18 | * recyclerView 添加水印 19 | */ 20 | 21 | public class WatermarkDecoration extends RecyclerView.ItemDecoration { 22 | 23 | WatermarkParams mWatermarkParams; 24 | WaterMarkDrawable mDrawable; 25 | int mScrollY = 0; 26 | int mListDrawTextSize = -1; 27 | 28 | private WatermarkDecoration(WatermarkParams mWatermarkParams) { 29 | this.mWatermarkParams = mWatermarkParams; 30 | mDrawable = new WaterMarkDrawable(); 31 | mListDrawTextSize = mWatermarkParams.mDrawTexts != null 32 | ? mWatermarkParams.mDrawTexts.size() : -1; 33 | } 34 | 35 | @Override 36 | public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { 37 | super.onDraw(c, parent, state); 38 | int top = -mScrollY; 39 | int right = parent.getWidth() / mWatermarkParams.mColumnNum; 40 | int start = Math.abs(mScrollY / mWatermarkParams.mRowHeight); 41 | int max = (parent.getHeight() + mScrollY) / mWatermarkParams.mRowHeight + 1; 42 | for (int i = start; i < max; i++) { 43 | int tempTop = top + (mWatermarkParams.mRowHeight * start); 44 | int tempLeft = right / 3; 45 | for (int j = 0; j < mWatermarkParams.mColumnNum; j++) { 46 | mDrawable.setBounds(tempLeft, top, tempLeft + right, tempTop + mWatermarkParams.mRowHeight); 47 | if (mListDrawTextSize == -1) { 48 | mDrawable.setDrawTex(mWatermarkParams.mDrawText); 49 | } else { 50 | mDrawable.setDrawTex(mWatermarkParams.mDrawTexts.get((i * mWatermarkParams.mColumnNum + j) % mListDrawTextSize)); 51 | } 52 | mDrawable.draw(c); 53 | tempLeft += right; 54 | } 55 | top += mWatermarkParams.mRowHeight; 56 | } 57 | 58 | } 59 | 60 | //跟踪recyclerView 滚动值 61 | public void setScrollY(int dy) { 62 | this.mScrollY += dy; 63 | } 64 | 65 | class WaterMarkDrawable extends Drawable { 66 | 67 | Paint mPaint; 68 | String mTempText; 69 | 70 | public WaterMarkDrawable() { 71 | mPaint = new Paint(); 72 | mPaint.setColor(mWatermarkParams.mTextColor); 73 | mPaint.setTextSize(mWatermarkParams.mTextSize); 74 | mPaint.setAlpha((int) (255 * mWatermarkParams.mAlpha)); 75 | mPaint.setAntiAlias(true); 76 | mPaint.setTextAlign(Paint.Align.LEFT); 77 | } 78 | 79 | @Override 80 | public void draw(@NonNull Canvas canvas) { 81 | Rect rect = getBounds(); 82 | canvas.save(); 83 | canvas.rotate(mWatermarkParams.mDegrees, rect.left, rect.bottom); 84 | canvas.drawText(mTempText, rect.left, rect.bottom, mPaint); 85 | canvas.restore(); 86 | } 87 | 88 | @Override 89 | public void setAlpha(int alpha) { 90 | 91 | } 92 | 93 | @Override 94 | public void setColorFilter(@Nullable ColorFilter colorFilter) { 95 | 96 | } 97 | 98 | @Override 99 | public int getOpacity() { 100 | return PixelFormat.UNKNOWN; 101 | } 102 | 103 | public void setDrawTex(String mDrawTex) { 104 | this.mTempText = mDrawTex; 105 | } 106 | } 107 | 108 | public static class Builder { 109 | private WatermarkParams mWatermarkParams; 110 | 111 | //水印背景字符 112 | public Builder(String drawText) { 113 | mWatermarkParams = new WatermarkParams(drawText); 114 | } 115 | 116 | //多个水印背景字符 117 | public Builder(List drawTexts) { 118 | mWatermarkParams = new WatermarkParams(drawTexts); 119 | } 120 | 121 | //文字大小 122 | public Builder setTextSize(int textSize) { 123 | mWatermarkParams.mTextSize = textSize; 124 | return this; 125 | } 126 | 127 | //文字颜色 128 | public Builder setTextColor(@ColorInt int textColor) { 129 | mWatermarkParams.mTextColor = textColor; 130 | return this; 131 | } 132 | 133 | //展示多少列 134 | public Builder setColumnNum(int columnNum) { 135 | mWatermarkParams.mColumnNum = columnNum; 136 | return this; 137 | } 138 | 139 | //行高 140 | public Builder setRowHeight(int rowHeight) { 141 | mWatermarkParams.mRowHeight = rowHeight; 142 | return this; 143 | } 144 | 145 | //倾斜角度 146 | public Builder setDegrees(int degrees) { 147 | mWatermarkParams.mDegrees = degrees; 148 | return this; 149 | } 150 | 151 | //透明度 0-1 152 | public Builder setAlpha(float alpha) { 153 | mWatermarkParams.mAlpha = alpha; 154 | return this; 155 | } 156 | 157 | public WatermarkDecoration builder() { 158 | return new WatermarkDecoration(mWatermarkParams); 159 | } 160 | } 161 | 162 | static class WatermarkParams { 163 | String mDrawText; 164 | List mDrawTexts; 165 | int mTextColor = Color.parseColor("#ebebeb"); 166 | int mTextSize = 40; 167 | int mColumnNum = 3; 168 | int mRowHeight = 240; 169 | int mDegrees = -30; 170 | float mAlpha = 0.5f; 171 | 172 | 173 | public WatermarkParams(String mDrawText) { 174 | this.mDrawText = mDrawText; 175 | } 176 | 177 | public WatermarkParams(List mDrawTexts) { 178 | this.mDrawTexts = mDrawTexts; 179 | } 180 | } 181 | } 182 | --------------------------------------------------------------------------------