[Android] TextView中setPadding()方法失效,不起作用

项目中使用了一个第三方控件,很多人都有用过,PagerSlidingTabStrip,发现在4.4(Kitkat)之前的版本,每个tab会挤在一起,分析源码后,发现每个tab在设置了setPadding后根本就无效,网上一查,还真有坑。

原因是在每个tab调用了setPadding后,又在其他地方调用了setBackgroundResource(),这在4.4之前是有问题的,4.4及以后的版本google已经fix了这个bug。

// does not work
tv.setPadding(20, 20, 20, 20);
tv.setBackgroundResource(R.drawable.border);

// works
tv.setBackgroundResource(R.drawable.border);
tv.setPadding(20, 20, 20, 20);

所以,解决办法是,必须在setBackgroundResource之后调用setPadding()方法。

[Android] Expand a RecyclerView in Four Steps

转自:https://www.bignerdranch.com/blog/expand-a-recyclerview-in-four-steps/?utm_source=Android+Weekly&utm_campaign=8f0cc3ff1f-Android_Weekly_165&utm_medium=email&utm_term=0_4eb677ad19-8f0cc3ff1f-337834121

The Expandable RecyclerView library is a lightweight library that simplifies the inclusion of expandable dropdown rows in your RecyclerView. In it, you have two types of views. The parent view is the one visible by default, and it contains the children. The child view is the one that is expanded or collapsed, and will appear when a parent item is clicked.

In this post, we will implement the Expandable RecyclerView in the CriminalIntent application from our Android programming guide. We’ll be showing a more detailed view of each crime from the main list fragment.

You can view the source code for the library and two samples on GitHub, or read the Javadocs.

Not familiar with RecyclerView? Bill Phillips has written two excellent blog posts on the subject.

Let’s Get it Working

Our completed demo will look like this:

Expandable CriminalIntent

Start by adding these two dependencies to your app’s build.gradle file:

dependencies {
    compile 'com.android.support:recyclerview-v7:22.2.0'
    compile 'com.bignerdranch.android:expandablerecyclerview:1.0.3'
}

All expanding and collapsing functionality is handled in the adapter, meaning that your RecyclerView is just a stock RecyclerView. All you’ll need to do to set up the Expandable RecyclerView in a layout is add a stock RecyclerView to your activity or fragment’s XML layout.

1. The ViewHolders

First, let’s create the XML layouts for our parent and child views. Our parent layout is going to include the title of the crime and a dropdown arrow to display an animation when the item is expanded or collapsed. We’ll call this layout list_item_crime_parent.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#dbdbda">

    <TextView
        android:id="@+id/parent_list_item_crime_title_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="16dp"
        android:textStyle="bold"
        android:text="Crime Title" />

    <ImageButton
        android:id="@+id/parent_list_item_expand_arrow"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_margin="8dp"
        android:src="@android:drawable/arrow_down_float" />

</RelativeLayout>

Now, onto the child layout. The child is going to contain a TextView that shows the date of the crime and a checkbox that we can click when the crime is solved. We’ll call this layout list_item_crime_child.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#cbcbcb">

    <TextView
        android:id="@+id/child_list_item_crime_date_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="8dp"
        android:text="Crime Date" />

    <CheckBox
        android:id="@+id/child_list_item_crime_solved_check_box"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_marginRight="8dp"
        android:text="Solved" />

</RelativeLayout>

Now that we have both of our layouts ready, let’s set up each ViewHolder. We will create a class called CrimeParentViewHolder that extends ParentViewHolder and another class called CrimeChildViewHolder that extends ChildViewHolder.

Let’s start with CrimeParentViewHolder. Go ahead and create a public TextView and ImageButton variable for our two views, like so:

public class CrimeParentViewHolder extends ParentViewHolder {

    public TextView mCrimeTitleTextView;
    public ImageButton mParentDropDownArrow;

    public CrimeParentViewHolder(View itemView) {
        super(itemView);

        mCrimeTitleTextView = (TextView) itemView.findViewById(R.id.parent_list_item_crime_title_text_view);
        mParentDropDownArrow = (ImageButton) itemView.findViewById(R.id.parent_list_item_expand_arrow);
    }
}

Now, onto our CrimeChildViewHolder. We’re again going to create two public variables for our views, but this time one will be a TextView and one will be a CheckBox:

public class CrimeChildViewHolder extends ChildViewHolder {

    public TextView mCrimeDateText;
    public CheckBox mCrimeSolvedCheckBox;

    public CrimeChildViewHolder(View itemView) {
        super(itemView);

        mCrimeDateText = (TextView) itemView.findViewById(R.id.child_list_item_crime_date_text_view);
        mCrimeSolvedCheckBox = (CheckBox) itemView.findViewById(R.id.child_list_item_crime_solved_check_box);
    }
}

Now let’s set up our parent and child objects.

2. Parents and Their Children

For our CriminalIntent example, the data that we want to display in our list items are fields of our Crime object. Since we have both a parent and a child layout, the best practice is to create a child object, separate from the parent, to hold the data that will be displayed in the child.

In this case, our parent object will be the Crime object itself. Let’s make our Crime object implement ParentObject. Implement the getter and setter methods with a list variable:

public class Crime implements ParentObject {

    /* Create an instance variable for your list of children */
    private List<Object> mChildrenList;

    /**
     * Your constructor and any other accessor
     *  methods should go here.
     */

    @Override
    public List<Object> getChildObjectList() {
        return mChildrenList;
    }

    @Override
    public void setChildObjectList(List<Object> list) {
        mChildrenList = list;
    }
}

The expandable RecyclerView allows for multiple children or none, so the children need to be added as a list. You can either add the children directly in the getChildObjectList method we implemented by returning your List of children, or you can add them when we create the list of items by calling setChildObjectList with the list of respective children. I will be doing the latter in this demo.

Our child object will hold two values, a String for the date and a boolean for the solved flag:

public class CrimeChild {

    private Date mDate;
    private boolean mSolved;

    public CrimeChild(Date date, boolean solved) {
        mDate = date;
        mSolved = solved;
    }

    /**
     * Getter and setter methods
     */
}

We’ll populate each parent object with children in the final step. Now, let’s get the adapter working!

3. The Adapter

We’re going need to implement a custom adapter that extends ExpandableRecyclerAdapter. Inside our adapter, we will implement a few methods so we can populate the data in our ViewHolders.

First, let’s create a class and call it CrimeExpandableAdapter. Make it extend ExpandableRecyclerAdapter and give it our two ViewHolder type parameters in the order of <parent view holder, child view holder>. Our header will look like this:

public class CrimeExpandableAdapter extends ExpandableRecyclerAdapter<CrimeParentViewHolder, CrimeChildViewHolder> {

You’ll need to implement the four inherited methods, onCreateParentViewHolder, onBindParentViewHolder, onCreateChildViewHolder and onBindChildViewHolder. Go ahead and implement the default constructor that will take in a Context and a List of ParentObjects.

In our constructor, let’s get access to the LayoutInflater and call it mInflater. This will be used in our onCreateParentViewHolder and onCreateChildViewHolder to inflate the layouts we created earlier. In our constructor, add mInflater = LayoutInflater.from(context);. This will create a layout inflater for us.

Now, let’s create our views and add them to the custom ViewHolders we made earlier. In onCreateParentViewHolder, let’s replace the return null line with these two lines:

View view = mInflater.inflate(R.layout.list_item_crime_parent, viewGroup, false);
return new CrimeParentViewHolder(view);

Let’s now do the same as we did in onCreateParentViewHolder, but adjust for our CrimeChildViewHolder. Again, replace return null with these two lines, but this time in onCreateChildViewHolder:

View view = mInflater.inflate(R.layout.list_item_crime_child, viewGroup, false);
return new CrimeChildViewHolder(view);

To finish off our adapter, let’s work on our onBindViewHolder methods, starting with onBindParentViewHolder. In onBindParentViewHolder, three variables are passed in: the viewholder we created in onCreateParentViewHolder, the position of the item and the parent object associated with that position. We’re going to need to cast the passed parent object to our parent object type (which, as you recall, is our Crime object). Let’s make our onBindParentViewHolder look like this:

public void onBindParentViewHolder(CrimeParentViewHolder crimeParentViewHolder, int i, Object parentObject) {
    Crime crime = (Crime) parentObject;
    crimeParentViewHolder.mCrimeTitleTextView.setText(crime.getTitle());
}

Finally, we will set up our CrimeChildViewHolder. Recall that our CrimeChildViewHolder contains a TextView for a date and a CheckBox to indicate whether the crime is solved. Our onBindChildViewHolder will look like this:

public void onBindChildViewHolder(CrimeChildViewHolder crimeChildViewHolder, int i, Object childObject) {
    CrimeChild crimeChild = (CrimeChild) childObject;
    crimeChildViewHolder.mCrimeDateText.setText(crimeChild.getDate().toString());
    crimeChildViewHolder.mCrimeSolvedCheckBox.setChecked(crimeChild.isSolved());
}

Now our adapter is ready to roll. Let’s finish this all up!

4. Tying it all together

Let’s head back to our main fragment, where we are hosting the RecyclerView. Make sure you find the RecyclerView in your layout and set its layout manager to a new LinearLayoutManager.

I went ahead and created a simple method to generate each of our Crime objects and attach their children. You can add this method in your Fragment:

private ArrayList<ParentObject> generateCrimes() {
    CrimeLab crimeLab = CrimeLab.get(getActivity());
    List<Crime> crimes = crimeLab.getCrimes();
    ArrayList<ParentObject> parentObjects = new ArrayList<>();
    for (Crime crime : crimes) {
        ArrayList<Object> childList = new ArrayList<>();
        childList.add(new CrimeChild(crime.getDate(), crime.isSolved()));
        crime.setChildObjectList(childList);
        parentObjects.add(crime);
    }
    return parentObjects;
}

Another option is to create a new list of children directly in your Crime object and set that to be the childrenList. A third option would be to create a list of children in getChildObjectList and return that list.

Now we can add the following lines to our onCreateView method:

CrimeExpandableAdapter mCrimeExpandableAdapter = new CrimeExpandableAdapter(getActivity(), generateCrimes());
mCrimeExpandableAdapter.setCustomParentAnimationViewId(R.id.parent_list_item_expand_arrow);
mCrimeExpandableAdapter.setParentClickableViewAnimationDefaultDuration();
mCrimeExpandableAdapter.setParentAndIconExpandOnClick(true);

Note that the list you pass into your adapter must be of the type ParentObject.

The setCustomParentAnimationView allows for the arrow in the parent layout to rotate on expand/collapse and setParentClickableAnimationDefaultDuration gives it a default rotation time of 200 milliseconds. setParentAndIconExpandOnClick ensures that we can click both the parent and the arrow to expand the item. You can always remove these if you don’t want an animation or custom triggering view.

Finally, set the RecyclerView’s adapter to finish it up:

mCrimeRecyclerView.setAdapter(mCrimeExpandableAdapter);

That’s it! You now should have a RecyclerView that expands and collapses and has a nice rotation animation to go along with it.

Want to improve it or see more?

The library is open source, so visit the project’s GitHub page to see all the source code, then send a pull request if there are new features you’d like to add.

*Ryan Brooks was an Android intern this summer. Apply now to join our team as an intern in Fall 2015.

[Android]Service可以显示对话框?

嗯,总有一些莫名其妙的需求,不过,仔细一想,这种情况还是存在的,比如手机电量低时,会弹出一个警告对话框,还有闹钟也会弹对话框,好,那就看看怎么来实现吧。

1.让service启动一个activity,该activity实际上是一个dialog类型,设置theme如下:

android:theme="@android:style/Theme.Dialog"

有个开源项目android-smspopup就是用的这个方法。

2.不使用activity

AlertDialog alertDialog = new AlertDialog.Builder(this)
                    .setTitle("Title")
                    .setMessage("Are you sure?")
                    .create();

alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
alertDialog.show();

在manifest里要用到一个权限:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

3. 基本上以上两个办法就可以了,更详细的讨论可以参考下这篇文章

 

Android自定义View实现左右滑动选择出生年份

转自:http://www.jb51.net/article/86071.htm

模仿的是微博运动界面的个人出生日期设置view,先看看我的效果图:

支持设置初始年份,左右滑动选择出生年份,对应的TextView的值也会改变。这个动画效果弄了好久,感觉还是比较生硬,与微博那个还是有点区别。大家有改进的方案,欢迎一起交流。

自定义View四部曲,这里依旧是这个套路,看看怎么实现的。

1.自定义view的属性:
在res/values/ 下建立一个attrs.xml , 在里面定义我们的属性以及声明我们的整个样式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>
<resources>
 //自定义属性名,定义公共属性
 <attr name="titleSize" format="dimension"></attr>
 <attr name="titleText" format="string"></attr>
 <attr name="titleColor" format="color"></attr>
 <attr name="outCircleColor" format="color"></attr>
 <attr name="inCircleColor" format="color"></attr>
 <attr name="lineColor" format="color"></attr>
 <declare-styleable name="MyScrollView">
  <attr name="titleSize"></attr>
  <attr name="titleColor"></attr>
  <attr name="lineColor"></attr>
 </declare-styleable>
</resources>

依次定义了字体大小,字体颜色,线的颜色3个属性,format是值该属性的取值类型。
然后就是在布局文件中申明我们的自定义view:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<TextView
 android:id="@+id/year_txt"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_margin="30dp"
 android:text="出生年份 (年)"
 android:textSize="20dp" />
<com.example.tangyangkai.myview.MyScrollView
 android:id="@+id/scroll_view"
 android:layout_width="match_parent"
 android:layout_height="70dp"
 myscroll:lineColor="@color/font_text"
 myscroll:titleColor="@color/strong"
 myscroll:titleSize="30dp">
</com.example.tangyangkai.myview.MyScrollView>

自定义view的属性我们可以自己进行设置,记得最后要引入我们的命名空间,
xmlns:app=”http://schemas.Android.com/apk/res-auto”

2.获取自定义view的属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public MyScrollView(Context context) {
 this(context, null);
}
public MyScrollView(Context context, AttributeSet attrs) {
 this(context, attrs, 0);
}
public MyScrollView(final Context context, AttributeSet attrs, int defStyleAttr) {
 super(context, attrs, defStyleAttr);
 //获取我们自定义的样式属性
 TypedArray array = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyScrollView, defStyleAttr, 0);
 int n = array.getIndexCount();
 for (int i = 0; i < n; i++) {
  int attr = array.getIndex(i);
  switch (attr) {
   case R.styleable.MyScrollView_lineColor:
    // 默认颜色设置为黑色
    lineColor = array.getColor(attr, Color.BLACK);
    break;
   case R.styleable.MyScrollView_titleColor:
    textColor = array.getColor(attr, Color.BLACK);
    break;
   case R.styleable.MyScrollView_titleSize:
    // 默认设置为16sp,TypeValue也可以把sp转化为px
    textSize = array.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
      TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));
    break;
  }
 }
 array.recycle();
 init();
}
private void init() {
 //初始化
 mPaint = new Paint();
 mPaint.setAntiAlias(true);
 mBound = new Rect();
 mTxtBound = new Rect();
 bigTxtSize = textSize;
 oneSize = textSize - 15;
 thirdSize = textSize - 15;
}

自定义View一般需要实现一下三个构造方法,这三个构造方法是一层调用一层的,属于递进关系。因此,我们只需要在最后一个构造方法中来获得View的属性以及进行一些必要的初始化操作。尽量不要在onDraw的过程中去实例化对象,因为这是一个频繁重复执行的过程,new是需要分配内存空间的,如果在一个频繁重复的过程中去大量地new对象会造成内存浪费的情况。

3.重写onMesure方法确定view大小:

上一篇自定义View的文章介绍的很详细,这里就不重复了,重点放在onDraw方法里面:
Android自定义View仿微博运动积分动画效果

4.重写onDraw方法进行绘画:

之前说过对于比较复杂的自定义View,重写onDraw方法之前,首先在草稿本上将大致的样子画出来,坐标,起始点都可以简单标注一下。这个方法很实用,思路很清晰。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
 int action = ev.getAction();
 int x = (int) ev.getX();
 int y = (int) ev.getY();
 switch (action) {
  case MotionEvent.ACTION_DOWN:
   xDown = x;
   yDown = y;
   break;
  case MotionEvent.ACTION_MOVE:
   xMove = x;
   yMove = y;
   dx = xMove - xDown;
   int dy = yMove - yDown;
   //如果是从左向右滑动
   if (xMove > xDown && Math.abs(dx) > mTouchSlop * 2 && Math.abs(dy) < mTouchSlop) {
    state = 1;
   }
   //如果是从右向左滑动
   if (xMove < xDown && Math.abs(dx) > mTouchSlop * 2 && Math.abs(dy) < mTouchSlop) {
    state = 2;
   }
   break;
  case MotionEvent.ACTION_UP:
   break;
 }
 return super.dispatchTouchEvent(ev);
}

重写View的dispatchTouchEvent方法来区别左右滑动,mTouchSlop是Android默认的滑动最小距离,如果水平方向滑动的距离大于竖直方向滑动的距离,就判断为水平滑动。这里为了不让滑动那么明显,我让水平滑动的距离大于默认距离的两倍才判定左右滑动。state是记录滑动的状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@Override
public boolean onTouchEvent(MotionEvent ev) {
 int action = ev.getAction();
 switch (action) {
  case MotionEvent.ACTION_DOWN:
   break;
  case MotionEvent.ACTION_MOVE:
   if (state == 1 && bigTxtSize - oneSize > -15) {
    bigTxtSize = bigTxtSize - 1;
    oneSize = oneSize + 1;
    postInvalidate();
   }
   if (state == 2 && bigTxtSize - thirdSize > -15) {
    bigTxtSize = bigTxtSize - 1;
    thirdSize = thirdSize + 1;
    postInvalidate();
   }
   break;
  case MotionEvent.ACTION_UP:
   if (state == 1) {
    size = size - 1;
    bigTxtSize = textSize;
    oneSize = textSize - 15;
    postInvalidate();
    listener.OnScroll(size);
    state = 0;
   }
   if (state == 2) {
    size = size + 1;
    bigTxtSize = textSize;
    thirdSize = textSize - 15;
    postInvalidate();
    listener.OnScroll(size);
    state = 0;
   }
   break;
 }
 return true;
}

重写View的onTouchEvent方法来处理View的点击事件。
(1)演示动态图中,左右滑动的过程中,中间数字会从大变小,左右的数字会从小变大,bigTxtSize代表中间的数字大小,oneSize代表从左到右第二个数字的大小,thirdSize代表从左到右第四个数字的大小。在滑动过程中再使用postInvalidate()方法来一直调用onDraw方法来重新进行绘制,达到数字大小变化的效果。
(2)滑动结束以后进行判断,如果是从左向右滑动,就会将数字减一;如果是从右向左滑动,就会将数字加一。最后将数字大小,滑动状态恢复到默认值。
(3)最后一定要返回true,表示消费当前滑动事件,不然滑动没反应

滑动的操作已经全部处理好,接下来就是绘制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
@Override
protected void onDraw(Canvas canvas) {
 txtSize = size - 2;
 bigText = String.valueOf(size);
 smallText = String.valueOf(txtSize);
 mPaint.setColor(lineColor);
 canvas.drawLine(0, 0, getWidth(), 0, mPaint);
 canvas.drawLine(0, getHeight(), getWidth(), getHeight(), mPaint);
 lineX = getWidth() / 10;
 for (int i = 0; i < 5; i++) {
  if (i == 2) {
   mPaint.setTextSize(bigTxtSize);
   if (bigTxtSize == textSize - 15) {
    mPaint.setColor(lineColor);
    canvas.drawLine(lineX, 0, lineX, getHeight() / 5, mPaint);
   } else {
    mPaint.setColor(textColor);
    canvas.drawLine(lineX, 0, lineX, getHeight() / 3, mPaint);
   }
   mPaint.getTextBounds(bigText, 0, bigText.length(), mBound);
   canvas.drawText(bigText, lineX - mBound.width() / 2, getHeight() / 2 + mBound.height() * 3 / 4, mPaint);
  } else if (i == 0 || i == 4) {
   mPaint.setColor(lineColor);
   mPaint.setTextSize(textSize - 15);
   mPaint.getTextBounds(smallText, 0, smallText.length(), mTxtBound);
   canvas.drawLine(lineX, 0, lineX, getHeight() / 5, mPaint);
   canvas.drawText(String.valueOf(txtSize), lineX - mTxtBound.width() / 2, getHeight() / 2 + mTxtBound.height() * 3 / 4, mPaint);
  } else if (i == 1) {
   mPaint.setTextSize(oneSize);
   if (oneSize == textSize) {
    mPaint.setColor(textColor);
    canvas.drawLine(lineX, 0, lineX, getHeight() / 3, mPaint);
   } else {
    mPaint.setColor(lineColor);
    canvas.drawLine(lineX, 0, lineX, getHeight() / 5, mPaint);
   }
   mPaint.getTextBounds(smallText, 0, smallText.length(), mTxtBound);
   canvas.drawText(String.valueOf(txtSize), lineX - mTxtBound.width() / 2, getHeight() / 2 + mTxtBound.height() * 3 / 4, mPaint);
  } else {
   mPaint.setTextSize(thirdSize);
   if (thirdSize == textSize) {
    mPaint.setColor(textColor);
    canvas.drawLine(lineX, 0, lineX, getHeight() / 3, mPaint);
   } else {
    mPaint.setColor(lineColor);
    canvas.drawLine(lineX, 0, lineX, getHeight() / 5, mPaint);
   }
   mPaint.getTextBounds(smallText, 0, smallText.length(), mTxtBound);
   canvas.drawText(String.valueOf(txtSize), lineX - mTxtBound.width() / 2, getHeight() / 2 + mTxtBound.height() * 3 / 4, mPaint);
  }
  txtSize++;
  lineX += getWidth() / 5;
 }
}

这里其实就是得到滑动操作的数字尺寸大小,然后进行绘制,最后将数字每次加一,lineX是B点的初始位置,每次加上宽度的五分之一。

5.得到当前的设置值
可以看到View上面的TextView也会跟着下面设置的值改变,所以这里我们需要单独处理一下。接口回调,简单暴力的方式。

在onTouchEvent的case MotionEvent.ACTION_UP中,得到最后设置的值

listener.OnScroll(size);

然后就是对应的Activity了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class SecondActivity extends AppCompatActivity implements MyScrollView.OnScrollListener {
 private MyScrollView scrollView;
 private TextView txt;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_second);
  initview();
 }
 private void initview() {
  scrollView = (MyScrollView) findViewById(R.id.scroll_view);
  scrollView.setSize(1992);
  scrollView.setListener(this);
  txt = (TextView) findViewById(R.id.year_txt);
  txt.setText("出生年份" + scrollView.getSize() + " (年)");
 }
 @Override
 public void OnScroll(int size) {
  txt.setText("出生年份" + size + " (年)");
 }
}

实现接口的方法,进行初始化,设置初始值,然后就是在接口的方法更新数据即可。

[Android] 一个全能型Android开发者需要掌握的知识

从09年开始做Android已经7年了,这期间Android的发展和变化是很大的,特别是第三方库很多,而且已经形成了体系,个人要开发一个小的app比以前容易多了,直接调用别人写的好的库,再自己学着搭搭框架,很快一个app就完成了,但如果要想深入理解其中的原理,还是要认真的分析源码,不管是Android的还是第三方库的,最好理解其中的原理。

下面总结了下要开发一个“像样”的App,大概需要掌握的知识,后面还会更新:

%e5%bc%80%e5%8f%91%e6%b5%81%e7%a8%8b