152:通过setOnTouchListener来给imageview画圆,canvas.scale这一步很重要,不然画出来的圆不准。
paint = new Paint();
paint.setColor(Color.RED);
image.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
bitmap = ConvertUtils.drawable2Bitmap(image.getDrawable()).copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(bitmap);
canvas.scale(canvas.getWidth()/(float) image.getWidth(),canvas.getHeight()/(float) image.getHeight());
canvas.drawCircle(event.getX(),event.getY(),ConvertUtils.dp2px(CeShiActivity.this, 10), paint);
image.setImageBitmap(bitmap);
break;
}
return false;
}
});
153:代码中设置textview字体加粗,就一句代码
textView.setTypeface(Typeface.DEFAULT_BOLD);
154:view中有个draw方法,参数是canvas对象,可以先创建一个bitmap,然后将bitmap作为canvas的画布,最后用view的draw方法将view上面的视图画到canvas上,然后就可以给任意的view制作截图了,代码如下所示:(注意要给TextView设置background才能看到文字和背景,所有的view都可以截图)(已记录)
textView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
bitmap = Bitmap.createBitmap(textView.getWidth(),textView.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
textView.draw(canvas);
canvas.drawCircle(event.getX(),event.getY(),ConvertUtils.dp2px(CeShiActivity.this, 10), paint);
ImageUtil.saveBitmap(Environment.getExternalStorageDirectory()+"/a.jpeg",bitmap);
break;
}
return false;
}
});
webview的代码同上:
webview.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
bitmap = Bitmap.createBitmap(webview.getWidth(),webview.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
webview.draw(canvas);
canvas.drawCircle(event.getX(),event.getY(),ConvertUtils.dp2px(CeShiActivity.this, 10), paint);
ImageUtil.saveBitmap(Environment.getExternalStorageDirectory()+"/a.jpeg",bitmap);
break;
}
return false;
}
});
155:Picture的用法
Picture picture=new Picture();
Canvas canvas=picture.beginRecording(200,200);//开始绘制
Paint paint=new Paint();
paint.setColor(Color.RED);
canvas.drawCircle(100,100,50,paint);
picture.endRecording();//结束绘制
bitmap = Bitmap.createBitmap(picture.getWidth(),picture.getHeight(), Bitmap.Config.ARGB_8888);//创建bitmap,作为canvas的画布
Canvas canvas1=new Canvas(bitmap);
picture.draw(canvas1);//将picture上的内容绘制到canvas的画布上
ImageUtil.saveBitmap(Environment.getExternalStorageDirectory()+"/a.jpeg",bitmap);
156:记录一个异常,在使用SlidingTabLayout时出现卡顿的原因是因为应该用getChildFragmentManager了,因为是在fragment中嵌套了fragment,用SlidingTabLayout的setViewPager(homeViewpager, strings);不要用setViewPager(homeViewpager, strings, activity, list);
157:java.lang.IllegalStateException: FragmentManager is already executing transactions解决方法
https://blog.csdn.net/q1406689423/article/details/66973555
158:scroller的用法
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
scroller.startScroll(100, 100, -200, -200, 5000);//x和y的变化量=初始坐标-最终坐标,x的变化量为负表示向右移,y的变化量为负表示向下移
invalidate();
break;
}
return super.onTouchEvent(event);
}
@Override
public void computeScroll() {
super.computeScroll();
if (scroller.computeScrollOffset()) {
((View) getParent()).scrollTo(scroller.getCurrX(), scroller.getCurrY());
invalidate();
}
}
159:当你给activity在Androidmanifest中设置了android:launchMode="singleTask"后,你按了home键之后,再回到app中,你会发现其他activity已经被关闭了
160:如果在没有用懒加载的情况下,系统会将viewpager的所有fragment中的数据都获取到之后才会展示出来,因此如果不用懒加载的话,而且fragment还特别多的话会非常卡。
161:系统自带的ListView就可以添加头布局和尾布局,但是添加了头和尾之后,系统会将BaseAdapter转换为HeaderViewListAdapter,要刷新适配器的话,需要再将HeaderViewListAdapter转换为BaseAdapter。
https://1028826685.iteye.com/blog/1464489
162:ScrollView嵌套RecyclerView时只显示一行元素的解决方法:
用NestedScrollView代替ScrollView,然后设置RecyclerView的属性nestedScrollingEnabled="false",最后RecyclerView的item的高度必须是具体的值才行,不能是match_parent。
163:两种滚动的方式:
第一种:
@Override
public boolean onTouchEvent(MotionEvent event) {
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
if (!scroller.isFinished()) {
scroller.abortAnimation();
}
int deltaY = (yLater - y)*20;
scroller.startScroll(0, getScrollY(), 0, deltaY);
invalidate();
break;
}
yLater = y;
return true;
}
@Override
public void computeScroll() {
Log.e("computeScroll", "computeScroll: " + scroller.getCurrX() + "," + scroller.getCurrY());
if (scroller.computeScrollOffset()) {
scrollTo(scroller.getCurrX(), scroller.getCurrY());
invalidate();
}
}
第二种:
@Override
public boolean onTouchEvent(MotionEvent event) {
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
if (!scroller.isFinished()) {
scroller.abortAnimation();
}
int deltaY = (yLater - y);
scrollBy(0,deltaY);
invalidate();
break;
}
yLater = y;
return true;
}
心得:在Android中画布是无限大的,view的大小是显示画布的区域,每个view都在各自的画布上面,但是画布之间有这父子关系,父画布上移动自己的画布就相当于在移动所有与父画布相关联的子画布,并且子画布的显示范围受父画布的显示范围影响,超出父画布的显示范围子画布将不会被显示,层层画布叠在一起,每个view的大小和位置就是各自在各自画布中要显示的大小和位置。scrollTo和scrollBy是移动了画布的位置,而不是view的位置。如果是列表类型的viewgroup,比如listview,gridview,recyclerview是不能单纯的用scrollTo和scrollBy来移动内容的,因为它们都有自己的复用机制。
getScrollY()获取到的是子view的左上角相对于父view的左上角(也就是(0,0)点)的y坐标的变化量(父view的左上角的纵坐标(也就是(0,0)点)-子view的左上角的当前纵坐标),变化量为正表示向上划,为负表示向下划。getScrollX()同理。另外滚动后要调用invalidate(),目的是为了调用view的onDraw方法来重新绘制view的布局,这样才能及时更新view的位置。
scroller.startScroll方法的第三个参数和第四个参数
* @param dx Horizontal distance to travel. Positive numbers will scroll the
* content to the left.
* @param dy Vertical distance to travel. Positive numbers will scroll the
* content up.
第三个参数如果是正数表示向左滑动,第四个参数如果是正数表示向上滑动。当然也可以根据:位置变化量=开始位置-最终位置来推出来。
VelocityTracker的使用,最终通过scroller来实现平滑滚动。
@Override
public boolean onTouchEvent(MotionEvent event) {
int y = (int) event.getY();
if (velocityTracker == null)
velocityTracker = VelocityTracker.obtain();
velocityTracker.addMovement(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
if (!scroller.isFinished()) {
scroller.abortAnimation();
}
int deltaY = (yLater - y);
scrollBy(0, deltaY);
invalidate();
break;
case MotionEvent.ACTION_UP:
velocityTracker.computeCurrentVelocity(1000);
if (Math.abs(velocityTracker.getYVelocity()) > 8000) {
if (velocityTracker.getYVelocity() > 0)
scroller.startScroll(0, getScrollY(), 0, -300, 1000);
else
scroller.startScroll(0, getScrollY(), 0, 300, 1000);
invalidate();
}
velocityTracker.recycle();
velocityTracker = null;
break;
}
yLater = y;
return true;
}
@Override
public void computeScroll() {
if (scroller.computeScrollOffset()) {
scrollTo(scroller.getCurrX(), scroller.getCurrY());
invalidate();
}
}
164:利用Scroller和VelocityTracker将LinearLayout改造成ScrollerView
public class MyScrollView extends LinearLayout {
private Scroller scroller;
private int yLater;
private VelocityTracker velocityTracker;
public MyScrollView(Context context) {
this(context, null, 0);
}
public MyScrollView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
scroller = new Scroller(context);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int y = (int) event.getY();
if (velocityTracker == null)
velocityTracker = VelocityTracker.obtain();
velocityTracker.addMovement(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
if (!scroller.isFinished()) {
scroller.abortAnimation();
}
int deltaY = (yLater - y);
scrollBy(0, deltaY);
invalidate();
break;
case MotionEvent.ACTION_UP:
velocityTracker.computeCurrentVelocity(1000);
if (Math.abs(velocityTracker.getYVelocity()) > 8000) {
if (velocityTracker.getYVelocity() > 0)
scroller.startScroll(0, getScrollY(), 0, -300, 1000);
else
scroller.startScroll(0, getScrollY(), 0, 300, 1000);
invalidate();
}
velocityTracker.recycle();
velocityTracker = null;
break;
}
yLater = y;
return true;
}
@Override
public void computeScroll() {
Log.e("computeScroll", "computeScroll: " + scroller.getCurrX() + "," + scroller.getCurrY());
if (scroller.computeScrollOffset()) {
scrollTo(scroller.getCurrX(), scroller.getCurrY());
invalidate();
}
}
}
165:SparseArray和ArrayList,如果这两个类中都没有任何一个元素,都调用get(0)方法,SparseArray不会崩,但是ArrayList会崩(java.lang.IndexOutOfBoundsException: Index: 0, Size: 0)。
166:设置dialog透明的方式
<style name="dialog" parent="@android:style/Theme.Dialog">
<item name="android:windowFrame">@null</item><!--边框-->
<item name="android:windowIsFloating">true</item><!--是否浮现在activity之上-->
<item name="android:windowIsTranslucent">false</item><!--半透明-->
<item name="android:windowNoTitle">true</item><!--无标题-->
<item name="android:windowBackground">@color/transparent</item><!--背景透明-->
<item name="android:backgroundDimEnabled">false</item><!--模糊-->
</style>
https://www.cnblogs.com/windlivefamily/articles/2133956.html
167:设置toolbar的menu的三个点为白色的方法
<style name="Theme.ToolBar.Menu" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
<!-- 设置-弹窗的背景-颜色-->
<item name="android:colorBackground">@color/common_bg</item>
<!-- 字体的颜色-->
<item name="android:textColor">@color/common_h1</item>
<!-- 字体大小-->
<item name="android:textSize">16sp</item>
<!-- 用于替换菜单的三个小白点,换成自已的图片-->
<item name="actionOverflowButtonStyle">@style/ActionButton.Overflow.Menu</item>
<!--用于控制menu弹出的位置,位于toolbar的下面,而不是上面-->
<item name="actionOverflowMenuStyle">@style/OverflowMenuStyle</item>
<!-- 用于修改item默认的分割线-->
<item name="android:dropDownListViewStyle">@style/dropDownStyle</item>
<item name="dropDownListViewStyle">@style/dropDownStyle</item>
</style>
<style name="ActionButton.Overflow.Menu" parent="android:style/Widget.Holo.Light.ActionButton.Overflow">
<item name="android:src">@drawable/abc_ic_menu_moreoverflow_mtrl_alpha</item>
</style>
168:一个申请权限的框架
https://github.com/getActivity/XXPermissions
169:自定义layoutmanager,示例代码如下:
public class MyLayoutManager extends RecyclerView.LayoutManager {
private int mDecoratedChildWidth;
private int mDecoratedChildHeight;
private int offset;
private SparseArray<Rect> rectList;
public MyLayoutManager(Context context) {
rectList = new SparseArray<>();
}
@Override
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
return new RecyclerView.LayoutParams(RecyclerView.LayoutParams.WRAP_CONTENT, RecyclerView.LayoutParams.WRAP_CONTENT);
}
@Override
public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
offset += dy;
if (offset < 0) {
offset = 0;
return 0;
}
if (offset > (getItemCount() * mDecoratedChildHeight - getVerticalSpace())) {
offset = getItemCount() * mDecoratedChildHeight - getVerticalSpace();
return 0;//在scrollVerticallyBy方法中return 0会在recyclerview中出现椭圆动画
}
layoutChidren(recycler,state);//判断偏移量是否小于0或大于屏幕高度的代码必须放在重新绘制子view代码的前面,offsetChildrenVertica方法必须放在重新绘制子view代码的后面。
offsetChildrenVertical(-offset);//将子view在垂直方向上进行滚动
return dy;
}
@Override
public boolean canScrollVertically() {
return true;
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
super.onLayoutChildren(recycler, state);
int left = 0, pianyi = 0;
for (int i = 0; i < state.getItemCount(); i++) {
View view = recycler.getViewForPosition(i);
measureChildWithMargins(view, 0, 0);
mDecoratedChildWidth = getDecoratedMeasuredWidth(view);
mDecoratedChildHeight = getDecoratedMeasuredHeight(view);
Rect rect = rectList.get(i);
if (rect == null) {
rect = new Rect();
}
rect.set(left, pianyi, left + mDecoratedChildWidth, pianyi + mDecoratedChildHeight);
rectList.put(i, rect);
pianyi += mDecoratedChildHeight;
}
layoutChidren(recycler,state);
}
private void layoutChidren(RecyclerView.Recycler recycler, RecyclerView.State state) {
detachAndScrapAttachedViews(recycler);
Rect parent = new Rect(0, offset, getHorSpace(), offset + getVerticalSpace());
for (int i = 0; i < state.getItemCount(); i++) {
if (Rect.intersects(parent, rectList.get(i))) {
View view = recycler.getViewForPosition(i);
measureChildWithMargins(view, 0, 0);
addView(view);
layoutDecorated(view, 0, rectList.get(i).top, rectList.get(i).right, rectList.get(i).bottom);
}
}
for (int i = 0; i < recycler.getScrapList().size(); i++) {
RecyclerView.ViewHolder viewHolder=recycler.getScrapList().get(i);
removeView(viewHolder.itemView);
recycler.recycleView(viewHolder.itemView);
}
/* Rect childFrame = new Rect();
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
childFrame.left = getDecoratedLeft(child);
childFrame.top = getDecoratedTop(child);
childFrame.right = getDecoratedRight(child);
childFrame.bottom = getDecoratedBottom(child);
//如果Item没有在显示区域,就说明需要回收
if (!Rect.intersects(parent, childFrame)) {
//回收掉滑出屏幕的View
removeAndRecycleView(child, recycler);
}
}*/
}
private int getVerticalSpace() {
return getHeight() - getPaddingBottom() - getPaddingTop();
}
private int getHorSpace() {
return getWidth() - getPaddingLeft() - getPaddingRight();
}
@Override
public void onLayoutCompleted(RecyclerView.State state) {
super.onLayoutCompleted(state);
LogUtils.e("MyLayoutManager", "布局完成");
}
}